灵符lingfu

soul-symphony-ling

↓ 0 downloads

Soul Symphony — Ling Edition. A spiritual 3D adventure in the soul realm: collect the letters of the world-song, clear the monster lattice, and duel in the arcade arena. Wind Waker-style toon renderer with volumetric light pools, SSAO, bloom and oil-slick tilt-shift — all ling-lang vectors.

Keywords game, 3d, toon, music, soul-symphony
lingfu install soul-symphony-ling
AuthorsLing Lin <taellinglin@gmail.com>
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (1947)

game/scenes/bonus.ling
# Bonus-level herald cutscene — "the leftover note"
# Returns [updatedPrevLine, shouldExit]
#
# สั้น เบา ก่อนเข้าด่านโบนัส (ลูกกลิ้งความเร็วสูง F12): ประตูลับหลังเมนูแตกร้าว
# เผยให้เห็น "โคด้า" — วิญญาณแสงเล็ก ๆ ร่าเริงเกินเหตุ ผู้เป็น "โน้ตที่เหลือ"
# ไม่มีที่ว่างในบทเพลงหลัก จึงมีสนามความเร็วเป็นของตัวเอง วาดแบบโพรซีเยอรัล
# ล้วน (ไม่มีโมเดล .lmesh) — ทรงกลมแกนสว่างสีวนรุ้ง + วงแหวนหางดาวตกวนรอบ
# + เส้นราง loop-de-loop ที่ค่อย ๆ ผุดขึ้นระหว่างบท จบด้วยแฟลชสว่างพุ่งเข้าฉาก
# สกอร์: Seraph.wav (เพลงเซราฟ — โหลดไว้แล้วจาก ch3)

