Advertisement
Guest User

Rocky's Unnamed Cinematic Script Thing for LuaLuna

a guest
Sep 29th, 2014
158
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 29.75 KB | None | 0 0
  1. --***************************************************************************************
  2. -- DIALOGUE/SUBTITLE VARIABLES                              *
  3. --***************************************************************************************
  4.  
  5. -- Speaker NPC ID
  6. dialogSpeaker = 0
  7.  
  8. -- _____
  9. dialogSpeakerFrame = 0
  10.  
  11. -- Text display countdown
  12. dialogTextTime = 0
  13.  
  14. -- Speaker animation countdown
  15. dialogSpeakerTime = 0
  16.  
  17. -- Dialogue update rate (characters per frame)
  18. dialogTextSpeed = 1
  19.  
  20. -- Check whether a line of dialogue or subtitle is being processed
  21. dialogOn = false
  22.  
  23. -- Speaker name
  24. dialogName = ""
  25.  
  26. -- Full line of dialogue being spoken with timing commands
  27. dialogTextFull = ""
  28.  
  29. -- Currently-revealed dialogue string
  30. dialogText = ""
  31.  
  32. -- Line of dialogue being spoken with timing commands
  33. dialogTextCommands = ""
  34.  
  35. -- Individual lines of the line of dialogue being spoken
  36. dialogTextLine1 = ""
  37. dialogTextLine2 = ""
  38. dialogTextLine3 = ""
  39. dialogTextLine4 = ""
  40.  
  41. -- Total number of characters in the dialogue string
  42. dialogNumCharsTotal = 0
  43.  
  44. -- Number of characters revealed in the displayed dialogue
  45. dialogNumCharsCurrent = 0
  46.  
  47. -- Number of characters revealed w/ bypassing commands
  48. dialogNumCharsCommands = 0
  49.  
  50. -- Can the player press the key to skip the current line?
  51. dialogSkippable = true
  52.  
  53. -- Does the dialogue halt the cutscene timing?
  54. dialogPause = true
  55.  
  56. -- Does the player have to press a key to continue?
  57. dialogEndWithInput = true
  58.  
  59.  
  60.  
  61. --***************************************************************************************
  62. -- CUTSCENE VARIABLES                                   *
  63. --***************************************************************************************
  64.  
  65. -- Is there a cutscene or boss in each section
  66. levelSectionHasCutscene = {true,  false, false, false, false,
  67.                            false, false, false, false, false,
  68.                            false, false, false, false, false,
  69.                            false, false, false, false, false,
  70.                            false}
  71.  
  72.                            
  73. -- Can the entire cutscene be skipped?
  74. cutsceneSkippable = true
  75.  
  76. -- Player input currently active?
  77. playerInputActive = false
  78.  
  79. -- Current cutscene/attack pattern time in frames
  80. cutsceneFrame = 0
  81. battleFrame = 0
  82.  
  83. -- "Phase" of the full sequence; 0 = pre-battle, 1 = battle, 2 = post-battle
  84. cutscenePhase = 0
  85.  
  86. -- "Phase" of the boss' attack pattern
  87. battlePhase = 0
  88.  
  89. -- For looping attack patterns, this is the current step of the pattern
  90. bossAttackPattern = 0
  91.  
  92.  
  93.  
  94.  
  95. --***************************************************************************************
  96. -- CONSTANTS AND ENUMS                                  *
  97. --***************************************************************************************
  98.  
  99. -- Key terms
  100. KEYTERM_PLAYERNAME = ""
  101.  
  102. -- NPC ID enums
  103. NPCID_BROADSWORD = 101
  104. NPCID_DONUTGEN = 211
  105. NPCID_SHOCKWAVEGEN = 206
  106. NPCID_COLLISIONA = 136
  107. NPCID_COLLISIONB = 137
  108.  
  109. -- Sound IDs
  110. SOUNDID_DRAWSWORD = "sword1.wav"
  111. SOUNDID_SLICE = "sword2.wav"
  112.  
  113. -- Animation states enum
  114. ANIMSTATE_NUMFRAMES = 0
  115. ANIMSTATE_IDLE = 1
  116. ANIMSTATE_TALK = 2
  117. ANIMSTATE_WALK = 3
  118. ANIMSTATE_JUMP = 4
  119. ANIMSTATE_FALL = 5
  120. ANIMSTATE_DEFEAT = 6
  121. ANIMSTATE_ATTACK1 = 7
  122. ANIMSTATE_ATTACK2 = 8
  123. ANIMSTATE_ATTACK3 = 9
  124. ANIMSTATE_ATTACK4 = 10
  125. ANIMSTATE_ATTACK5 = 11
  126. ANIMSTATE_ATTACK6 = 12
  127. ANIMSTATE_ATTACK7 = 13
  128.  
  129.  
  130. -- NPC animation state table
  131. npcAnimStates = {}
  132. npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  133.  
  134.  
  135. -- Individual NPC animation settings
  136. animData_Broadsword = {}
  137. animData_Broadsword[ANIMSTATE_NUMFRAMES] = 32
  138. animData_Broadsword[ANIMSTATE_IDLE] = "0-0"
  139. animData_Broadsword[ANIMSTATE_TALK] = "1-2"
  140. animData_Broadsword[ANIMSTATE_WALK] = "4-5"
  141. animData_Broadsword[ANIMSTATE_JUMP] = "7-7"
  142. animData_Broadsword[ANIMSTATE_FALL] = "9-9"
  143. animData_Broadsword[ANIMSTATE_DEFEAT] = "21-21"
  144. animData_Broadsword[ANIMSTATE_ATTACK1] = "11-11"
  145. animData_Broadsword[ANIMSTATE_ATTACK2] = "13-15"
  146. animData_Broadsword[ANIMSTATE_ATTACK3] = "17-17"
  147. animData_Broadsword[ANIMSTATE_ATTACK4] = "19-19"
  148. animData_Broadsword[ANIMSTATE_ATTACK5] = "23-23"
  149. animData_Broadsword[ANIMSTATE_ATTACK6] = "25-25"
  150. animData_Broadsword[ANIMSTATE_ATTACK7] = "27-30"
  151.  
  152.  
  153.  
  154.  
  155.  
  156. -- PLEASE TAMPER WITH THIS FUNCTION, THANK YOU -----------------------------------------
  157. function onLoadVars ()
  158. end
  159.  
  160. function preBattleEvents ()  
  161.  
  162.   -- Disable the shockwave generators
  163.   shockwaveGenLNPC:mem (0x6C, FIELD_FLOAT, 0)
  164.   shockwaveGenRNPC:mem (0x6C, FIELD_FLOAT, 0)
  165.  
  166.   -- Make the boss invincible during the intro cutscene
  167.   collisionANPC:mem (0x46, FIELD_WORD, 0xFFFF)
  168.  
  169.   -- Cutscene events
  170.   if     cutsceneFrame <    60 then
  171.     forceNPCWalkRight (broadswordNPC, 0)
  172.     player.speedX = 3
  173.    
  174.   elseif cutsceneFrame ==   60 then
  175.     --playSFX("voice_talk1.wav")
  176.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  177.     forceNPCWalkLeft (broadswordNPC, 0)
  178.  
  179.   elseif cutsceneFrame ==   61 then
  180.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "A-ha! 'Twas a good show, "..KEYTERM_PLAYERNAME..", but I       emerge the victor!", 30, 30, "voice_talk1.wav")
  181.  
  182.   elseif cutsceneFrame ==   62 then
  183.     startDialog  (NPCID_IRIS, KEYTERM_PLAYERNAME, "B-but we really need that leek!            Best two out of three?", 30, 30, "")
  184.  
  185.   elseif cutsceneFrame ==   63 then
  186.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "Tsk, tsk, tsk! Nobody likes a sore loser,  my dear!", 30, 30, "")
  187.  
  188.   elseif cutsceneFrame ==   64 then
  189.     setDialogRules (false, false, true, 1)
  190.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "But I am still feeling a tad sporting...", 160, 100, "")
  191.  
  192.   elseif cutsceneFrame  <   120 then
  193.     forceNPCWalkRight (broadswordNPC, 2)
  194.  
  195.   elseif cutsceneFrame ==   120 then
  196.     setDialogRules (true, true, true, 1)
  197.     forceNPCWalkRight (broadswordNPC, 0)
  198.  
  199.   elseif cutsceneFrame ==   121 then
  200.     forceNPCWalkLeft (broadswordNPC, 0)
  201.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "Very well! If this preposterous produce    means that much to you, then come and have  a go!", 30, 30, "")
  202.  
  203.   elseif cutsceneFrame ==   122 then
  204.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "Best moi in a duel and the colossal        cabbage is yours!", 30, 30, "")
  205.  
  206.   elseif cutsceneFrame ==   123 then
  207.     --playSFX("voice_talk4.wav");
  208.  
  209.   elseif cutsceneFrame ==   124 then
  210.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "But I shant take this challenge lightly,   so don't hold back yourself!", 30, 30, "voice_talk4.wav")
  211.  
  212.   elseif cutsceneFrame ==   125 then
  213.     --playSFX("voice_talk5.wav");  
  214.  
  215.   elseif cutsceneFrame ==   126 then
  216.     setDialogRules (false, false, false, 1)
  217.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "EN GARDE!", 160, 160, "voice_talk5.wav")  
  218.  
  219.   elseif cutsceneFrame <   150 then
  220.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  221.  
  222.   elseif cutsceneFrame ==  150 then
  223.     playSFX(SOUNDID_DRAWSWORD)
  224.     broadswordNPC.x = broadswordNPC.x - 8
  225.  
  226.   elseif cutsceneFrame <   210 then
  227.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK1
  228.  
  229.   elseif cutsceneFrame ==  210 then
  230.     playSFX(SOUNDID_SLICE)
  231.     broadswordNPC.x = broadswordNPC.x - 16
  232.  
  233.   elseif cutsceneFrame <   260 then
  234.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK2
  235.  
  236.   elseif cutsceneFrame ==  260 then
  237.     broadswordNPC.x = broadswordNPC.x + 32
  238.  
  239.   elseif cutsceneFrame <   320 then
  240.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  241.  
  242.   elseif cutsceneFrame ==  320 then
  243.     triggerEvent("Begin Battle")
  244.     cutscenePhase = 1
  245.     cutsceneFrame = 0
  246.     collisionANPC:mem (0x46, FIELD_WORD, 0)
  247.   end
  248. end
  249.  
  250. function bossBattleEvents ()
  251.   -- Activate player input
  252.   playerInputActive = true  
  253.  
  254.    -- Disable the shockwave generators
  255.   if battlePhase ~= 2 then
  256.     shockwaveGenLNPC:mem (0x6C, FIELD_FLOAT, 0)
  257.     shockwaveGenRNPC:mem (0x6C, FIELD_FLOAT, 0)
  258.   end
  259.  
  260.  
  261.   -- Determine where the boss is relative to the player
  262.   local distToPlayerX = math.abs(getNPCRelativePosX (broadswordNPC))
  263.   local dirToPlayerX = getNPCRelativeDirX (broadswordNPC)
  264.   local distToWallX = getNPCWallDistance (broadswordNPC, getNPCWallClosest(broadswordNPC))
  265.  
  266.  
  267.   -- Display boss HP
  268.   if battlePhase ~= 30 then
  269.     printCenteredText ("AUGUSTUS LEOPOLD BROADSWORD ESQ. III", 4, 400, 500)  
  270.     printCenteredText (string.rep("8", bossHP), 4, 400, 520)  
  271.     printCenteredText (string.rep("3", bossHP), 4, 400, 520)  
  272.     printCenteredText (string.rep("K", bossHP), 4, 400, 520)  
  273.     printCenteredText (string.rep("N", bossHP), 4, 400, 520)  
  274.     printCenteredText (string.rep("W", bossHP), 4, 400, 520)  
  275.   end
  276.  
  277.  
  278.  
  279.   -- PHASE 1: DEFEND & MOVE AROUND -------------------------------------------------------------------
  280.   if battlePhase == 0 then
  281.  
  282.     battleFrame = battleFrame + 1
  283.    
  284.    
  285.     -- After 160 frames, move on to the next phase of the attack pattern
  286.     if battleFrame >= 240  and  broadswordNPC.speedY == 0  then
  287.      
  288.       bossAttackPattern = bossAttackPattern + 1
  289.       if (bossAttackPattern % 2 == 1) then
  290.         playSFX ("voice_attack1.wav")
  291.         battlePhase = 1
  292.       else
  293.         playSFX ("voice_attack2.wav")
  294.         battlePhase = 2
  295.       end
  296.       battleFrame = 0
  297.  
  298.      
  299.     elseif broadswordNPC.speedY == 0  then
  300.       if npcAnimStates[NPCID_BROADSWORD] == ANIMSTATE_ATTACK7 then
  301.         npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  302.       end
  303.        
  304.       if     distToWallX > 128  then  
  305.         if     distToPlayerX > 160 then
  306.           forceNPCWalkToPlayer (broadswordNPC, math.clamp(5, 12*(distToPlayerX/180 - 1), 8))
  307.  
  308.         elseif distToPlayerX < 160 then
  309.           forceNPCJump (broadswordNPC, math.random(4,6))
  310.           forceNPCWalkToPlayer (broadswordNPC, -6)
  311.         end
  312.       else
  313.         if (donutGenNPC ~= nil) then
  314.           donutGenNPC:mem (0x06, FIELD_WORD, 0)
  315.         end
  316.         forceNPCJump (broadswordNPC, 10)
  317.         forceNPCWalkToPlayer (broadswordNPC, 8)
  318.         npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK7
  319.         playSFX ("sword2.wav")
  320.       end
  321.     end
  322.  
  323.    
  324.   -- PHASE 2: DASH ATTACK ------------------------------------------------------------------------------
  325.   elseif battlePhase == 1 then
  326.    
  327.     battleFrame = battleFrame + 1
  328.    
  329.     -- Unsheath sword and hack away
  330.     if battleFrame     <  60 then
  331.       broadswordNPC.speedY = math.max(0, broadswordNPC.speedY)
  332.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK1
  333.       forceNPCWalkToPlayer (broadswordNPC, 0)
  334.     elseif battleFrame == 60 then
  335.       playSFX (SOUNDID_SLICE)
  336.     elseif battleFrame < 100 then
  337.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK2
  338.       forceNPCWalkForward (broadswordNPC, 8)
  339.       if getNPCWallDistance (broadswordNPC, getNPCWallFacing(broadswordNPC)) < 100 then
  340.         battleFrame = 100
  341.       end
  342.     else
  343.       battlePhase = 3
  344.       battleFrame = 0
  345.     end
  346.  
  347.   -- PHASE 3: POGO ------------------------------------------------------------------------------
  348.   elseif battlePhase == 2  then
  349.    
  350.     -- Disable the shockwave generators
  351.     if battleFrame ~= 120 then
  352.       shockwaveGenLNPC:mem (0x6C, FIELD_FLOAT, 0)
  353.       shockwaveGenRNPC:mem (0x6C, FIELD_FLOAT, 0)
  354.     end
  355.  
  356.    
  357.     -- Jump high
  358.     if battleFrame < 4 then
  359.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK5
  360.       forceNPCWalkToPlayer (broadswordNPC, math.clamp(-8, 0.05*(distToPlayerX), 8))
  361.       if broadswordNPC.speedY == 0  then
  362.         forceNPCJump (broadswordNPC, 11)
  363.         if (battleFrame > 0) then
  364.           playSFX ("boing.wav")
  365.         end
  366.         battleFrame = battleFrame + 1
  367.       end
  368.    
  369.     -- Hold in the air
  370.     elseif battleFrame == 4 then
  371.       playSFX (11)
  372.       battleFrame = battleFrame + 1
  373.     elseif battleFrame < 60 then
  374.       battleFrame = battleFrame + 1
  375.       forceNPCWalkToPlayer (broadswordNPC, 0)
  376.       if broadswordNPC.speedY > 0  then
  377.         broadswordNPC.speedY = 0
  378.       end
  379.      
  380.     -- Stab down
  381.     elseif battleFrame == 60 then    
  382.       playSFX (22)
  383.       battleFrame = battleFrame + 1
  384.      
  385.     elseif battleFrame < 120 then
  386.       if broadswordNPC.y + 200000 < -225  then
  387.         npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_ATTACK6
  388.         broadswordNPC.speedY = 64
  389.       else
  390.         shockwaveGenLNPC:mem (0x6C, FIELD_FLOAT, 100)
  391.         shockwaveGenRNPC:mem (0x6C, FIELD_FLOAT, 100)
  392.         battleFrame = 120
  393.       end
  394.    
  395.     else
  396.       battlePhase = 3
  397.       battleFrame = 0
  398.     end
  399.    
  400.    
  401.   -- PHASE 4: VULNERABLE ---------------------------------------------------------------------
  402.   elseif battlePhase == 3  then
  403.     battleFrame = battleFrame + 1
  404.    
  405.     if     battleFrame < 240 then
  406.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_DEFEAT
  407.     else
  408.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_JUMP
  409.       forceNPCJump (broadswordNPC, 4)
  410.       forceNPCWalkToPlayer (broadswordNPC, -4)
  411.       battlePhase = 0
  412.       battleFrame = 0
  413.     end
  414.  
  415.  
  416.    
  417.   -- PHASE 30: DEFEAT SEQUENCE ------------------------------------------------------------------------------
  418.   elseif battlePhase == 30  then
  419.     battleFrame = battleFrame + 1
  420.  
  421.     if     battleFrame   ==   1 then
  422.       npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_DEFEAT
  423.       playSFX ("voice_defeat.wav")
  424.       triggerEvent("End Battle")
  425.     elseif battleFrame   == 120 then
  426.       cutscenePhase = 2
  427.       battleFrame = 0
  428.       cutsceneFrame = 0
  429.     end
  430.   end
  431. end
  432.  
  433. function postBattleEvents ()  
  434.  
  435.   -- Make the boss invincible during the cutscene
  436.   collisionANPC:mem (0x46, FIELD_WORD, 0xFFFF)
  437.  
  438.   -- Disable the shockwave generators
  439.   shockwaveGenLNPC:mem (0x6C, FIELD_FLOAT, 0)
  440.   shockwaveGenRNPC:mem (0x6C, FIELD_FLOAT, 0)
  441.  
  442.   -- Cutscene events
  443.   if     cutsceneFrame <=    1 then
  444.     playerInputActive = false
  445.  
  446.   elseif cutsceneFrame  <   60 then
  447.     setDialogRules (true, true, true, 1)
  448.     npcAnimStates[NPCID_BROADSWORD] = ANIMSTATE_IDLE
  449.    
  450.     --forceNPCWalkToX (broadswordNPC, 600-200000, 2);
  451.     --forceNPCWalkToX (player, 600-200000, 2);
  452.  
  453.   elseif cutsceneFrame ==   60 then
  454.     player.x = 200-200000
  455.     broadswordNPC.x = 600-200000
  456.     forceNPCWalkLeft (broadswordNPC, 0);
  457.     --playSFX("voice_talk1.wav");
  458.  
  459.   elseif cutsceneFrame ==   61 then
  460.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "I daresay, that was a most exhilarating    scuffle! Bravo!", 30, 30, "voice_talk1.wav")
  461.  
  462.   elseif cutsceneFrame ==   62 then
  463.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "As per our wager, the titanic tomato is    now yours. Treasure it always!", 30, 30, "")
  464.  
  465.   elseif cutsceneFrame ==   63 then
  466.     forceNPCJump (broadswordNPC, 6);
  467.     triggerEvent("Reveal Leek")
  468.  
  469.   elseif cutsceneFrame  <   67 then
  470.     -- EMPTY SPACE
  471.  
  472.   elseif cutsceneFrame ==   67 then
  473.     triggerEvent("Reveal Leek")
  474.  
  475.   elseif cutsceneFrame  <  120 then
  476.     -- EMPTY SPACE
  477.  
  478.   elseif cutsceneFrame ==  120 then
  479.     --playSFX("voice_talk3.wav");
  480.  
  481.   elseif cutsceneFrame ==  121 then
  482.   forceNPCWalkRight (broadswordNPC, 0)
  483.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "And with that, I must take my leave. There is still much adventuring to do! Cheerio!", 30, 30, "voice_talk3.wav")
  484.  
  485.   elseif cutsceneFrame  <  180 then  
  486.   forceNPCWalkRight (broadswordNPC, 2)
  487.  
  488.   elseif cutsceneFrame  <  240 then  
  489.   forceNPCWalkRight (broadswordNPC, 0)
  490.  
  491.   elseif cutsceneFrame ==  240 then
  492.     --playSFX("voice_talk4.wav");
  493.  
  494.   elseif cutsceneFrame ==  241 then
  495.     forceNPCWalkLeft (broadswordNPC, 0)
  496.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "Ah, one more thing.", 30, 30, "voice_talk4.wav")
  497.  
  498.   elseif cutsceneFrame ==  242 then
  499.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "My brothers are...", 30, 30, "")
  500.  
  501.   elseif cutsceneFrame ==  243 then
  502.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "...", 30, 30, "")
  503.  
  504.   elseif cutsceneFrame ==  244 then
  505.     forceNPCWalkRight (broadswordNPC, 0);
  506.     startDialog  (NPCID_BROADSWORD, "Uncle Broadsword", "Ah, what am I doing? Spoilers, Augustus!   Spoilers!", 30, 30, "")
  507.  
  508.   elseif cutsceneFrame  <  360 then
  509.     forceNPCWalkRight (broadswordNPC, 4);
  510.  
  511.   elseif cutsceneFrame ==  360 then
  512.     playerInputActive = true
  513.   end
  514. end
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522. -- PLEASE DO NOT TAMPER WITH THESE FUNCTIONS, THANK YOU ----------------------------
  523. function onLoad ()
  524.   -- Filter the player to big
  525.   player.powerup = math.max(player.powerup, 2)
  526.  
  527.   -- Set the boss' HP to 8
  528.   bossHP = 8
  529.  
  530.   dialogSpeaker = 0
  531.  
  532.   dialogTextTime = 0
  533.   dialogSpeakerTime = 0
  534.  
  535.   dialogName = ""
  536.   dialogText = ""
  537.   dialogTextLine1 = ""
  538.   dialogTextLine2 = ""
  539.   dialogTextLine3 = ""
  540.   dialogTextLine4 = ""
  541.   dialogTextFull = ""
  542.  
  543.  
  544.   dialogSkippable = true
  545.   dialogPause = true
  546.   dialogEndWithInput = true
  547.  
  548.   cutsceneFrame = 0
  549.  
  550.   setDialogRules(true, true, true, 1)
  551. end
  552.  
  553.  
  554.  
  555. function onLoop()
  556.   -- Get references
  557.   donutGenNPC   = findnpcs(NPCID_DONUTGEN,   -1)[0]
  558.   shockwaveGenLNPC   = findnpcs(NPCID_SHOCKWAVEGEN,   -1)[0]
  559.   shockwaveGenRNPC   = findnpcs(NPCID_SHOCKWAVEGEN,   -1)[1]
  560.   broadswordNPC = findnpcs(NPCID_BROADSWORD, -1)[0]
  561.   collisionANPC  = findnpcs(NPCID_COLLISIONA,  -1)[0]
  562.   collisionBNPC  = findnpcs(NPCID_COLLISIONB,  -1)[0]
  563.  
  564.   -- player input during cutscenes
  565.   freezePlayerInput ()
  566.  
  567.  
  568.   -- Shockwave generators
  569.   if (shockwaveGenLNPC ~= nil) then
  570.     shockwaveGenLNPC.x = broadswordNPC.x-64
  571.     shockwaveGenLNPC.y = broadswordNPC.y+32
  572.   end  
  573.  
  574.   if (shockwaveGenRNPC ~= nil) then
  575.     shockwaveGenRNPC.x = broadswordNPC.x+64
  576.     shockwaveGenRNPC.y = broadswordNPC.y+32
  577.   end  
  578.  
  579.  
  580.   -- Snap the collision dummy A to Broadsword
  581.   if (collisionANPC ~= nil) then
  582.     collisionANPC.x = broadswordNPC.x
  583.     collisionANPC.y = broadswordNPC.y
  584.    
  585.     -- If the boss is out of health, begin the win sequence and lead into the post-battle cutscene
  586.     if (bossHP <= 0  and  battlePhase ~= 30) then
  587.       collisionANPC:mem (0x46, FIELD_WORD, 0xFFFF)
  588.       battlePhase = 30
  589.       battleFrame = 0
  590.     end
  591.   end
  592.  
  593.   -- Quickly reset the collision dummy B and reduce the boss HP counter
  594.   if (collisionBNPC ~= nil) then
  595.     bossHP = bossHP - 1
  596.     playSFX ("voice_hurt1.wav")
  597.    
  598.     if battlePhase == 3  then
  599.       battleFrame = battleFrame + 30
  600.     end
  601.  
  602.    
  603.     -- Speed up the music toward the end
  604.     if (bossHP == 2) then
  605.       triggerEvent("Ramp Up Music")
  606.     end
  607.     collisionBNPC:mem (0xE2, FIELD_WORD, NPCID_COLLISIONA)
  608.   end
  609.  
  610.   -- Snap the donut generator to Broadsword
  611.   if (donutGenNPC ~= nil) then
  612.     donutGenNPC.x = broadswordNPC.x
  613.     donutGenNPC.y = broadswordNPC.y
  614.   end
  615.  
  616.  
  617.   -- Turn all rinkas into _____
  618.   allNPCs = findnpcs(210,player.section)
  619.   for k,v in pairs(allNPCs) do
  620.     v.speedY = -8
  621.     v:mem (0xE2, FIELD_WORD, 30)
  622.     if (v:mem (0x136, FIELD_WORD) == FFFF) then
  623.       v.speedX = 4 * getNPCRelativeDirX (v)
  624.     end
  625.   end
  626.  
  627.  
  628.  
  629.   -- Test text
  630.   --printText("SPEAKER="..tostring(dialogSpeaker), 10, 10)
  631.   --printText("TIME="..tostring(cutsceneFrame), 10, 30)
  632.    
  633.   -- Trigger sequenced cutscene events
  634.   processCutscene()
  635.  
  636.   -- Control specific NPC talking/idle animations
  637.   controlNPCAnimation (NPCID_BROADSWORD, animData_Broadsword)
  638.  
  639.   -- Control dialogue display
  640.   processDialog()
  641.  
  642.   defineKeyTerms()
  643. end
  644.  
  645.  
  646. function freezePlayerInput ()
  647.   --[[
  648.   if  playerInputActive == false   then
  649.     player:mem(0x04, FIELD_WORD, 1)
  650.     player:mem(0x06, FIELD_WORD, 0)
  651.    
  652.     player:mem(0xF2, FIELD_WORD, 0)
  653.     player:mem(0xF4, FIELD_WORD, 0)
  654.     player:mem(0xF6, FIELD_WORD, 0)
  655.     player:mem(0xF8, FIELD_WORD, 0)
  656.     player:mem(0xFA, FIELD_WORD, 0)
  657.     player:mem(0xFC, FIELD_WORD, 0)
  658.     player:mem(0x100, FIELD_WORD, 0)
  659.    
  660.     player:mem(0x118, FIELD_WORD, 0)
  661.     player:mem(0x11E, FIELD_WORD, 0)
  662.     player:mem(0x120, FIELD_WORD, 0)
  663.   else
  664.     player:mem(0x04, FIELD_WORD, 0)
  665.     player:mem(0x06, FIELD_WORD, 1)
  666.   end  
  667.   --]]
  668. end
  669.  
  670.  
  671.  
  672.  
  673. function onKeyDown (keycode)
  674.   -- Skip dialog if allowed
  675.   if(keycode == KEY_X  and  dialogEndWithInput == true  and  (dialogTextTime > 0  or  dialogSpeakerTime > 0))then
  676.     playSFX(23) -- 10 = skid, 14 = coin, 23 = shckwup
  677.     endDialogLine()
  678.   end  
  679. end
  680.  
  681.  
  682.  
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689.  
  690. -- NPC COMMANDS ---------------------------------------------------------------------------------
  691.  
  692. -- Jump --
  693. function forceNPCJump (myNPC, jumpStrength)
  694.   myNPC.speedY = -1 * jumpStrength
  695.   playSFX(1)
  696. end
  697.  
  698. -- Walk --
  699. function forceNPCWalkToPlayer (myNPC, speed)
  700.   local dirToPlayerX = getNPCRelativeDirX (myNPC)
  701.  
  702.   if dirToPlayerX == DIR_LEFT then
  703.     forceNPCWalkLeft (myNPC, speed)
  704.   else
  705.     forceNPCWalkRight (myNPC, speed)
  706.   end
  707.  
  708.   local tempSpeedX = myNPC.speedX
  709.   myNPC.direction = dirToPlayerX
  710.   myNPC.speedX = tempSpeedX
  711. end
  712.  
  713. function forceNPCWalkToX (myNPC, destX, speed)
  714.   local dirToX = DIR_LEFT
  715.  
  716.   if (myNPC.x - destX < 0) then
  717.      dirToX = DIR_RIGHT
  718.   end
  719.  
  720.   if dirToPlayerX == DIR_LEFT then
  721.     forceNPCWalkLeft (myNPC, speed)
  722.   else
  723.     forceNPCWalkRight (myNPC, speed)
  724.   end
  725.  
  726.   local tempSpeedX = myNPC.speedX
  727.   myNPC.direction = dirToPlayerX
  728.   myNPC.speedX = tempSpeedX
  729. end
  730.  
  731.  
  732. function forceNPCWalkForward (myNPC, speed)
  733.   myNPC.speedX = myNPC.direction * speed
  734. end
  735.  
  736.  
  737. function forceNPCWalkLeft (myNPC, speed)  
  738.   myNPC.direction = DIR_LEFT
  739.   myNPC.speedX = -1*speed
  740.  
  741.   setAnimStateByMovement (myNPC, myNPC.id)
  742. end
  743.  
  744. function forceNPCWalkRight (myNPC, speed)
  745.   myNPC.direction = DIR_RIGHT
  746.   myNPC.speedX = speed
  747.  
  748.   setAnimStateByMovement (myNPC, myNPC.id)
  749. end
  750.  
  751.  
  752.  
  753. function setAnimStateByMovement (myNPC, npcid)
  754.  
  755.   -- Don't disrupt unique animations
  756.   if npcAnimStates[npcid] < ANIMSTATE_ATTACK1 then
  757.  
  758.     -- If on ground
  759.     if    myNPC.speedY == 0 then
  760.       if    math.abs(myNPC.speedX) < 1 then
  761.         if    dialogSpeaker == npcid   then
  762.           npcAnimStates[npcid] = ANIMSTATE_TALK
  763.         else
  764.           npcAnimStates[npcid] = ANIMSTATE_IDLE
  765.         end
  766.       else
  767.         npcAnimStates[npcid] = ANIMSTATE_WALK
  768.       end
  769.  
  770.     -- If jumping or falling
  771.     elseif  myNPC.speedY > 0 then
  772.       npcAnimStates[npcid] = ANIMSTATE_FALL
  773.     else
  774.       npcAnimStates[npcid] = ANIMSTATE_JUMP
  775.     end
  776.   end
  777. end
  778.  
  779.  
  780. -- Accelerate --
  781. function accelNPCX (npcid, horzAccel)
  782.   local myNPC = findnpcs(npcid, -1)[0]
  783.   myNPC.speedX = myNPC.speedX + horzAccel
  784. end
  785.  
  786. function accelNPCY (npcid, vertAccel)
  787.   local myNPC = findnpcs(npcid, -1)[0]
  788.   myNPC.speedY = myNPC.speedY + vertAccel
  789. end
  790.  
  791. -- Set speed --
  792. function setNPCSpeedX (npcid, horzAmount)
  793.   local myNPC = findnpcs(npcid, -1)[0]
  794.   myNPC.speedX = horzAmount
  795. end
  796.  
  797. function setNPCSpeedY (npcid, vertAmount)
  798.   local myNPC = findnpcs(npcid, -1)[0]
  799.   myNPC.speedY = vertAmount
  800. end
  801.  
  802. function setNPCPosX (npcid, xPos)
  803.   local myNPC = findnpcs(npcid, -1)[0]
  804.   myNPC.x = xPos
  805. end
  806.  
  807. function setNPCPosY (npcid, yPos)
  808.   local myNPC = findnpcs(npcid, -1)[0]
  809.   myNPC.y = yPos
  810. end
  811.  
  812. function setNPCPos (npcid, xPos, yPos)
  813.   setNPCPosX (npcid, xPos)
  814.   setNPCPosY (npcid, yPos)
  815. end
  816.    
  817.    
  818. -- CUTSCENE CONTROL FUNCTIONS ---------------------------------------------------------------------------------
  819.  
  820. function setDialogRules (pause, skippable, needInput, textSpeed)
  821.   dialogPause = pause
  822.   dialogSkippable = skippable
  823.   dialogEndWithInput = needInput
  824.   dialogTextSpeed = textSpeed
  825. end
  826.  
  827.  
  828. -- Character branching --
  829.  
  830. function branchByCharacter(demoTime, irisTime, koodTime, sheathTime, raocowTime)
  831.   local pID = getPlayerID()
  832.  
  833.   if     pID == 1 then cutsceneFrame = demoTime
  834.   elseif pID == 2 then cutsceneFrame = irisTime
  835.   elseif pID == 3 then cutsceneFrame = koodTime
  836.   elseif pID == 4 then cutsceneFrame = raocowTime
  837.   elseif pID == 5 then cutsceneFrame = sheathTime
  838.   else                
  839.     cutsceneFrame = triggerTime
  840.     printText("LOOP ERROR", 3, 400, 300)
  841.   end
  842. end
  843.  
  844.  
  845. function timedBranchByCharacter (triggerTime, demoTime, irisTime, koodTime, sheathTime, raocowTime)
  846.   if (cutsceneFrame == triggerTime) then
  847.     branchByCharacter (demoTime, irisTime, koodTime, sheathTime, raocowTime)
  848.   end
  849. end
  850.  
  851.  
  852. -- Random chance branching --
  853.  
  854. function branchRandom (percent, passFrame, failFrame)
  855.   if (math.random(0, 100) <= percent) then
  856.     cutsceneFrame = passFrame
  857.   else
  858.     cutsceneFrame = failFrame
  859.   end
  860. end
  861.  
  862. function timedBranchRandom (triggerTime, percent, passFrame, failFrame)
  863.   if (cutsceneFrame == triggerTime) then
  864.     branchRandom (percent, passFrame, failFrame)
  865.   end
  866. end
  867.  
  868.  
  869.  
  870. -- Time jumps --
  871.  
  872. function timedCutsceneTimeJump (triggerFrame, jumpToFrame)
  873.   if(cutsceneFrame == triggerFrame) then
  874.     cutsceneTimeJump(jumpToFrame)
  875.   end
  876. end
  877.  
  878. function cutsceneTimeJump (jumpToFrame)
  879.   cutsceneFrame = jumpToFrame
  880. end
  881.  
  882.  
  883.  
  884. -- Triggering dialog --
  885. function startDialog (speakerid, name, text, textTime, speakTime, sound)
  886.   if  dialogOn == false  and  sound ~= ""  then
  887.     playSFX (sound)
  888.   end  
  889.   triggerDialogSpeaker (speakerid, speakTime)
  890.   triggerDialogText (name, text, textTime)
  891.   dialogOn = true
  892. end
  893.  
  894.  
  895. function triggerDialogSpeaker (npcid, timeVal)
  896.   dialogSpeaker = npcid
  897.   dialogSpeakerTime = timeVal
  898. end
  899.  
  900. function triggerDialogText (name,text,textTime)
  901.   dialogName = name
  902.   dialogTextFull = text
  903.   dialogTextTime = textTime
  904. end
  905.  
  906.  
  907.  
  908.  
  909.    
  910. -- CUTSCENE MANAGEMENT, DO NOT TOUCH ---------------------------------------------------------------------------------
  911.  
  912. function defineKeyTerms()
  913.   local pID = getPlayerID()
  914.  
  915.   if     pID == 0 then KEYTERM_PLAYERNAME = "NOBODY"
  916.   elseif pID == 1 then KEYTERM_PLAYERNAME = "Demo"
  917.   elseif pID == 2 then KEYTERM_PLAYERNAME = "Iris"
  918.   elseif pID == 3 then KEYTERM_PLAYERNAME = "Kood"
  919.   elseif pID == 4 then KEYTERM_PLAYERNAME = "raocow"
  920.   elseif pID == 5 then KEYTERM_PLAYERNAME = "Sheath"
  921.   end
  922. end
  923.  
  924.  
  925. function processCutscene()
  926.   if (dialogPause == false  or  dialogTextTime <= 0) then
  927.     cutsceneFrame = cutsceneFrame + 1
  928.   end
  929.  
  930.   -- Pre-battle cutscene
  931.   if cutscenePhase == 0 then
  932.     preBattleEvents ()
  933.  
  934.   -- Boss battle attack pattern
  935.   elseif cutscenePhase == 1 then
  936.     bossBattleEvents ()
  937.  
  938.   -- Post-battle cutscene
  939.   elseif cutscenePhase == 2 then
  940.     postBattleEvents ()
  941.   end
  942. end
  943.  
  944.  
  945.  
  946. function processDialog ()
  947.  
  948.   -- Display the text only revealed by the typewriter effect
  949.   local currentCharNum = math.floor (dialogNumCharsCurrent)
  950.  
  951.   dialogText = string.sub (dialogTextFull, 0, currentCharNum)
  952.   local currentChar = string.sub (dialogTextFull, currentCharNum-1, currentCharNum)
  953.  
  954.   -- Decrement the dialogue timer and increment the typewriter effect.
  955.   if (dialogTextTime > 0) then
  956.     dialogTextTime = dialogTextTime - 1
  957.  
  958.     if (dialogNumCharsCurrent < string.len (dialogTextFull)) then
  959.       dialogNumCharsCurrent = dialogNumCharsCurrent + dialogTextSpeed
  960.       --if (currentChar ~= " "  and  dialogNumCharsCurrent % 2 == 0) then
  961.       --playSFX (35) -- 10 = skid, 14 = coin, 23 = shckwup, 24 = boing, 26 = skittish ticking, 29 = menu option, 33 = whoosh, 35 = blip
  962.       --end
  963.     end
  964.  
  965.    
  966.     -- While the dialogue timer counts down, display the dialogue.
  967.     printText(dialogName..":", 4, 5, 475)  
  968.     printText(string.sub(dialogText, 0, 43), 4, 15, 495)
  969.     printText(string.sub(dialogText, 44, 87), 4, 15, 515)
  970.     printText(string.sub(dialogText, 88, 131), 4, 15, 535)
  971.     printText(string.sub(dialogText, 132, 175), 4, 15, 555)
  972.    
  973.     if(dialogEndWithInput == true)then
  974.       printText("(PRESS X TO CONTINUE)", 4, 400, 580)
  975.     end
  976.   end
  977.  
  978.  
  979.   -- When the speaker timer reaches zero, reset the speaker.
  980.   dialogSpeakerTime = dialogSpeakerTime - 1
  981.  
  982.   if(dialogSpeakerTime == 0)then
  983.     dialogSpeaker = 0
  984.   end
  985. end
  986.  
  987.  
  988. function endDialogLine()
  989.   dialogOn = false
  990.   dialogTextTime = 0
  991.   dialogNumCharsCurrent = 0
  992.   dialogSpeakerTime = 0
  993.   dialogSpeaker = 0
  994. end
  995.  
  996.  
  997.  
  998. function controlNPCAnimation (npcid, animDataTable)
  999.   local state = npcAnimStates[npcid]
  1000.   local boundsString = animDataTable[state]
  1001.   local dashCharPos = string.find(boundsString, "-")
  1002.   local minVal = tonumber(string.sub(boundsString, 0, dashCharPos-1))
  1003.   local maxVal = tonumber(string.sub(boundsString, dashCharPos+1))
  1004.  
  1005.   clampNPCAnim (npcid, minVal, maxVal, animDataTable[ANIMSTATE_NUMFRAMES])
  1006. end
  1007.  
  1008.  
  1009. function getNPCAnimFrame (myNPC)
  1010.   return myNPC:mem (0xE4, FIELD_WORD)
  1011. end
  1012.  
  1013.  
  1014. function setNPCAnimFrame(myNPC, frame)
  1015.   myNPC:mem(0xE4, FIELD_WORD, frame)
  1016. end
  1017.  
  1018.  
  1019. function clampNPCAnim(npcid, minVal, maxVal, dirOffsetFrames)
  1020.   local myNPC = findnpcs(npcid, -1)[0]
  1021.  
  1022.   -- Add an offset for flipped animations
  1023.   local dirOffset = dirOffsetFrames
  1024.   if(myNPC.direction == DIR_LEFT)then
  1025.     dirOffset = 0
  1026.   end
  1027.  
  1028.   -- Get the current animation frame
  1029.   animFrame = getNPCAnimFrame(myNPC)
  1030.  
  1031.   --printText(tostring(npcid).." ("..tostring(math.floor (myNPC.x+200000))..", "..tostring(math.floor (myNPC.y+200000))..")", 3, 10, 40+20*(npcid-100))
  1032.   --printText(tostring(npcid).." FRAMES > "..tostring(minVal)..", "..tostring(animFrame)..", "..tostring(maxVal), 3, 10, 10+80*(npcid-100))
  1033.   --printText("ANIMSTATE: "..tostring(npcAnimStates[npcid])..", X = "..tostring(myNPC.x), 3, 10, 30+80*(npcid-100))
  1034.   --printText("WALL "..tostring(getNPCWallDistance(npcid)), 3, 10, 50+80*(npcid-100))
  1035.   --printText("PLAYER "..tostring(getNPCRelativePosX(npcid)), 3, 10, 70+80*(npcid-100))
  1036.  
  1037.  
  1038.   if (animFrame < (minVal+dirOffset)  or  animFrame > (maxVal+dirOffset))then
  1039.     setNPCAnimFrame(myNPC, minVal+dirOffset)
  1040.   end
  1041. end
  1042.  
  1043.  
  1044.  
  1045. function printCenteredText (text, font, xPos, yPos)
  1046.   printText (text, font, xPos-9*string.len(text), yPos)
  1047. end
  1048.  
  1049.  
  1050. function getPlayerID()
  1051.   return player:mem(0xF0, FIELD_WORD)
  1052. end
  1053.  
  1054.  
  1055. function getNPCRelativePosX (myNPC)
  1056.   return (myNPC.x - player.x)
  1057. end
  1058.  
  1059.  
  1060.  
  1061. function getNPCRelativeDirX (myNPC)
  1062.   if (getNPCRelativePosX (myNPC) < 0) then
  1063.     return DIR_RIGHT
  1064.   else
  1065.     return DIR_LEFT
  1066.   end
  1067. end
  1068.  
  1069.  
  1070. function getNPCWallClosest (myNPC)
  1071.   local wallX = -200000
  1072.  
  1073.   if getNPCRelativeDirX(myNPC) == DIR_LEFT then
  1074.     wallX = 800 - 200000
  1075.   end
  1076.  
  1077.   return wallX
  1078. end
  1079.  
  1080.  
  1081. function getNPCWallFacing (myNPC)
  1082.   local wallX = -200000
  1083.  
  1084.   if myNPC.direction == DIR_RIGHT then
  1085.     wallX = 800 - 200000
  1086.   end
  1087.  
  1088.   return wallX
  1089. end
  1090.  
  1091.  
  1092.  
  1093.  
  1094. function getNPCWallDistance (myNPC, wallX)  
  1095.   return math.abs(myNPC.x - wallX)
  1096. end
  1097.  
  1098.  
  1099. -- Clamps a number to within a certain range, with optional rounding
  1100. function math.clamp (low, n, high)
  1101.   return math.min(math.max(n, low), high)
  1102. end
  1103.  
  1104.  
  1105. function getNPCAnimFrame (tarNPC)
  1106.   return tarNPC:mem(0xE4, FIELD_WORD)
  1107. end
  1108.  
  1109. function setNPCAnimFrame (tarNPC, val)
  1110.   tarNPC:mem(0xE4, FIELD_WORD, val)
  1111. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement