SHARE
TWEET

FF6 BizHawk LUA Info Overlay

a guest Jan 26th, 2020 149 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- Used with "BizHawk" emulator - load ROM -> Tools -> Lua Console -> Script -> Open Script -> double-click until green play sign
  2.  
  3. -- Displays hints for Rages, Dances, Sketch, Control, and Steal/Mug (or Fight with ThiefKnife-effect).
  4. -- To display extended Rage information, hold X or Y while hovering over the Rage.
  5.  
  6. -- Enable or disable the overlay with [R+SELECT]. Haven't played with this mod yet, so
  7. -- you may end up seeing overlay popups during the normal game at odd times, hence the hotkey.
  8.  
  9. -- mod type for offsets, works off of the 'rom name' (what it says in title bar/saves games as)
  10. -- if your rom isn't detected just add it in this format (including the , and any " marks):
  11. -- ["ROM NAME"] = romtype,
  12. -- where romtype is one of these: nil, "ROTDS", "BNW"
  13. -- any other romtype will use nil (vanilla) settings
  14.  
  15. local MODS = {
  16.  
  17. ["Final Fantasy III (USA)"]     = nil,     -- vanilla, default. -- means comments
  18. ["Return of the Dark Sorcerer"] = "ROTDS", -- uses rotds extended item/spell names
  19. ["Brave New World 2.0"]         = "BNW",   -- mod'd dance chance
  20. ["FFVI T Edition"]              = "japan", -- nothing yet, the version is stripped further down
  21.  
  22. }
  23.  
  24. --- =======================
  25. --- all settings are above this
  26. --- =======================
  27.  
  28.  
  29.  
  30. local romname = gameinfo.getromname()
  31.  
  32. -- t-edition has ever-changing patch number on the end
  33. if (romname:sub(1,14) == "FFVI T Edition") then romname = "FFVI T Edition" end
  34. local MOD_TYPE = MODS[romname]
  35. function initialize()
  36.      gui.defaultPixelFont("fceux")
  37.     -- vanilla
  38. -- offset start, text length, index start
  39.     offNames = {
  40.         spells = { 0x26F567, 7, 0 },
  41.         espers = { 0x26F6E1, 8, 54 },
  42.        attacks = { 0x26F7B9, 10, 81 },
  43.     espattacks = { 0x26FE8F, 10, 256 },
  44.         dances = { 0x26FF9D, 12, 283 },
  45. }
  46.     offMonsterData = 0xF0000
  47.     lenMonsterData = 32
  48.     offItemNames = 0x12B300
  49.     lenItemNames = 13
  50.     if (MOD_TYPE == "ROTDS") then
  51.         offNames.spells = { 0x316100, 9, 0 }
  52.         offNames.espers = { 0x3162E6, 12, 54 }
  53.         offNames.attacks = { 0x31645E, 16, 81 }
  54.         offNames.espattacks = { 0x316DDE, 16, 256 }
  55.         offNames.dances = { 0x3170FE, 13, 283 }
  56.         lenItemNames = 13
  57.     end
  58. end
  59. initialize()
  60.  
  61. -- maps each font byte to the appropriate character, FF should break loop, space for anything else
  62. local fontMap = { [0x80] = "A", [0x81] = "B", [0x82] = "C", [0x83] = "D", [0x84] = "E", [0x85] = "F", [0x86] = "G", [0x87] = "H", [0x88] = "I", [0x89] = "J", [0x8A] = "K", [0x8B] = "L", [0x8C] = "M", [0x8D] = "N", [0x8E] = "O", [0x8F] = "P", [0x90] = "Q", [0x91] = "R", [0x92] = "S", [0x93] = "T", [0x94] = "U", [0x95] = "V", [0x96] = "W", [0x97] = "X", [0x98] = "Y", [0x99] = "Z", [0x9A] = "a", [0x9B] = "b", [0x9C] = "c", [0x9D] = "d", [0x9E] = "e", [0x9F] = "f", [0xA0] = "g", [0xA1] = "h", [0xA2] = "i", [0xA3] = "j", [0xA4] = "k", [0xA5] = "l", [0xA6] = "m", [0xA7] = "n", [0xA8] = "o", [0xA9] = "p", [0xAA] = "q", [0xAB] = "r", [0xAC] = "s", [0xAD] = "t", [0xAE] = "u", [0xAF] = "v", [0xB0] = "w", [0xB1] = "x", [0xB2] = "y", [0xB3] = "z", [0xB4] = "0", [0xB5] = "1", [0xB6] = "2", [0xB7] = "3", [0xB8] = "4", [0xB9] = "5", [0xBA] = "6", [0xBB] = "7", [0xBC] = "8", [0xBD] = "9", [0xBE] = "!", [0xBF] = "?", [0xC3] = "'", [0xC4] = "-", [0xC5] = ".", }
  63.  
  64. local monSpecials = {
  65. [0x00]="+Darkness", [0x01]="+Zombie", [0x02]="+Poison", [0x03]="+Magitek", [0x04]="+Invis", [0x05]="+Imp", [0x06]="+Stone", [0x07]="+Death", [0x08]="+Doom", [0x09]="+Critical", [0x0A]="+Blink", [0x0B]="+Silence", [0x0C]="+Berserk", [0x0D]="+Confuse", [0x0E]="+Sap", [0x0F]="+Sleep", [0x10]="+Dance", [0x11]="+Regen", [0x12]="+Slow", [0x13]="+Haste", [0x14]="+Stop", [0x15]="+Shell", [0x16]="+Protect", [0x17]="+Reflect", [0x18]="+Rage", [0x19]="+Frozen", [0x1A]="+Reraise", [0x1B]="+Morph", [0x1C]="+Spellcast", [0x1D]="+Flee", [0x1E]="+Interceptor", [0x1F]="+Float", [0x20]=" Damage + 50%", [0x21]=" Damage +100%", [0x22]=" Damage +150%", [0x23]=" Damage +200%", [0x24]=" Damage +250%", [0x25]=" Damage +300%", [0x26]=" Damage +350%", [0x27]=" Damage +400%", [0x28]=" Damage +450%", [0x29]=" Damage +500%", [0x2A]=" Damage +550%", [0x2B]=" Damage +600%", [0x2C]=" Damage +650%", [0x2D]=" Damage +700%", [0x2E]=" Damage +750%", [0x2F]=" Damage +800%",
  66. }
  67. function hexformat(input) return string.format("%02x", input):upper() end
  68. function trim(out) return (out:gsub("^%s*(.-)%s*$", "%1")) end
  69. -- skipFF to anything to prevent breaking on FF
  70. function translate(byteTable,skipFF)
  71.     local out = ""
  72.     local start = 0
  73.     if (not byteTable[start]) then start = 1 end
  74.     for i=start,#byteTable do
  75.         local hex = byteTable[i]
  76.         if ((hex == 0xFF or not hex) and not skipFF) then break end
  77.         if (fontMap[hex]) then
  78.             out = out .. fontMap[hex]
  79.         else
  80.             out = out .. " "
  81.         end
  82.     end
  83.     out = trim(out)
  84.     return out
  85. end
  86. function getStatuses(byteA,byteB,byteC)
  87.     local statuses = { {"Blind", "Zombi", "Poisn", "M-Tek", "Invis", "Imp  ", "Stone", "Death"},
  88.                        {"Doom ", "Hurt ", "Image", "Mute ", "Brsrk", "Muddl", "Sap  ", "Sleep"},
  89.                        {"Float", "Regen", "Slow ", "Haste", "Stop ", "Shell", "Safe ", "Rflct"} }
  90.     local outStatuses = {}
  91.     for _,byte in pairs({ byteA, byteB, byteC }) do
  92.         for i=1,#statuses[_] do
  93.             if (bit.band(byte,bit.lshift(1,(i-1))) > 0) then
  94.                 outStatuses[#outStatuses+1] = statuses[_][i]
  95.             end
  96.         end
  97.     end
  98.     local out = ""
  99.     for _,v in pairs(outStatuses) do
  100.         out = out .. v .. " "
  101.         if (_ % 6 == 0) then out = out .. "\n      " end
  102.     end
  103.     return trim(out)
  104. end
  105. function getElements(byte)
  106.     local elements = { "FIR", "ICE", "THN", "POI", "WND", "HLY", "ERT", "WTR" }
  107.     local outElements = {}
  108.     for i=1,#elements do
  109.         if (bit.band(byte,bit.lshift(1,(i-1))) > 0) then
  110.             outElements[#outElements+1] = elements[i]
  111.         end
  112.     end
  113.     local out = ""
  114.     for _,v in pairs(outElements) do
  115.         out = out .. v .. " "
  116.         --if (_ % 5 == 0) then out = out .. "\n" end
  117.     end
  118.     return trim(out)
  119. end
  120. function getSpellName(index)
  121.     local type = nil
  122.     if (index >= offNames.dances[3]) then type = offNames.dances
  123.     elseif (index >= offNames.espattacks[3]) then type = offNames.espattacks
  124.     elseif (index >= offNames.attacks[3]) then type = offNames.attacks
  125.     elseif (index >= offNames.espers[3]) then type = offNames.espers
  126.     else type = offNames.spells
  127.     end
  128.     local beginOffset = type[1]
  129.     local textLength = type[2]
  130.     local startSkillIndex = type[3]
  131.     local firstByte = beginOffset + ((index-startSkillIndex)*textLength)
  132.     local out = memory.readbyterange(firstByte,textLength,"CARTROM")
  133.     out = translate(out)
  134.     return out
  135. end
  136. function getItemName(index)
  137.     local out = memory.readbyterange(offItemNames + (index*lenItemNames),lenItemNames,"CARTROM")
  138.     out = translate(out,"don't-break-on-FF")
  139.     if (out == "") then out = "(None)" end
  140.     return out
  141. end
  142. local cursor_state = nil
  143. local inputs = { { nil, nil, nil, nil, "R", "L", "X", "A", },
  144.                  { "Right", "Left", "Down", "Up", "Start", "Select", "Y", "B" } }
  145. local keymap = {}
  146. local keymapLastFrame = {}
  147.  
  148. function buttonHandler()
  149.     -- X is at 0x0A as the 7th bit (0x40), Y is at 0x0B same
  150.     local input1 = memory.readbyte(0x04,"WRAM")
  151.     local input2 = memory.readbyte(0x05,"WRAM")
  152.     if (input1 == 0x00 and input2 == 0x00) then
  153.         input1 = memory.readbyte(0x0A)
  154.         input2 = memory.readbyte(0x0B)
  155.     end
  156.     keymapLastFrame = keymap
  157.     keymap = {}
  158.     for _,byte in pairs({ input1, input2 }) do
  159.         for i=1,#inputs[_] do
  160.             if (inputs[_][i] ~= nil) then
  161.                 if (bit.band(byte,bit.lshift(1,(i-1))) > 0) then
  162.                     keymap[inputs[_][i]] = true
  163.                 end
  164.             end
  165.         end
  166.     end
  167. end
  168.  
  169. function checkIfHelpButton()
  170.     -- X is at 0x0A as the 7th bit (0x40), Y is at 0x0B same
  171.     if (keymap["X"] or keymap["Y"] or keymapLastFrame["X"] or keymapLastFrame["Y"]) then return true end
  172.     return false
  173. end
  174.  
  175. local enabledToggle = true
  176. local messageStartTime = 0
  177. local messageText = ""
  178. local messageDuration = 0
  179. function disabledCheck()
  180.     if (keymap["Select"] and keymap["R"] and not (keymapLastFrame["R"] and keymapLastFrame["Select"])) then
  181.         enabledToggle = not enabledToggle
  182.         if (enabledToggle) then message("Overlay enabled.",4)
  183.         else message("Overlay disabled.", 4)       
  184.         end
  185.     end
  186. end
  187. function message(msg,duration)
  188.     messageStartTime = os.time()
  189.     messageText = msg
  190.     messageDuration = duration
  191. end
  192. function messageCheck()
  193.     messageTime = os.time()
  194.     if (messageTime < (messageStartTime + messageDuration)) then
  195.         gui.drawText(0,210,messageText,"white","black")
  196.     end
  197. end
  198. function processEnemySpecial(idxTargetMonster)
  199.     local monStats = memory.readbyterange(offMonsterData + (lenMonsterData * idxTargetMonster),lenMonsterData,"CARTROM")
  200.     local specialAttack = monStats[0x1F]
  201.     local noEvade = (bit.band(specialAttack,0x80) > 0)
  202.     local noDamage = (bit.band(specialAttack,0x40) > 0)
  203.     specialAttack = bit.band(specialAttack,0x3F)
  204.     specialAttack = monSpecials[specialAttack]
  205.     if (specialAttack) then
  206.         if (noEvade or noDamage) then
  207.             specialAttack = specialAttack..")\n(Special:"
  208.             if (noEvade) then specialAttack = specialAttack .. "Can't dodge" end
  209.             if (noEvade and noDamage) then specialAttack = specialAttack .. " & " end
  210.             if (noDamage) then specialAttack = specialAttack .. "No damage" end
  211.         end
  212.     else
  213.         specialAttack = "+???"
  214.     end
  215.     return "(Special:Attack"..specialAttack..")"
  216. end
  217. local hintLoc = { x = 8, y = 142, height = 9 }
  218. function printHint(msg)
  219.     local _, extraLineCount = msg:gsub('\n', '\n')
  220.     gui.pixelText(hintLoc.x,hintLoc.y-(hintLoc.height * extraLineCount),msg,"white")
  221. end
  222. function doStealStuff(targetted_monster)
  223.     local stealLoc = 0x3310 + (2*targetted_monster)
  224.     local rare_steal = memory.read_u8(stealLoc)
  225.     local common_steal = memory.read_u8(stealLoc+1)
  226.     local itemNames = { getItemName(common_steal), getItemName(rare_steal) }
  227.     if (common_steal == 0xFF) then itemNames[1] = "---" end
  228.     if (rare_steal   == 0xFF) then itemNames[2] = "---" end
  229.     local out = "Nothing to steal!"
  230.     if (itemNames[1] ~= "---" or itemNames[2] ~= "---") then
  231.         out = "Common Steal (7/8): "..itemNames[1].."\n  Rare Steal (1/8): "..itemNames[2]
  232.     end
  233.     return out
  234. end
  235. function main()
  236.     disabledCheck()
  237.     messageCheck()
  238.     if (not enabledToggle) then return end
  239.  
  240.  
  241.     local paused = memory.read_u8(0x62ab)
  242.     if (paused > 0) then
  243. -- should probably get a check so it ONLY works in battle
  244. --[[
  245.         -- show enemy health if paused
  246.         for i=0,5 do
  247.             local hp = memory.read_u16_le(0x3bfc + (2*i))
  248.             if (hp > 0) then
  249.                 local x = memory.read_u16_le(0x80c3 + (2*i)) -- monster loc x in pixels
  250.                 local y = memory.read_u16_le(0x80cf + (2*i)) -- monster loc y in pixels
  251.                 gui.drawText(x,y,hp)
  252.             end
  253.         end
  254. ]]--
  255.     end
  256.  
  257.     -- reads memory of 'cursor state' which appears to be the type of command being hovered over
  258.     local last_cursor_state = cursor_state
  259.     cursor_state = memory.read_u8(0x7bc2)
  260.     local which_character = memory.read_u8(0x62ca) -- offsets cursor info
  261.     local idxRecentCommand = memory.read_u8(0x890F + which_character) -- the command we're hovering on main menu
  262.     local recentCommandType = memory.read_u8(0x202E + (12*which_character) + (3*idxRecentCommand))
  263.     --23 = scrolling page up or down
  264.     if (cursor_state == 23 or cursor_state == 24) then cursor_state = last_cursor_state end
  265.     --30 = rage
  266.     if (cursor_state == 30) then
  267.         local rages = memory.readbyterange(0x257E,256)
  268.         local battleMenuColumn = 0x892F -- row and scrolled are derived from this (+4/-4)
  269.         local column = memory.read_u8(battleMenuColumn + which_character)
  270.         local row = memory.read_u8(battleMenuColumn + which_character + 4)
  271.         local scrolled = memory.read_u8(battleMenuColumn + which_character - 4)
  272.         local hoverRage = rages[((row+scrolled)*2) + column]
  273.         local menuClosing = (memory.read_u8(0x7BCB) > 0) -- get rid of little text-blink as rage menu closes
  274.         if (hoverRage < 255 and not menuClosing) then
  275.             local rageLoc = 0xF4600 + (2*hoverRage)
  276.             local rageAttacks = { memory.readbyte(rageLoc,"CARTROM"), memory.readbyte(rageLoc+1,"CARTROM") }
  277.             for i=1,2 do rageAttacks[i] = getSpellName(rageAttacks[i]) end --.."("..rageAttacks[i]..")" end
  278.             local monStats = memory.readbyterange(offMonsterData + (lenMonsterData * hoverRage),lenMonsterData,"CARTROM")
  279.             local out = "Rage: "..rageAttacks[1] .. "/" .. rageAttacks[2]
  280.             if (rageAttacks[2] == "Special" or rageAttacks[1] == "Special") then
  281.                 specialAttack = processEnemySpecial(hoverRage)
  282.                 out = specialAttack .. "\n"..out
  283.             end
  284.             printHint(out)
  285.             if (checkIfHelpButton()) then
  286.                 local blockedStatuses = { monStats[0x14], monStats[0x15], monStats[0x16] }
  287.                 local appliedStatuses = { monStats[0x1B], monStats[0x1C], monStats[0x1D] }
  288.                 local absorbElements = monStats[0x17]
  289.                 local immuneElements = monStats[0x18]
  290.                 local weakElements = monStats[0x19]
  291.                 local bytes = ""
  292.                 for i=0,#monStats do
  293.                     bytes = bytes .. " " .. hexformat(monStats[i])
  294.                     if ((i+1) % 8 == 0) then bytes = bytes .. "\n" end
  295.                 end
  296.                 local infoText = ""
  297.                 blockedStatuses = getStatuses(blockedStatuses[1],blockedStatuses[2],blockedStatuses[3])
  298.                 appliedStatuses = getStatuses(appliedStatuses[1],appliedStatuses[2],appliedStatuses[3])
  299.                 if (#appliedStatuses > 0) then infoText = infoText.."GAINS:"..appliedStatuses.."\n" end
  300.                 if (#blockedStatuses > 0) then infoText = infoText.. "BLOCK:"..blockedStatuses.."\n" end
  301.                 absorbElements = getElements(absorbElements)
  302.                 immuneElements = getElements(immuneElements)
  303.                 weakElements = getElements(weakElements)
  304.                 if (#absorbElements > 0) then infoText = infoText.. "ABS:"..absorbElements.."\n" end
  305.                 if (#immuneElements > 0) then infoText = infoText.. "IMM:"..immuneElements.."\n" end
  306.                 if (#weakElements > 0) then infoText = infoText.. "WEAK:"..weakElements.."\n" end
  307.                 infoText = trim(infoText)
  308.                 gui.pixelText(0,0,string.format("%-99s",infoText),"white")
  309.             end
  310.         end
  311.     -- dances
  312.     elseif (cursor_state == 33) then
  313.         local dances = memory.readbyterange(0x267E,8)
  314.         local battleMenuColumn = 0x8937 -- row and scrolled are derived from this (+4/-4)
  315.         local column = memory.read_u8(battleMenuColumn + which_character)
  316.         local row = memory.read_u8(battleMenuColumn + which_character + 4)
  317.         local scrolled = memory.read_u8(battleMenuColumn + which_character - 4)
  318.    
  319.         local hoverDance = dances[((row+scrolled)*2) + column]
  320.         local menuClosing = (memory.read_u8(0x7BCB) > 0) -- get rid of little text-blink as dance menu closes
  321.         if (hoverDance < 255 and not menuClosing) then
  322.             local danceLoc = 0xFFE80 + (4*hoverDance)
  323.             local danceAttacks = { memory.readbyte(danceLoc,"CARTROM"), memory.readbyte(danceLoc+1,"CARTROM"),
  324.                             memory.readbyte(danceLoc+2,"CARTROM"), memory.readbyte(danceLoc+3,"CARTROM") }
  325.             for i=1,4 do danceAttacks[i] = getSpellName(danceAttacks[i]) end
  326.             local danceChances = { 7, 6, 2, 1 }
  327.             if (MOD_TYPE == "BNW") then danceChances = { 7, 5, 3, 1 } end
  328.             local out = string.format("Dance: (%s/16) %s\n       (%s/16) %s\n       (%s/16) %s\n       (%s/16) %s", danceChances[1], danceAttacks[1], danceChances[2], danceAttacks[2], danceChances[3], danceAttacks[3], danceChances[4], danceAttacks[4])
  329.             printHint(out)
  330.         end
  331.     -- targetting enemies
  332.     elseif (cursor_state == 0x38) then
  333.         local targetted_monster = memory.read_u8(0x7B7E)
  334.         -- only bother if we're actually targetting a monster (ie not an ally)
  335.         if (targetted_monster > 0) then
  336.             targetted_monster = (math.log(targetted_monster) / math.log(2))
  337.             if (recentCommandType == 0x00) then -- fight
  338.                 local weaponPropLoc = 0x3CBC --main, then off
  339.                 weaponPropLoc = weaponPropLoc + (2*which_character)
  340.                 local my_weapons = { memory.read_u8(weaponPropLoc), memory.read_u8(weaponPropLoc + 1) }
  341.                 -- the offhand will be shortcircuited if first passes
  342.                 my_weapons[1] = (bit.band(my_weapons[1],0x10) > 0 and my_weapons[1] < 32)
  343.                 if (my_weapons[1] or (bit.band(my_weapons[2],0x10) > 0 and my_weapons[2] < 32)) then
  344.                     local out = doStealStuff(targetted_monster)
  345.                     local weaponLoc = 0x3CA8
  346.                     weaponLoc = weaponLoc + (2*which_character)
  347.                     local providingWeapon = "ThiefKnife"
  348.                     if (my_weapons[1]) then
  349.                         providingWeapon = getItemName(memory.read_u8(weaponLoc))
  350.                     else -- use off-hand since it wasn't from mainhand
  351.                         providingWeapon = getItemName(memory.read_u8(weaponLoc + 1))
  352.                     end
  353.                     printHint("* Shown due to "..providingWeapon..":\n"..out)
  354.                 end
  355.             elseif (recentCommandType == 0x05 or recentCommandType == 0x06) then -- we're stealing and targetting enemies
  356.                 printHint(doStealStuff(targetted_monster))
  357.             elseif (recentCommandType == 0x0D) then --sketch
  358.                 local idxTargetMonster = memory.read_u16_le(0x2001 + (2*targetted_monster))
  359.                 local cantSketchByte = memory.readbyte(offMonsterData + (lenMonsterData * idxTargetMonster) + 0x13,"CARTROM")
  360.                 if (bit.band(cantSketchByte,0x20) > 0) then
  361.                     printHint("Can't sketch!")
  362.                 else
  363.                     local sketchLoc = 0xF4300 + (2*idxTargetMonster)
  364.                     local sketchAttacks = { memory.readbyte(sketchLoc,"CARTROM"), memory.readbyte(sketchLoc+1,"CARTROM") }
  365.                     for i=1,2 do sketchAttacks[i] = getSpellName(sketchAttacks[i]) end
  366.                     local out = "Sketch: (75%) "..sketchAttacks[2] .. "\n        (25%) " .. sketchAttacks[1] ..""
  367.                     if (sketchAttacks[2] == "Special" or sketchAttacks[1] == "Special") then
  368.                         specialAttack = processEnemySpecial(idxTargetMonster)
  369.                         out = specialAttack.."\n"..out
  370.                     end
  371.                     printHint(out)
  372.                 end
  373.             elseif (recentCommandType == 0x0E) then -- chaos control
  374.                 local idxTargetMonster = memory.read_u16_le(0x2001 + (2*targetted_monster))
  375.                 local cantControlByte = memory.readbyte(offMonsterData + (lenMonsterData * idxTargetMonster) + 0x13,"CARTROM")
  376.                 if (bit.band(cantControlByte,0x80) > 0) then
  377.                     printHint("Can't control!")
  378.                 else
  379.                     local controlLoc = 0xF3D00 + (4*idxTargetMonster)
  380.                     local controlAttacks = { memory.readbyte(controlLoc,"CARTROM"), memory.readbyte(controlLoc+1,"CARTROM"), memory.readbyte(controlLoc+2,"CARTROM"), memory.readbyte(controlLoc+3,"CARTROM") }
  381.                     local hasSpecial = false
  382.                     local namesControlAttacks = {}
  383.                     for i=1,4 do
  384.                         if (controlAttacks[i] ~= 0xFF) then
  385.                             namesControlAttacks[#namesControlAttacks + 1] = getSpellName(controlAttacks[i])
  386.                             if (namesControlAttacks[#namesControlAttacks] == "Special") then hasSpecial = true end
  387.                             if (#namesControlAttacks == 3) then namesControlAttacks[3] = "\n         "..namesControlAttacks[3] end
  388.                         end
  389.                     end
  390.                     local out = "Control: "..table.concat(namesControlAttacks,", ")
  391.                     if (hasSpecial) then
  392.                         specialAttack = processEnemySpecial(idxTargetMonster)
  393.                         out = specialAttack.."\n"..out
  394.                     end
  395.                     printHint(out)
  396.                 end
  397.             end
  398.         end
  399.     end
  400. end
  401.  
  402. while true do
  403.     emu.frameadvance();
  404.     -- prevent it from doing dumb things while rom isn't even loaded
  405.     if (romname ~= "Null") then
  406.         buttonHandler()
  407.         main()
  408.     end
  409. end
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top