ฟังก์ชัน ฉากโบนัส_บทพูดกลิฟ(ภาษา) {
    ถ้า ภาษา == 0 {
        คืน [
            [24, 15, 16, 18, 26, 23, 12, 25, 25, 21, -1, 11, 21, 8, 3, -1, 19, 12, 20, 29, 26, -1, 17, 16, 25, 8, 16, -1, 20, 21, -1, 26, 24, 15, 16, 23, 21, 4, 20, 16, -1, 15, 8, 16, 11, 11, 21, 3, -1, 18, 26, 23, 16, 18, 26, -1, 21, 22, 26, 20, 5],
            [21, 0, -1, 21, 0, -1, 13, 8, 16, 20, 8, 23, 16, 0, -1, 11, 8, 23, 12, 18, 8, -1, 28, 8, 23, 12, 28, 8, 23, 12, -1, 13, 8, 26, 20, 11, 21, 0],
            [10, 15, 16, 24, 8, 20, 8, -1, 9, 8, 24, 26, 25, 21, -1, 21, 9, 26, -1, 23, 8, 16, 25, 21, 3, -1, 24, 21, 20, 21, -1, 9, 8, 4, 11, 12, -1, 24, 26, 22, 16, 20, 3, -1, 16, 19, 22, 21, 24, 15, 16, 9, 26, 23, 26, -1, 24, 26, 22, 16, 11, 21, 4, 11, 12, -1, 14, 16, 14, 14, 26, 23, 26, 5],
            [28, 8, 23, 12, 28, 8, 23, 12, -1, 18, 21, 11, 8, 0, -1, 24, 21, 20, 14, 26, -1, 20, 21, -1, 20, 8, 18, 8, 3, -1, 11, 8, 23, 12, -1, 19, 21, -1, 23, 26, 19, 26, -1, 20, 8, 18, 8, 25, 25, 8, -1, 23, 16, 13, 26, 25, 21, 9, 8, -1, 20, 21, 25, 21, 0],
            [11, 8, 18, 8, 23, 8, -1, 18, 8, 23, 12, 23, 8, 3, -1, 28, 8, 23, 12, 28, 8, 23, 12, 4, 20, 16, -1, 21, 23, 26, -1, 25, 21, 23, 8, 18, 18, 26, -1, 9, 16, 23, 26, 11, 21, 3, -1, 28, 8, 16, 23, 26, 11, 21, -1, 23, 8, 20, -1, 24, 26, 23, 26, -1, 25, 8, 19, 12, 0],
            [23, 16, 25, 21, 23, 26, -1, 23, 8, 16, 25, 21, 3, -1, 13, 21, 8, 28, 8, 11, 21, -1, 30, 16, 22, 22, 26, 3, -1, 12, 8, 4, 21, -1, 25, 24, 26, 23, 26, -1, 14, 26, 23, 21, 16, 20, 14, 26, -1, 23, 26, 22, 26, -1, 25, 21, 23, 12, 16, 24, 26, 5],
            [15, 21, 22, 22, 26, -1, 16, 20, 3, -1, 15, 21, 22, 22, 26, -1, 16, 20, 0, -1, 19, 21, 19, 12, 20, 25, 8, 19, 26, -1, 28, 12, 16, 25, 21, -1, 24, 15, 16, 20, 8, 16, 3, -1, 28, 8, 23, 12, 28, 8, 23, 12, -1, 19, 21, -1, 24, 15, 16, 20, 8, 16, 0],
            [23, 12, 11, 16, 7, -1, 20, 8, 30, 12, 20, 8, 23, 8, -1, 28, 8, 23, 12, 28, 8, 23, 12, -1, 24, 26, 11, 12, 20, 16, -1, 14, 21, -1, 22, 26, 24, 24, 15, 26, -1, 24, 15, 16, 25, 8, 0],
            [24, 21, 24, 15, 16, 25, 12, -1, 9, 26, 23, 8, 16, 25, 21, 3, -1, 23, 12, 18, 18, 26, 23, 12, 24, 26, -1, 23, 8, 13, 13, 26, 4, 11, 12, 3, -1, 25, 21, 23, 8, 18, 18, 26, -1, 23, 8, 16, 13, 26, 4, 20, 16, -1, 23, 21, 8, 5],
        ]
    }
    ถ้า ภาษา == 1 {
        คืน [
            [13, -1, 31, 17, 15, 30, 17, 32, -1, 16, 27, 27, 30, 4, -1, 20, 21, 16, 16, 17, 26, -1, 14, 17, 20, 21, 26, 16, -1, 32, 20, 17, -1, 25, 17, 26, 33, -1, 21, 32, 31, 17, 24, 18, 4, -1, 15, 30, 17, 13, 23, 31, -1, 27, 28, 17, 26, 6],
            [27, 20, 0, -1, 27, 20, 0, -1, 18, 21, 26, 13, 24, 24, 37, 0, -1, 31, 27, 25, 17, 27, 26, 17, -1, 18, 27, 33, 26, 16, -1, 25, 17, 0],
            [13, -1, 31, 25, 13, 24, 24, -1, 14, 33, 30, 31, 32, -1, 27, 18, -1, 24, 21, 19, 20, 32, -1, 31, 28, 21, 26, 31, -1, 21, 26, -1, 28, 24, 13, 15, 17, 4, -1, 19, 21, 19, 19, 24, 21, 26, 19, -1, 13, 32, -1, 21, 25, 28, 27, 31, 31, 21, 14, 24, 17, -1, 31, 28, 17, 17, 16, 6],
            [21, 1, 25, -1, 15, 27, 16, 13, 0, -1, 32, 20, 17, -1, 24, 17, 18, 32, 27, 34, 17, 30, -1, 26, 27, 32, 17, -1, 26, 27, 14, 27, 16, 37, -1, 20, 13, 16, -1, 30, 27, 27, 25, -1, 18, 27, 30, -1, 21, 26, -1, 32, 20, 17, -1, 31, 27, 26, 19, 0],
            [31, 27, -1, 32, 20, 17, 37, -1, 14, 33, 21, 24, 32, -1, 25, 17, -1, 13, -1, 35, 20, 27, 24, 17, -1, 32, 30, 13, 15, 23, -1, 32, 27, -1, 30, 33, 26, -1, 35, 21, 24, 16, -1, 27, 26, -1, 21, 26, 31, 32, 17, 13, 16, 0],
            [32, 20, 17, -1, 24, 21, 32, 32, 24, 17, -1, 24, 21, 19, 20, 32, -1, 38, 21, 28, 31, -1, 18, 27, 30, 35, 13, 30, 16, 4, -1, 32, 30, 13, 15, 21, 26, 19, -1, 13, -1, 19, 24, 27, 35, 21, 26, 19, -1, 24, 27, 27, 28, -1, 32, 20, 30, 27, 33, 19, 20, -1, 32, 20, 17, -1, 13, 21, 30, 6],
            [20, 27, 28, -1, 21, 26, 4, -1, 20, 27, 28, -1, 21, 26, 0, -1, 25, 27, 25, 17, 26, 32, 33, 25, -1, 16, 27, 17, 31, 26, 1, 32, -1, 35, 13, 21, 32, 4, -1, 13, 26, 16, -1, 26, 17, 21, 32, 20, 17, 30, -1, 16, 27, -1, 21, 0],
            [30, 17, 13, 16, 37, 8, -1, 14, 17, 15, 13, 33, 31, 17, -1, 21, -1, 13, 24, 30, 17, 13, 16, 37, -1, 28, 30, 17, 31, 31, 17, 16, -1, 19, 27, 0],
            [13, 26, 16, -1, 35, 21, 32, 20, -1, 13, -1, 14, 30, 21, 19, 20, 32, 4, -1, 30, 17, 15, 23, 24, 17, 31, 31, -1, 24, 13, 33, 19, 20, 4, -1, 32, 20, 17, -1, 32, 30, 13, 15, 23, -1, 30, 27, 13, 30, 17, 16, -1, 32, 27, -1, 24, 21, 18, 17, 6],
        ]
    }
    ถ้า ภาษา == 2 {
        คืน [
            [65, 93, 129, 44, 101, 130, 62, 51, 139, 31, 123, 57, 123, 90, 119, 101, 130, 20, 149, 84, 59, 149, 123, 20, 149, 125, 123, 123, 123, 6, 149, 113, 138, 88, 20, 149, 123, 141, 88, 38, 150, 106, 107, 149, 65, 135, 38, 123, 123, 6],
            [151, 126, 0, -1, 151, 126, 0, -1, 152, 57, 51, 139, 114, 38, 0, -1, 84, 138, 13, 57, 149, 21, 123, 26, 130, 57, 150, 106, 107, 0],
            [150, 113, 20, 149, 101, 155, 6, -1, 154, -1, 77, 20, 6, 93, 129, 21, 133, 88, 119, 85, 57, 123, 90, 6, 130, 62, 51, 139, -1, 119, 130, 107, 149, 93, 133, 129, 13, 135, 6, 13, 130, 6, 41, 107, 88, 13, 107, 133, 84, 149, 93, 155, 107, 51, 139, 149, 65, 155, 57, 153, 65, 153, 86, 153, 41],
            [26, 130, 57, 27, 147, 123, 151, 13, 41, 133, 0, -1, 151, 61, 42, 51, 139, 149, 119, 101, 146, 123, 51, 139, 153, 86, 84, 138, 51, 139, 108, 133, 20, 152, 121, 152, 57, 62, 51, 149, 76, 101, 20, 153, 20, 105, 129, 0],
            [76, 107, 6, 149, 10, 133, 149, 101, 88, 113, 99, 133, 20, 93, 133, 20, 51, 132, 20, 93, 133, 20, 152, 121, 26, 130, 57, 107, 136, 20, 149, 105, 57, 150, 62, 62, 64, 133, 13, 101, 131, 20, 150, 51, 57, 0],
            [150, 113, 20, 149, 101, 155, 6, -1, 154, -1, 77, 20, 153, 65, 12, 133, 20, 119, 61, 133, -1, 101, 133, 6, 149, 65, 155, 57, 107, 20, 150, 119, 107, 57, 149, 93, 146, 123, 20, 150, 113, 20, 6, 101, 133, 20, 123, 133, 6, 133, 110],
            [6, 93, 129, 151, 38, 38, 10, 145, 57, 84, 133, 149, 101, 88, -1, 6, 93, 129, 151, 38, 38, 10, 145, 57, 84, 133, 0, -1, 151, 84, 149, 84, 57, 42, 130, 84, 153, 86, 93, 123, 152, 13, 93, 57, 129, -1, 150, 106, 107, 26, 130, 57, 6, 155, 153, 86, 93, 123, 41, 107, 88, 0],
            [76, 99, 123, 84, 119, 93, 146, 123, 88, 130, 20, 5, -1, 149, 76, 93, 133, 129, 26, 130, 57, 6, 38, 153, 65, 150, 106, 107, 57, 129, 0],
            [150, 101, 129, 41, 107, 88, 149, 113, 138, 88, 20, 119, 130, 107, 149, 93, 133, 129, 113, 38, 152, 113, 153, 86, 88, 132, 20, 13, 135, 38, -1, 93, 133, 20, 6, 155, 13, 134, 93, 133, 84, 84, 138, 27, 138, 107, 135, 42, 10, 145, 57, 84, 133],
        ]
    }
    ถ้า ภาษา == 3 {
        คืน [
            [224, 113, -1, 523, 226, -1, 148, 349, -1, 309, 35, 429, -1, 272, 244, 385, -1, 239, 386, 4, -1, 85, 387, -1, 302, 206, 203, -1, 93, 225, -1, 353, 207, 120],
            [359, 0, -1, 359, 0, -1, 149, 157, 340, 0, -1, 110, 17, -1, 88, -1, 444, 333, 340, 0],
            [397, 382, -1, 276, 385, -1, 131, 340, 206, 17, -1, 60, -1, 396, 206, 349, 292, -1, 275, 63, 275, 63, -1, 136, 225, 4, -1, 215, 134, -1, 329, -1, 140, 115, -1, 303, 134, 197, -1, 474, 150, 28, 207, 120],
            [87, -1, 469, 120, 336, 0, -1, 105, 179, 349, -1, 396, 206, 17, -1, 346, 340, 292, -1, 89, 35, 429, -1, 384, 495, 174, 43, 0],
            [60, 179, 292, -1, 127, 318, -1, 93, 17, -1, 211, 384, 74, -1, 124, 208, -1, 307, -1, 393, 115, -1, 485, 180, 383, -1, 483, 436, 197, -1, 213, 153, 340, 425, 427, 0],
            [397, 382, -1, 276, 386, -1, 334, 381, 197, -1, 528, -1, 86, 327, 17, 225, 4, -1, 48, 423, 349, -1, 276, 86, 115, -1, 43, 206, 203, -1, 60, 207, 120],
            [477, 4, -1, 340, 292, -1, 477, 0, -1, 370, 137, 183, 382, -1, 65, 120, 192, 420, 427, -1, 331, 327, 4, -1, 86, 134, -1, 211, 441, 17, 427, 43, 0],
            [421, 272, 139, 340, 16, -1, 366, 96, 226, -1, 87, -1, 386, 243, -1, 457, 249, -1, 254, 486, 383, -1, 112, 189, 28, 151, 0],
            [60, 206, 43, -1, 250, 43, -1, 28, 463, 346, 115, -1, 373, 384, 302, 206, 362, -1, 505, 75, 4, -1, 485, 180, 386, -1, 51, 384, 383, -1, 93, 225, -1, 286, 327, 90, 120],
        ]
    }
    ถ้า ภาษา == 4 {
        คืน [
            [111, 103, 113, 122, 440, 604, 33, 49, 63, 49, 49, 525, 46, 594, 26, 72, 35, 463, 266, 49, 325, 17, 6, 18, 27, 60, 45, 17, 69, 586, 12, 35],
            [15, 15, 0, -1, 15, 15, 0, -1, 39, 12, 46, 0, -1, 537, 16, 17, 462, 75, 527, 39, 22, 41, 20, 72, 35, 0],
            [268, 26, 45, 167, 49, 227, 17, 33, 49, 226, 42, 20, 71, 20, 71, 43, 216, 70, 6, 11, 70, 303, 45, 12, 564, 26, 42, 20, 29, 20, 29, 473, 38, 41, 12, 71],
            [462, 50, 88, 122, 96, 0, -1, 393, 49, 134, 46, 272, 226, 324, 17, 45, 16, 38, 35, 6, 152, 70, 63, 49, 49, 605, 475, 68, 0],
            [36, 16, 69, 144, 74, 70, 46, 6, 312, 12, 38, 18, 70, 369, 540, 42, 18, 71, 88, 122, 91, 169, 150, 75, 153, 38, 41, 20, 72, 35, 49, 0],
            [268, 26, 45, 167, 50, 182, 55, 43, 615, 53, 176, 27, 6, 468, 134, 46, 550, 20, 551, 75, 344, 12, 35],
            [26, 11, 136, 38, 41, 6, 136, 38, 41, 0, -1, 185, 12, 50, 300, 38, 41, 20, 72, 45, 12, 27, 6, 462, 63, 300, 35, 45, 12, 74, 68, 0],
            [415, 160, 50, 12, 12, 3, -1, 36, 38, 41, 63, 13, 6, 91, 95, 122, 100, 107, 95, 120, 50, 333, 27, 37, 64, 38, 35, 63, 49, 0],
            [33, 27, 41, 363, 71, 20, 201, 24, 13, 527, 30, 45, 473, 12, 232, 43, 43, 63, 46, 6, 88, 122, 91, 50, 552, 605, 75, 128, 23, 41, 184, 18, 176, 27, 35],
        ]
    }
    ถ้า ภาษา == 5 {
        คืน [
            [11, 371, 698, 216, 694, 142, 567, 818, 454, 739, 672, 163, 573, 271, 793, 850, 173, 175, 11, 228, 374, 315, 38],
            [186, 847, 186, 847, 639, 41, 847, 449, 48, 378, 123, 367, 38, 847],
            [11, 207, 276, 276, 573, 93, 145, 217, 426, 742, 582, 850, 56, 17, 158, 345, 714, 573, 765, 310, 182, 182, 614, 582],
            [367, 436, 280, 228, 848, 1, 4, 3, 2, 849, 847, 436, 773, 833, 480, 779, 500, 217, 424, 268, 632, 573, 7, 128, 16, 573, 819, 616, 847],
            [370, 56, 54, 57, 300, 674, 27, 367, 766, 38, 11, 421, 456, 730, 769, 850, 713, 367, 279, 358, 552, 246, 847],
            [773, 769, 276, 276, 573, 93, 165, 126, 571, 834, 664, 146, 850, 216, 607, 25, 116, 111, 11, 769, 150, 93, 573, 213, 555],
            [340, 15, 457, 850, 340, 15, 457, 847, 133, 781, 158, 17, 619, 48, 850, 367, 36, 11, 467, 847],
            [108, 230, 247, 38, 166, 852, 206, 27, 367, 294, 640, 396, 16, 111, 150, 791, 38, 847],
            [805, 582, 11, 799, 433, 46, 664, 428, 370, 823, 338, 573, 614, 228, 850, 730, 769, 745, 840, 582, 688, 777, 38, 752, 457],
        ]
    }
    คืน []
}

