SHARE
TWEET

FF6 BizHawk LUA Info Overlay

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