ฟังก์ชัน ฉากโบนัส_บทพูด(ภาษา) {
    ถ้า ภาษา == 0 {
        คืน [
            "shikuretto doa, menyu jitai no ushiro-ni haiddo, kuriku opun.",
            "o! o! fainari! dareka wareware faundo!",
            "chisana basuto obu raito, sono ba-de supin, imposhiburu supido-de gigguru.",
            "wareware koda! songu no naka, dare mo rumu nakatta rifutoba noto!",
            "dakara karera, wareware-ni oru torakku birudo, wairudo ran suru tame!",
            "ritoru raito, foawado zippu, ea-o tsuru guroingu rupu toreisu.",
            "hoppu in, hoppu in! momentamu weito shinai, wareware mo shinai!",
            "redi? nazenara wareware sudeni go pusshu shita!",
            "soshite buraito, rekkuresu raffu-de, torakku raifu-ni roa."
        ]
    }
    ถ้า ภาษา == 2 {
        คืน [
            "ประตูลับที่ซ่อนอยู่หลังเมนูเองเอ่อออกเสียงเอี๊ยดแล้วเปิดออก",
            "โอ้! โอ้! ในที่สุด! มีคนเจอฉันแล้ว!",
            "แสงเล็ก ๆ พุ่งกระจายหมุนอยู่กับที่ หัวเราะคิกคักด้วยความเร็วที่เป็นไปไม่ได้",
            "ฉันชื่อโคด้า! โน้ตที่เหลือที่ไม่มีที่ว่างให้ในบทเพลงไงล่ะ!",
            "พวกเขาเลยสร้างรางทั้งรางให้ฉันวิ่งเล่นแบบบ้าคลั่งแทน!",
            "แสงเล็ก ๆ พุ่งไปข้างหน้า ลากเป็นวงแหวนเรืองแสงกลางอากาศ",
            "กระโดดขึ้นมาเลย กระโดดขึ้นมา! โมเมนตัมไม่รอใครนะ แล้วฉันก็ไม่รอด้วย!",
            "พร้อมหรือยัง? เพราะฉันกดไปแล้วนะ!",
            "และด้วยเสียงหัวเราะสดใสไม่ยั้งคิด รางก็คำรามมีชีวิตขึ้นมา"
        ]
    }
    ถ้า ภาษา == 3 {
        คืน [
            "메뉴 화면 뒤에 숨겨진 비밀의 문이, 끼익 소리를 내며 열린다",
            "오! 오! 드디어! 누가 날 찾았어!",
            "작은 빛의 덩어리가 그 자리에서 빙글빙글 돌며, 말도 안 되는 속도로 키득거린다",
            "난 코다야! 노래에 자리가 없어서 남겨진 음표라고!",
            "그래서 대신 내가 마음껏 달릴 수 있는 트랙을 통째로 만들어줬지!",
            "작은 빛이 앞으로 휙 나아가며, 공중에 빛나는 고리를 그린다",
            "타, 어서 타! 운동량은 기다려주지 않아, 나도 마찬가지고!",
            "준비됐어? 왜냐면 난 이미 출발 버튼을 눌렀거든!",
            "그리고 밝고 거침없는 웃음소리와 함께, 트랙이 굉음을 내며 살아났다"
        ]
    }
    ถ้า ภาษา == 4 {
        คืน [
            "メニュー画面そのものの裏に隠された秘密の扉が、きしみながら開いた",
            "おお! おお! ついに! 誰かが私を見つけてくれた!",
            "小さな光の塊がその場でくるくると回り、あり得ない速さでくすくす笑っている",
            "私はコーダ! 歌の中に居場所がなかった、余りものの音符よ!",
            "だから代わりに、思いっきり暴走できるコース全体を作ってくれたの!",
            "小さな光は前へと飛び出し、空中に輝く輪を描いた",
            "さあ乗って、乗って! 勢いは待ってくれないし、私も待たないわよ!",
            "準備はいい? だってもう、スタートボタンは押しちゃったもの!",
            "そして明るく向こう見ずな笑い声とともに、コースは轟音を上げて動き出した"
        ]
    }
    ถ้า ภาษา == 5 {
        คืน [
            "一扇藏在菜单界面本身背后的密门,吱呀一声打开了",
            "哦!哦!终于!有人找到我了!",
            "一团小小的光原地旋转着,以不可思议的速度咯咯笑着",
            "我是尾声(Coda)!是那首歌里没地方容纳的、剩下的音符!",
            "所以他们干脆为我造了一整条赛道,让我尽情狂奔!",
            "那道小小的光向前疾驰而去,在空中划出一道发光的圆环",
            "快上来,快上来!动量可不等人,我也一样!",
            "准备好了吗?因为我已经按下出发键了!",
            "随着一阵明亮而无所顾忌的笑声,赛道轰鸣着苏醒了过来"
        ]
    }
    คืน [
        "a secret door, hidden behind the menu itself, creaks open.",
        "oh! oh! finally! someone found me!",
        "a small burst of light spins in place, giggling at impossible speed.",
        "i'm coda! the leftover note nobody had room for in the song!",
        "so they built me a whole track to run wild on instead!",
        "the little light zips forward, tracing a glowing loop through the air.",
        "hop in, hop in! momentum doesn't wait, and neither do i!",
        "ready? because i already pressed go!",
        "and with a bright, reckless laugh, the track roared to life."
    ]
}

ฟังก์ชัน ฉากโบนัส_ผู้พูด() {
    คืน [0, 1, 0, 1, 1, 0, 1, 1, 0]   # 0 narrator, 1 coda
}

# รหัสผู้พูดสำหรับพากย์เสียง (ต้องตรงกับ tools/voiceover/manifest.py ทุกตัวอักษร)
ฟังก์ชัน ฉากโบนัส_ผู้พูดรหัส() {
    คืน ["narrator", "coda", "narrator", "coda", "coda", "narrator", "coda", "coda", "narrator"]
}

# ระยะเวลาเล่นต่อบรรทัด (วิ) — ยังไม่มีเสียงพากย์อัดจริงตอนเขียนไฟล์นี้ (ทุกภาษา
# รวม en) จึงใช้ค่าประมาณคร่าว ๆ ตามความยาวประโยคไปก่อน แทนที่ด้วยตัวเลขจริงจาก
# tools/voiceover/progress.json ทันทีที่อัดเสียงแต่ละภาษาเสร็จ (ดูแพตเทิร์นใน
# chapter1.ling ฟังก์ชันเดียวกันนี้)
ฟังก์ชัน ฉากโบนัส_ระยะเวลา(lang) {
    ถ้า lang == "ko" { คืน [5.22, 4.74, 7.78, 4.98, 4.50, 5.86, 4.98, 4.66, 19.38] }
    ถ้า lang == "ja" { คืน [5.94, 5.14, 6.10, 7.14, 4.98, 5.38, 6.02, 4.42, 6.74] }
    ถ้า lang == "zh" { คืน [4.58, 2.58, 5.78, 4.34, 3.22, 5.06, 2.82, 2.66, 5.70] }
    ถ้า lang == "daemon" { คืน [4.98, 4.34, 4.66, 6.50, 7.30, 5.86, 4.26, 4.50, 5.86] }
    ถ้า lang == "th" { คืน [4.28, 4.40, 5.28, 4.60, 4.10, 4.48, 5.54, 3.20, 4.94] }
    ถ้า lang == "en" { คืน [4.58, 3.14, 5.14, 3.70, 3.14, 4.02, 3.54, 2.02, 4.58] }
    ถ้า lang == "ko" { คืน [5.22, 4.74, 7.78, 4.98, 4.50, 5.86, 4.98, 4.66, 19.38] }
    ถ้า lang == "ja" { คืน [5.94, 5.14, 6.10, 7.14, 4.98, 5.38, 6.02, 4.42, 6.74] }
    ถ้า lang == "zh" { คืน [4.58, 2.58, 5.78, 4.34, 3.22, 5.06, 2.82, 2.66, 5.70] }
    คืน [3.2, 2.2, 3.4, 3.0, 3.0, 3.2, 2.8, 2.4, 3.2]
}

ฟังก์ชัน ฉากโบนัส_สีวน(h) {
    คืน [floor((ไซน์(h)*0.5+0.5)*205+50), floor((ไซน์(h+2.094)*0.5+0.5)*205+50), floor((ไซน์(h+4.189)*0.5+0.5)*205+50)]
}

# พารามิเตอร์จาก main (ฟังก์ชันมองไม่เห็น local ของ do-block) — ไม่มีคิว/ควีนในฉากนี้
# สามเหลี่ยมสองหน้า (เวกเตอร์ขวาของระนาบหน้าพลิกเครื่องหมายเมื่อกล้องข้ามฝั่ง)
ฟังก์ชัน ฉากโบนัส_สองหน้า(ax, ay, az, bx, by, bz, cx, cy, cz) {
    วาดสามเหลี่ยม3มิติ(ax, ay, az, bx, by, bz, cx, cy, cz)
    วาดสามเหลี่ยม3มิติ(bx, by, bz, ax, ay, az, cx, cy, cz)
}

ฟังก์ชัน เล่นฉากโบนัส(t, บทเริ่ม, บรรทัดก่อน, musicOn, ปริมาณBGM, ปริมาณSFX, เพลงฉาก, ยาวเพลงฉาก, ภาษา, แสดงบทพูด, ภาษาบทพูด) {
    bind บทพูด = ฉากโบนัส_บทพูด(ภาษาแสดงผล(ภาษา))
    bind บทพูดกลิฟ = ฉากโบนัส_บทพูดกลิฟ(ภาษาบทพูด)
    bind ผู้พูด = ฉากโบนัส_ผู้พูด()
    bind ผู้พูดรหัส = ฉากโบนัส_ผู้พูดรหัส()
    bind voLang = รหัสภาษาเสียง(ภาษา)
    bind ระยะเวลา = ฉากโบนัส_ระยะเวลา(voLang)
    bind bnt = t - บทเริ่ม
    bind BN = ความยาว(บทพูด)
    bind bcum = [0.0]
    bind cci = 0
    ขณะที่ cci < BN {
        bind bcum = list_push(bcum, list_get(bcum, cci) + list_get(ระยะเวลา, cci))
        bind cci = cci + 1
    }
    bind BTOTAL = list_get(bcum, BN)
    bind BEND = BTOTAL + 3.0                                    # หาง 3 วิ: เล่นค้าง + เฟดดำ + กล้องถอย
    bind BFADE = 0.0
    ถ้า bnt > BEND - 3.2 { bind BFADE = (bnt - (BEND - 3.2)) / 3.2 }
    ถ้า BFADE > 1.0 { bind BFADE = 1.0 }
    bind bi = 0
    bind bscan = 1
    ขณะที่ bscan == 1 {
        ถ้า bi >= BN - 1 { bind bscan = 0 }
        มิฉะนั้น { ถ้า bnt < list_get(bcum, bi + 1) { bind bscan = 0 }
        มิฉะนั้น { bind bi = bi + 1 } }
    }
    bind BSEC = list_get(ระยะเวลา, bi)
    bind ดำ = 1.0 - BFADE

    ถ้า musicOn == 1 {
        ถ้า ยาวเพลงฉาก > 1.0 {
            ถ้า ตำแหน่งเพลง() >= ยาวเพลงฉาก - 0.5 { ค้นหาเพลง(0);  เล่นเพลง(เพลงฉาก) }
        }
        ระดับเพลง(ปริมาณBGM * 0.33 * (1.0 - BFADE))              # หรี่ BGM — เสียงพากย์ต้องเด่นกว่า
    }

    เบลอเฟรม(0.958)
    เติม(floor(4.0*ดำ), floor(3.0*ดำ), floor(9.0*ดำ))

    # ── ประตูลับแตกร้าว: วงแหวนรอยแยกโตขึ้นเรื่อย ๆ จนเต็มช่วงต้นฉาก ──
    bind crackOn = bnt / 2.0;  ถ้า crackOn > 1.0 { bind crackOn = 1.0 }
    bind cx = 0.0;  bind cy = 0.0 - 4.0;  bind cz = 10.0

    # ── โคด้า: ทรงกลมแกนสว่างสีวนรุ้ง วนรอบจุดศูนย์กลาง + กระพือความเร็ว ──
    bind hue = bnt * 2.6
    bind cCol = ฉากโบนัส_สีวน(hue)
    bind orbit = bnt * 3.4
    bind codaR = 6.0 + ไซน์(bnt*0.9)*1.5
    bind codax = cx + โคไซน์(orbit) * codaR
    bind coday = cy + ไซน์(bnt*2.2) * 1.8
    bind codaz = cz + ไซน์(orbit) * codaR * 0.6

    # ── กล้อง: ช็อต A (บรรทัด 0-2) กว้างเผยประตู · ช็อต B (3+) วนใกล้โคด้า ──
    bind tA = list_get(bcum, 3)
    bind camX = 0.0;  bind camY = 0.0 - 6.0;  bind camZ = 0.0 - 13.0
    bind lookX = cx;  bind lookY = cy;  bind lookZ = cz
    ถ้า bnt < tA {
        bind sp1 = bnt / tA;  bind se1 = sp1*sp1*(3.0-2.0*sp1)
        bind camX = 0.0 - 10.0 + 10.0*se1;  bind camY = 0.0 - 5.5;  bind camZ = 0.0 - 16.0 + 3.0*se1
    }
    มิฉะนั้น {
        bind ag = 2.2 - (bnt - tA)*0.18
        bind camX = codax + โคไซน์(ag)*7.0
        bind camZ = codaz - ไซน์(ag)*7.0 - 4.0
        bind camY = coday - 3.0
        bind lookX = codax;  bind lookY = coday;  bind lookZ = codaz
    }
    ถ้า bnt > BTOTAL {
        bind หลังฉาก = bnt - BTOTAL
        bind camY = camY - หลังฉาก*0.6;  bind camZ = camZ - หลังฉาก*1.4
    }
    ตั้งกล้องมอง(camX, camY, camZ, lookX, lookY, lookZ)
    ตั้งระยะห่าง(1.85)

    ล้างแสง()
    ตั้งแสงรอบข้าง(0.16 * ดำ)
    เพิ่มแสง(codax, coday - 3.0, codaz, list_get(cCol,0)/255.0, list_get(cCol,1)/255.0, list_get(cCol,2)/255.0, 1.6*ดำ, 55.0)

    # ── วงแหวนรอยแยกประตู (โหมดผสม additive) ──
    โหมดผสม(1)
    ถ้า crackOn > 0.0 {
        bind rc = ฉากโบนัส_สีวน(hue + 1.4)
        สีดินสอ(list_get(rc,0), list_get(rc,1), list_get(rc,2))
        bind rg = 0
        ขณะที่ rg < 20 {
            bind a0 = rg*0.3142;  bind a1 = (rg+1)*0.3142
            bind rr = 6.5*crackOn
            วาดเส้น3มิติ(cx+โคไซน์(a0)*rr, cy+ไซน์(a0)*rr, cz,  cx+โคไซน์(a1)*rr, cy+ไซน์(a1)*rr, cz)
            bind rg = rg + 1
        }
    }

    # ── หางดาวตกของโคด้า: ไล่ตำแหน่งย้อนหลัง 6 จุด ──
    bind tr = 0
    ขณะที่ tr < 6 {
        bind tp = tr / 6.0
        bind torb = orbit - tr*0.35
        bind tR = codaR - tr*0.15
        bind tx = cx + โคไซน์(torb)*tR
        bind ty = cy + ไซน์(bnt*2.2 - tr*0.1)*1.8
        bind tz = cz + ไซน์(torb)*tR*0.6
        bind trc = ฉากโบนัส_สีวน(hue - tr*0.5)
        สีดินสอ(floor(list_get(trc,0)*(1.0-tp)), floor(list_get(trc,1)*(1.0-tp)), floor(list_get(trc,2)*(1.0-tp)))
        อนุภาคทรงกลม(tx, ty, tz, 0.9*(1.0-tp*0.6), 6, bnt*3.0+tr, list_get(trc,0), list_get(trc,1), list_get(trc,2))
        bind tr = tr + 1
    }

    # ── แกนสว่างของโคด้า (แกนขาวจ้าตรงกลาง + ตาเล็กสองจุดให้มีบุคลิก) ──
    set_flat_shade(1.0)
    สีดินสอ(floor(230*ดำ), floor(235*ดำ), floor(255*ดำ))
    sphere(codax, coday, codaz, 1.05, 1.05, 1.05, 0.0, 0.0, 0.0, 0, 10, 8)
    flush_3d()
    สีดินสอ(20, 16, 30)
    # ระนาบหน้าโคด้าหันตามกล้อง — ช็อต B กวาดกล้องข้ามระนาบตาเดิม (codaz-1.0) ท้ายฉาก
    bind คนx = camX - codax;  bind คนz = camZ - codaz
    bind คนl = รากที่สอง(คนx*คนx + คนz*คนz);  ถ้า คนl < 0.001 { bind คนl = 0.001 }
    bind cnx = คนx/คนl;  bind cnz = คนz/คนl
    bind crx = 0.0 - cnz;  bind crz = cnx
    bind cbx = codax + cnx*1.0;  bind eyez = codaz + cnz*1.0
    ฉากโบนัส_สองหน้า(cbx - crx*0.32, coday-0.12, eyez - crz*0.32,
                     cbx - crx*0.14, coday-0.12, eyez - crz*0.14,
                     cbx - crx*0.23, coday+0.08, eyez - crz*0.23)
    ฉากโบนัส_สองหน้า(cbx + crx*0.32, coday-0.12, eyez + crz*0.32,
                     cbx + crx*0.14, coday-0.12, eyez + crz*0.14,
                     cbx + crx*0.23, coday+0.08, eyez + crz*0.23)
    flush_3d()
    set_flat_shade(0.0)

    # ── รางโรลเลอร์โคสเตอร์ที่กำลังผุด (loop-de-loop) — โผล่ทีละส่วนตามความคืบหน้าฉาก ──
    bind trackP = 0.0
    ถ้า bnt > tA { bind trackP = (bnt - tA) / (BTOTAL - tA) }
    ถ้า trackP > 1.0 { bind trackP = 1.0 }
    ถ้า trackP > 0.0 {
        bind tkCol = ฉากโบนัส_สีวน(hue + 2.7)
        สีดินสอ(list_get(tkCol,0), list_get(tkCol,1), list_get(tkCol,2))
        bind segMax = floor(48.0 * trackP)
        bind sg = 0
        ขณะที่ sg < segMax {
            bind u0 = sg / 48.0;  bind u1 = (sg+1) / 48.0
            bind ang0 = u0 * 12.566;  bind ang1 = u1 * 12.566        # 2 รอบวน = ลูป
            bind fx0 = cx - 4.0 + u0*22.0;  bind fx1 = cx - 4.0 + u1*22.0
            bind fy0 = cy - 2.0 + ไซน์(ang0)*3.2;  bind fy1 = cy - 2.0 + ไซน์(ang1)*3.2
            bind fz0 = cz + 6.0 + โคไซน์(ang0)*3.2;  bind fz1 = cz + 6.0 + โคไซน์(ang1)*3.2
            วาดเส้น3มิติ(fx0, fy0, fz0, fx1, fy1, fz1)
            bind sg = sg + 1
        }
    }
    flush_3d();  โหมดผสม(0)

    # ── เหตุการณ์ครั้งเดียวต่อบรรทัด: พากย์เสียง + โน้ตประกอบ ──
    ถ้า bi > บรรทัดก่อน {
        ถ้า bi < BN {
            bind whoN = list_get(ผู้พูด, bi)
            เล่นเสียงพากย์("bonus", bi, list_get(ผู้พูดรหัส, bi), ภาษา, ปริมาณSFX)
            ถ้า whoN < 0.5 { เล่นไชม์ใหญ่(cx, cy, cz, 293.7, 0.24 * ปริมาณSFX) }
            มิฉะนั้น {
                เล่นกาเมลัน(codax, coday, codaz, 587.3 + ไซน์(bnt*4.0)*80.0, 0.28 * ปริมาณSFX)
                เล่นฮังแพน(codax, coday, codaz, 392.0, 0.14 * ปริมาณSFX)
            }
            ถ้า bi == 8 {                                          # "track roared to life": แฟลช + เสียงเครื่องยนต์พุ่ง
                เสียงเอฟเฟกต์(cx, cy, cz, 1.0, 90.0, 0.4*ปริมาณSFX, 1.2, "saw")
                เล่นฆ้อง(cx, cy, cz, 130.8, 0.3 * ปริมาณSFX)
            }
        }
        bind บรรทัดก่อน = bi
    }

    # ── ตัวหนังสือ ──
    ตั้งกล้องมอง(0.0, 0.0, -22.0, 0.0, 0.0, 0.0)
    ตั้งระยะห่าง(2.8)
    สีดินสอ(floor(220*ดำ+15), floor(200*ดำ+15), floor(255*ดำ+15))
    วาดสตริง("bonus : the leftover note", 0.0, 10.0, 0.0, 0.62, 1)
    ถ้า bi < BN {
        bind bline = list_get(บทพูด, bi)
        bind blineกลิฟ = list_get(บทพูดกลิฟ, bi)
        bind who2 = list_get(ผู้พูด, bi)
        bind lt = bnt - list_get(bcum, bi)
        bind laf = 1.0
        ถ้า lt < 0.5 { bind laf = lt / 0.5 }
        ถ้า lt > BSEC - 0.6 { bind laf = (BSEC - lt) / 0.6 }
        ถ้า laf < 0.0 { bind laf = 0.0 }
        bind lr = floor(230.0 * laf);  bind lg = floor(240.0 * laf);  bind lb = floor(255.0 * laf)
        ถ้า who2 > 0.5 { bind lr = floor(255.0*laf);  bind lg = floor(210.0*laf);  bind lb = floor(255.0*laf) }
        ถ้า แสดงบทพูด == 1 {
            วาดสตริงบทพูดบากขอบ(blineกลิฟ, ภาษาบทพูด, 0.0, 8.3, 0.0, 0.62)
            สีดินสอ(lr, lg, lb)
            วาดสตริงบทพูดบาก(blineกลิฟ, ภาษาบทพูด, 0.0, 8.3, 0.0, 0.62)
        }
    }
    สีดินสอ(170, 180, 205)
    วาดสตริง("[enter/space] continue   [esc] skip", 0.0, 10.9, 0.0, 0.42, 1)
    flush_3d()

    แสดงผล()

    bind outB = 0.0
    ถ้า bnt >= BEND { bind outB = 1.0 }
    ถ้า bnt > 5.0 {
        ถ้า กดปุ่ม("enter") { bind outB = 1.0 }
        ถ้า กดปุ่ม("space") { bind outB = 1.0 }
        ถ้า กดปุ่ม("escape") { bind outB = 1.0 }
        ถ้า จอยปุ่ม("a") { bind outB = 1.0 }
        ถ้า จอยปุ่ม("start") { bind outB = 1.0 }
    }
    ถ้า outB > 0.5 { เบลอเฟรม(0.0) }
    คืน [บรรทัดก่อน, outB]
}

← Back to index