-- ---------------------------- -- -- Final Fantasy V LUA script -- -- By: samurai goroh -- -- Mail: samuraigoroh@gmail.com -- -- ---------------------------- -- --require "FFV_Tables" -- Imports file with all the tables --require "FFV_Icons" -- Imports file with all icon drawings dofile("D:/Erick/Juegos/SNES/FFV/LUA/bizhawk/FFV_Tables.lua") dofile("D:/Erick/Juegos/SNES/FFV/LUA/bizhawk/FFV_Icons.lua") -- ------- -- -- GLOBALS -- -- ------- -- Rheld = false -- R button is held (ally info) Lheld = false -- L button is held (enemy info) characterPage = 0 -- Starting 'Page' battle info for characters enemyPage = 0 -- Starting 'Page' battle info for enemies windowColor = 0 -- Color of the window, which can be edited in config. -- --------- -- -- CONSTANTS -- -- --------- -- gapY = 15 -- Pixels gap in coord Y, used in gui for rows CharacterMax = 4 -- Max number of characters in a battle EnemiesMax = 8 -- Max number of enemies in a battle battle_lut = {} -- Table that keeps values of the LUT @ C0/FEC0 characterPageMax = 9 -- Total 'pages' [0 based] battle info for characters Set to 0 to remove enemyPageMax = 7 -- Total 'pages' [0 based] battle info for enemies Set to 0 to remove --https://msdn.microsoft.com/en-us/library/system.drawing.color.aspx <-- color name/value color = { black = 0xFF000000, -- AARRGGBB red = 0xFFFF0000, -- Alpha pink = 0xFFFFC0CB, -- Red orange = 0xFFFFA500, -- Green yellow = 0xFFFFFF00, -- Blue green = 0xFF008000, light_green = 0xFF90EE90, dark_green = 0xFF006400, aqua = 0xFF00FFFF, blue = 0xFF0000FF, navy = 0xFF000084, lime = 0xFF00FF00, purple = 0xFF800080, fuchsia = 0xFFFF00FF, brown = 0xFFA52A2A, gray = 0xFF808080, white = 0xFFFFFFFF } -------------------------------------------------------------------------------- local function transparency(color, alpha) -- Change transparency of a color -------------------------------------------------------------------------------- --print (color, alpha) local result = (color - 0xFF000000 + (alpha%0x100 * 0x01000000)) % 0x100000000 return result end -------------------------------------------------------------------------------- local function within ( low, value, high ) -- Determines whether value is between the limits (low <= value <= high) -------------------------------------------------------------------------------- return ( value >= low ) and ( value <= high ) end -------------------------------------------------------------------------------- local function txt ( x, y, str, ... ) -- ... = bgcolor, color, anchor -------------------------------------------------------------------------------- gui.text( x, y, str, ... ) end -------------------------------------------------------------------------------- local function TEXT ( x, y, str, Color, fontsize, fontfamily, fontstyle ) -- -------------------------------------------------------------------------------- if Color == nil then Color = color.red end if fontsize == nil then fontsize = 10 end if fontfamily == nil then fontfamily = "Arial" end if fontstyle == nil then fontstyle = "regular" end -- fontstyle = regular, bold, italic, strikethrough, underline gui.drawText( x, y, str, Color, fontsize, fontfamily, fontstyle ) end -------------------------------------------------------------------------------- local function BitOn(number, size) -- Function that returns table with 1's and 0's -------------------------------------------------------------------------------- local bitTable = {} local pos = 0 for i=1, size do bitTable[i] = 0 end while number > 0 do pos = pos+1 bitTable[pos] = number % 2 number = math.floor(number / 2) end return bitTable end -------------------------------------------------------------------------------- function splitTop(num, split) -- Function that returns high part of "Byte" -------------------------------------------------------------------------------- return (num % split) end -------------------------------------------------------------------------------- function splitBot(num, split) -- Function that returns low part of "Byte" -------------------------------------------------------------------------------- return math.floor(num / split) end -------------------------------------------------------------------------------- local function positionPage(current, total) -- Function that shows battle page position -------------------------------------------------------------------------------- local str = "" for i=0, total do -- 0 based if i ~= current then str = str .. "-" else str = str .. "+" end end return str end -------------------------------------------------------------------------------- local function readBitwiseTable(myValue, myTable) -- Function that reads bitwise tables -------------------------------------------------------------------------------- local str = "" local size = #myTable -- Number of elements of the table local TableOn = {} TableOn = BitOn(myValue, size) for i=1, size do if TableOn[i] == 1 then str = str .. myTable[i] .. " " end end if str ~= "" then return str else return "__" end end -------------------------------------------------------------------------------- local function drawElement(x, y, myValue) -- Function that draws Elemental Affinity icons -------------------------------------------------------------------------------- local TableOn = {} local gapX = 0 TableOn = BitOn(myValue, 8) if TableOn[1] == 1 then -- Fire draw_fire(x+gapX, y) gapX = gapX + 8 end if TableOn[2] == 1 then -- Ice draw_ice(x+gapX, y) gapX = gapX + 8 end if TableOn[3] == 1 then -- Lightning draw_lightning(x+gapX, y) gapX = gapX + 8 end if TableOn[4] == 1 then -- Poison draw_poisonE(x+gapX, y) gapX = gapX + 8 end if TableOn[5] == 1 then -- Holy draw_holy(x+gapX, y) gapX = gapX + 8 end if TableOn[6] == 1 then -- Earth draw_earth(x+gapX, y) gapX = gapX + 8 end if TableOn[7] == 1 then -- Wind draw_wind(x+gapX, y) gapX = gapX + 8 end if TableOn[8] == 1 then -- Water draw_water(x+gapX, y) end end -------------------------------------------------------------------------------- local function drawCurable(x, y, myValue) -- Function that draws Curable Status icons -------------------------------------------------------------------------------- local TableOn = {} local gapX = 0 TableOn = BitOn(myValue, 8) if TableOn[1] == 1 then draw_darkness(x+gapX, y) gapX = gapX + 8 end if TableOn[2] == 1 then draw_zombie(x+gapX, y) gapX = gapX + 8 end if TableOn[3] == 1 then draw_poisonC(x+gapX, y) gapX = gapX + 8 end if TableOn[4] == 1 then draw_float(x+gapX, y) gapX = gapX + 8 end if TableOn[5] == 1 then draw_mini(x+gapX, y) gapX = gapX + 8 end if TableOn[6] == 1 then draw_toad(x+gapX, y) gapX = gapX + 8 end if TableOn[7] == 1 then draw_petrify(x+gapX, y) gapX = gapX + 8 end if TableOn[8] == 1 then draw_dead(x+gapX, y) end end -------------------------------------------------------------------------------- local function drawTemporary(x, y, myValue) -- Function that draws Temporary Status icons -------------------------------------------------------------------------------- local TableOn = {} local gapX = 0 TableOn = BitOn(myValue, 8) if TableOn[1] == 1 then draw_imageL(x+gapX, y) gapX = gapX + 8 end if TableOn[2] == 1 then draw_imageR(x+gapX, y) gapX = gapX + 8 end if TableOn[3] == 1 then draw_mute(x+gapX, y) gapX = gapX + 8 end if TableOn[4] == 1 then draw_berserk(x+gapX, y) gapX = gapX + 8 end if TableOn[5] == 1 then draw_charm(x+gapX, y) gapX = gapX + 8 end if TableOn[6] == 1 then draw_paralyze(x+gapX, y) gapX = gapX + 8 end if TableOn[7] == 1 then draw_sleep(x+gapX, y) gapX = gapX + 8 end if TableOn[8] == 1 then draw_aging(x+gapX, y) end end -------------------------------------------------------------------------------- local function drawDispellable(x, y, myValue) -- Function that draws Dispellable Status icons -------------------------------------------------------------------------------- local TableOn = {} local gapX = 0 TableOn = BitOn(myValue, 8) if TableOn[1] == 1 then draw_regen(x+gapX, y) gapX = gapX + 8 end if TableOn[2] == 1 then draw_invulnerable(x+gapX, y) gapX = gapX + 8 end if TableOn[3] == 1 then draw_slow(x+gapX, y) gapX = gapX + 8 end if TableOn[4] == 1 then draw_haste(x+gapX, y) gapX = gapX + 8 end if TableOn[5] == 1 then draw_stop(x+gapX, y) gapX = gapX + 8 end if TableOn[6] == 1 then draw_shell(x+gapX, y) gapX = gapX + 8 end if TableOn[7] == 1 then draw_armor(x+gapX, y) gapX = gapX + 8 end if TableOn[8] == 1 then draw_wall(x+gapX, y) end end -------------------------------------------------------------------------------- local function drawPermanent(x, y, myValue) -- Function that draws Permanent Status icons -------------------------------------------------------------------------------- local TableOn = {} local gapX = 0 TableOn = BitOn(myValue, 8) if TableOn[1] == 1 then draw_hidden(x+gapX, y) gapX = gapX + 8 end if TableOn[2] == 1 then draw_peril(x+gapX, y) gapX = gapX + 8 end if TableOn[3] == 1 then draw_singing(x+gapX, y) gapX = gapX + 8 end if TableOn[4] == 1 then draw_leak(x+gapX, y) gapX = gapX + 8 end if TableOn[5] == 1 then draw_countdown(x+gapX, y) gapX = gapX + 8 end if TableOn[6] == 1 then draw_controlled(x+gapX, y) gapX = gapX + 8 end if TableOn[7] == 1 then draw_false(x+gapX, y) gapX = gapX + 8 end if TableOn[8] == 1 then draw_erased(x+gapX, y) end end -------------------------------------------------------------------------------- local function drawTransport(x, y) -- Function that draws Transportation icons -------------------------------------------------------------------------------- local gapY = 8 draw_chocobo( x, y+(0*gapY) ) draw_black_chocobo( x, y+(1*gapY) ) draw_hiryu( x, y+(2*gapY) ) draw_submarine( x, y+(3*gapY) ) draw_steamship( x, y+(4*gapY) ) draw_airship( x, y+(5*gapY) ) draw_boot( x, y+(6*gapY) ) end -------------------------------------------------------------------------------- local function getWindowColor() -- Function that gets the color picked for the Window -------------------------------------------------------------------------------- local colour = memory.read_u16_le(0x0971) local red = colour % 0x20 -- Increment of 0x0001 local green = math.floor(colour / 0x20) % 0x20 -- Increment of 0x0020 local blue = math.floor(colour / 0x400) % 0x20 -- Increment of 0x0400 local result = 0xFF000000 + 8*(red*0x10000 + green*0x100 + blue) -- Change from 555 to ARGB return (result) end -------------------------------------------------------------------------------- local function AttackFormulaParameters(formula, x, y) -- Every Attack Formula uses 3 bytes, but in different ways -------------------------------------------------------------------------------- local p1 = formula.Parameter1 -- Parameter 1 local p2 = formula.Parameter2 -- Parameter 2 local p3 = formula.Parameter3 -- Parameter 3 local aType = formula.formula -- Attack Formula local results = {'','',''} -- Results of parameter operations local s = {} -- Flags if formula.Special then s = BitOn( formula.Special,8 ) else s = BitOn( 0,8 ) end -- Just to be sure, try to print parameters if they are not unused for debugging purposes if p1 ~= 0 then results[1]= p1 end if p2 ~= 0 then results[2]= p2 end if p3 ~= 0 then results[3]= p3 end if aType == 0x00 then -- "Nothing" if p1 > 0 then results[1] = string.format( "Duration = %u", p1*2 ) end if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end elseif aType == 0x01 then -- Monster Fight --results[1] = p1 --results[2] = p2 --results[3] = p3 elseif aType == 0x02 then -- Monster Specialty --results[1] = p1 --results[2] = p2 --results[3] = p3 elseif aType == 0x03 then -- Magic Sword 1 [Fire, Ice, Bolt, Venom, Break] --results[1] = Spell # results[2] = "Element:" drawElement( x+34, y+6, p2) --results[3] = [Status 0] or Always??? elseif aType == 0x04 then -- Magic Sword 2 [Mute, Sleep, Fire2, Ice 2, Bolt2] --results[1] = Spell # results[2] = "Element:" drawElement( x+34, y+6, p2) --results[3] = [Status 0] elseif aType == 0x05 then -- Magic Sword 3 [Drain, Bio, Fire3, Ice 3, Bolt3, Holy, Flare, Psych] --results[1] = Spell # results[2] = "Element:" drawElement( x+34, y+6, p2) --results[3] = [Status 0] elseif aType == 0x06 then -- Magic Attack --results[1] = 0 results[2] = string.format( "Attack = %u", p2 ) results[3] = "Element:" drawElement( x+34, y+14, p3) elseif aType == 0x07 then -- HP based damage (gravity) if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "x/16th = %u", p2 ) results[3] = "Status add:" drawTemporary( x+34, y-2, p3 ) elseif aType == 0x08 then -- Pierce magic defense --results[1] 0 results[2] = string.format( "Attack = %u", p2) --results[3] 0 elseif aType == 0x09 then -- Random damage --results[1] 0 --results[2] Damage multiplier results[2] = string.format( "Damage mult = %u", p2 ) --results[3] {00, 00, 40, 00} elseif aType == 0x0A then -- Physical magic if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Attack : %u", p2 ) --results[3] 0 elseif aType == 0x0B then -- Level based damage + status curable results[1] = "Element:" drawElement( x+34, y-2, p1 ) results[2] = string.format( "% : %u", p2 ) results[3] = "Status Add:" drawCurable( x+34, y+14, p3 ) elseif aType == 0x0C then -- Pierce defense + HP leak results[1] = "Element:" drawElement( x+34, y-2, p1 ) results[2] = string.format( "Attack : %u", p2 ) if p3 > 0 then results[1] = string.format( "Duration/2: %u", p3 ) end elseif aType == 0x0D then -- HP drain if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Attack = %u", p2 ) --results[3] 0 elseif aType == 0x0E then -- MP drain if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Attack : %u", p2 ) --results[3] 0 elseif aType == 0x0F then -- Reduce HP to Critical if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] 0 elseif aType == 0x10 then -- Restore HP --results[1] 0 results[2] = string.format( "Attack : %u", p2 ) --results[3] 0 elseif aType == 0x11 then -- Restore full HP --results[1] 0 results[2] = string.format( "Attack = %u", p2 ) --results[3] 0 elseif aType == 0x12 then -- Status [Curable] if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Duration = %u", p2 ) results[3] = "Status Add:" drawCurable( x+34, y+14, p3 ) elseif aType == 0x13 then -- Status [Temporary] if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Duration = %u", 2*p2 ) results[3] = "Status Add:" drawTemporary( x+34, y+14, 255-p3 ) elseif aType == 0x14 then -- Status [Dispellable] if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Duration : %u", p2 ) results[3] = "Status Add:" drawDispellable( x+45, y+14, p3 ) elseif aType == 0x15 then -- Toggle Status [Curable] if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] = "Status Add/Removed:" drawCurable( x+34, y+14, p3 ) elseif aType == 0x16 then -- Speed Status if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = "Removes:" drawDispellable( x+34, y+6, 255-p2 ) results[3] = "Adds :" drawDispellable( x+34, y+14, p3 ) elseif aType == 0x17 then -- Instant death if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 results[3] = "Status Add:" drawCurable( x+34, y+14, p3 ) elseif aType == 0x18 then -- Instant destroy if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] {00, 00, 00, 80} --results[3] 0 elseif aType == 0x19 then -- Status Removal results[1] = " Curable:" drawCurable( x+50, y-2 , 255-p1 ) results[2] = "Dispellable:" drawDispellable( x+50, y+6 , 255-p2 ) results[3] = " Temporary:" drawTemporary( x+50, y+14, 255-p3 ) elseif aType == 0x1A then -- Resurrection results[1] = string.format( "Hit: %u%%", p1 ) --results[2] = "" results[3] = string.format( "%u/16 HP restored", p3 ) elseif aType == 0x1B then -- Whispering Wind --results[1] 0 results[2] = string.format( "Attack = %u", p2 ) --results[3] 0 elseif aType == 0x1C then -- Element attribute change results[1] = "Absorb:" drawElement( x+34, y-2, p1 ) results[1] = "Immune:" drawElement( x+34, y+6, p2 ) results[1] = "Half :" drawElement( x+34, y+14, p3 ) elseif aType == 0x1D then -- View stats results[1] = string.format( "%s", readBitwiseTable(p1, TableCommand) ) --results[2] 0 --results[3] 0 elseif aType == 0x1E then -- Drag --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x1F then -- Void --results[1] 0x40 --results[2] 0 --results[3] 0 elseif aType == 0x20 then -- End battle --results[1] 0x40 --results[2] 0 --results[3] 0 elseif aType == 0x21 then -- Reset --results[1] 0x40 --results[2] 0 --results[3] 0 elseif aType == 0x22 then -- Quick --results[1] 0x40 --results[2] 0 --results[3] 0 elseif aType == 0x23 then -- Earth Wall --results[1] 0x3F --results[2] 0x16 --results[3] 0 elseif aType == 0x24 then -- Constant HP restore results[1] = string.format( "Restore %u HP", p1*p2 ) results[2] = "" --results[3] 0 elseif aType == 0x25 then -- Constant MP restored results[1] = string.format( "Restore %u MP", p1*p2 ) results[2] = "" --results[3] 0 elseif aType == 0x26 then -- Full HP/MP results[1] = "Full HP/MP" elseif aType == 0x27 then -- Status C,T,D added results[1] = "Added:" drawCurable( x+34, y-2 , p1 ) results[2] = "Added:" drawTemporary( x+34, y+6 , p2 ) results[3] = "Added:" drawDispellable( x+34, y+14, p3 ) elseif aType == 0x28 then -- Fixed Damage if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Damage = %u", p2 + p3*0x200 ) elseif aType == 0x29 then -- Status [Permanent] inflicted if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Countdown timer / duration ? results[3] = "Added:" drawPermanent( x+34, y+14, p3 ) elseif aType == 0x2A then -- HP based damage + HP leak --results[1] [Element] --results[2] HP damage (numerator of /16 fraction) --results[3] HP leak duration elseif aType == 0x2B then -- User HP based damage --results[1] 0 --results[2] HP damage (numerator of /16 fraction) --results[3] [Status Curable] added elseif aType == 0x2C then -- Random effect --results[1] [Status Curable] added --results[2] Duration/2 --results[3] [Status Temporary] added elseif aType == 0x2D then -- Ground attacks --results[1] 0 --results[2] Attack power --results[3] [Element] elseif aType == 0x2E then -- Reaper's Sword if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Attack power --results[3] [Status Curable] added elseif aType == 0x2F then -- N/U? --results[1] --results[2] --results[3] elseif aType == 0x30 then -- Unarmed results[1] = string.format( "Critical hit: %u%%", p1 ) --results[2] 0 --results[3] 0 elseif aType == 0x31 then -- Swords results[1] = "Element:" drawElement( x+34, y-2, p1 ) if p2 > 0 then results[2] = string.format( "Activate: %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability : %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability : %s", TableMagicID[p3+1] ) end end elseif aType == 0x32 then -- Knives results[1] = "Element:" drawElement( x+34, y-2, p1) if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end end elseif aType == 0x33 then -- Spears results[1] = "Element:" drawElement( x+34, y-2, p1) if p2 > 0 then results[2] = string.format( "Activate: %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability : %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability : %s", TableMagicID[p3+1] ) end end elseif aType == 0x34 then -- Axes, Staves if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end end elseif aType == 0x35 then -- Status infliction bow if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if math.floor(p2/128) == 1 then -- if inflict status results[2] = string.format( "Activate = %u%%", p2%128 ) results[3] = "Status:" drawCurable( x+34, y+14 , p3 ) end elseif aType == 0x36 then -- Bows if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Critical = %u%%", p2 ) results[3] = "Element:" drawElement( x+34, y+14, p3 ) elseif aType == 0x37 then -- Katanas results[1] = string.format( "Critical = %u%%", p1 ) if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end end elseif aType == 0x38 then -- Whips if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end end elseif aType == 0x39 then -- Bells --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x3A then -- Long Reach Axes if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end end elseif aType == 0x3B then -- Rods if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[3] = "Element:" drawElement( x+34, y+14, p3) elseif aType == 0x3C then -- Rune weapon if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Attack +%u", p2 ) results[3] = string.format( "MP Cost = %u MP", p3 ) elseif aType == 0x3D then -- Death Claw if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Duration/2 --results[3] [Status Temporary] added elseif aType == 0x3E then -- Failure (EL+TS) if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Chance of HP to critical (numerator of /16 fraction) --results[3] 0 elseif aType == 0x3F then -- Zombie Breath --results[1] 0 --results[2] Damage multiplier --results[3] 0 elseif aType == 0x40 then -- Change row if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Position Flags --results[3] 0 elseif aType == 0x41 then -- N/U? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x42 then -- HP and Status Restored if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end results[2] = string.format( "Power = %u", p2 ) results[3] = "Removes: " drawCurable( x+34, y+14, 255-p3) elseif aType == 0x43 then -- !Steal --results[1] Success % --results[2] 0 --results[3] 0 elseif aType == 0x44 then -- Escape (enemy) --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x45 then -- !Throw --results[1] 0x50 --results[2] 0 --results[3] 0 elseif aType == 0x46 then -- !GilToss --results[1] Gil cost factor --results[2] Damage multiplier --results[3] 0 elseif aType == 0x47 then -- !Tame --results[1] Success % --results[2] Duration/2 --results[3] [Status 2] added elseif aType == 0x48 then -- !Catch --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x49 then -- Flirt if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if p2 > 0 then results[2] = string.format( "Activate = %u%%", p2 ) results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end elseif aType == 0x4A then -- !Dance --results[1] 0x13 --results[2] 0 --results[3] 0 elseif aType == 0x4B then -- Lv5 Doom --results[1] Level factor --results[2] 0 --results[3] [Status Curable] added elseif aType == 0x4C then -- Lv2 Old --results[1] Level factor --results[2] 0 --results[3] [Status Temporary] added elseif aType == 0x4D then -- Lv4 Qrter --results[1] Level factor --results[2] HP damage (numerator of /16 fraction) --results[3] 0 elseif aType == 0x4E then -- Lv3 Flare --results[1] Level factor --results[2] Attack power --results[3] 0 elseif aType == 0x4F then -- Spirit --results[1] % chance for Zombie status --results[2] 0 --results[3] HP restored (numerator of /16 fraction) elseif aType == 0x50 then -- Goblin Punch if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0x03 --results[3] 0 elseif aType == 0x51 then -- Status Up/Down local p2Bits = BitOn(p2,8) if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end if p2Bits[8] == 1 or p2Bits[7] == 1 then results[2] = "Level Half" end if p2Bits[6] == 1 then results[2] = "Defense Half" end if p2Bits[5] == 1 then results[2] = "Level Up" end if p2Bits[3] == 1 then results[2] = "Attack Power Up" end if p3 > 0 then results[3] = string.format( "Amount = %u", p3 ) end elseif aType == 0x52 then -- Mucus if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] [Status Dispellable] removed (inverted) --results[3] [Status Dispellable] added elseif aType == 0x53 then -- MP damage (Rasp) if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] MP damage (numerator of /16 fraction) --results[3] 0 elseif aType == 0x54 then -- User HP based damage (negative) if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] 0 elseif aType == 0x55 then -- Fusion --results[1] 0 --results[2] 0 --results[3] 0x50 elseif aType == 0x56 then -- N/U? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x57 then -- Random effect --results[1] [Status Curable] added --results[2] Duration/2 --results[3] [Status Temporary] added elseif aType == 0x58 then -- Mind Blast if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] Attack power --results[3] Duration/2 elseif aType == 0x59 then -- Max HP Up (Giant Drink) --results[1] 0 --results[2] 0 results[3] = "Doubles max HP" elseif aType == 0x5A then -- White Wind --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x5B then -- N/U? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x5C then -- Hug if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] [Status Curable] added elseif aType == 0x5D then -- Dance of the Dead, Zombie Powder if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] 0 elseif aType == 0x5E then -- Increase stat while Singing --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x5F then -- Creature Type only Damage --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x60 then -- Unhide Monster --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x61 then -- "Stalker Attack" --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x62 then -- "Unhide Next Page" --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x63 then -- Grand Cross --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x64 then -- Chicken Knife -- Not actually part of Parameters, but useful info for the item local escape = memory.readbyte(0x7C75) --results[1] = string.format( "Escape = %u times", escape ) results[1] = string.format( "Attack = %u" , math.floor(escape/2) ) results[2] = string.format( "Activate = %u%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = "Ability = " .. TableAbilityID[p3+1] else results[3] = "Ability = " .. TableMagicID[p3+1] end elseif aType == 0x65 then -- Interceptor Rocket --results[1] 0x50 --results[2] 0x50 --results[3] 0x50 elseif aType == 0x66 then -- Targeting --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x67 then -- Pull --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x68 then -- Terminate --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x69 then -- !Control --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x6A then -- ? (Sandworm's Death) --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x6B then -- Status Immunity, Magic Element UP, Creature Type --results[1] [Monster type] applied --results[2] [Status Curable] immunity --results[3] [Element] strengthened elseif aType == 0x6C then -- Monster type bonus --results[1] 0 results[2] = string.format( "Attack = %u", p2) results[3] = string.format( "Strong Vs: %s", readBitwiseTable(p3, TableCreature) ) elseif aType == 0x6D then -- Vampire if p1 == 0x80 then results[1] = "Hit = 100%" else results[1] = string.format( "Hit = %u%%", p1 ) end --results[2] 0 --results[3] 0 elseif aType == 0x6E then -- Brave Blade local escape = memory.readbyte(0x7C75) local attack = formula.AttPower - escape if attack > 0 then results[1] = string.format ( "Attack = %u", attack ) else results[1] = "Attack = 0" end results[2] = string.format ( "Escape = %u times", escape ) elseif aType == 0x6F then -- Fight (strong) --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x70 then -- Wormhole --results[1] 0x50 --results[2] 0 --results[3] 0x50 elseif aType == 0x71 then -- Level Down --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x72 then -- Anti-monster Bow results[1] = string.format( "Strong Vs: %s", readBitwiseTable(p1, TableCreature) ) if p2 > 0 then results[2] = string.format( "Activate: %u%%", p2 ) results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) end elseif aType == 0x73 then -- Anti-monster 'spear' results[1] = string.format("Strong Vs: %s", readBitwiseTable(p1, TableCreature) ) --results[2] 0 --results[3] 0 elseif aType == 0x74 then -- Unhide monster --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x75 then -- Terminate --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x76 then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x77 then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x78 then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x79 then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7A then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7B then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7C then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7D then -- ? --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7E then -- Ineffective --results[1] 0 --results[2] 0 --results[3] 0 elseif aType == 0x7F then -- No Action [+ Harps] if p1 > 0 then results[1] = string.format( "Power = %s", p1 ) end if p2> 0 then results[2] = string.format( "Activate = %s%%", p2 ) if s[2] == 1 then -- If "ability attack" special bit is set, use ability table results[3] = string.format( "Ability = %s", TableAbilityID[p3+1] ) else results[3] = string.format( "Ability = %s", TableMagicID[p3+1] ) if s[1] ==1 then -- Wonder Rod results[3] = "Ability = Wonder Rod" end end end -- if actually a harp, look for actual info if within(0x74, p3, 0x77) then results[1] = "Harp" end end --]] -- Print the results gui.text( x, y, results[1], color.black, color.aqua ) gui.text( x, y+8, results[2], color.black, color.aqua ) gui.text( x, y+16, results[3], color.black, color.aqua ) end -------------------------------------------------------------------------------- local function ItemFormula(ID) -- Formula that ITEMS use -------------------------------------------------------------------------------- local item = {} local address = 0 if ID <= 0x7F then -- Weapon address = 0xD10000 + (ID*12) item = { index = ID, itemType = "weapon", Target = memory.readbyte(address + 0x0), -- 0 Targeting (when used as item) AttackType = memory.readbyte(address + 0x1), -- 1 Attack type Throwable = splitBot(memory.readbyte(address+0x2), 0x40), -- 2a Throwable EquipType = splitTop(memory.readbyte(address+0x2), 0x40), -- 2b Equipment category StatsUpCheck = splitBot(memory.readbyte(address+0x3), 0x80), -- 3a Stats up check bit ElementBoost = splitTop(memory.readbyte(address+0x3), 0x80), -- 3b Elemental Boost StatsUp = math.floor((memory.readbyte(address+0x3)%0x80)/8), -- 3c Bonus Stats StatsValue = memory.readbyte(address + 0x3)%8, -- 3d Stats up value Description = memory.readbyte(address + 0x4)%64, -- 4a Description Double = math.floor(memory.readbyte(address+0x4)/64), -- 4b Double Grip info Special = memory.readbyte(address + 0x5), -- 5 Special properties UsedAsItem = math.floor(memory.readbyte(address+0x6)/0x80), -- 6a Break on use Action = memory.readbyte(address + 0x6)%0x80, -- 6b Used as item AttPower = memory.readbyte(address + 0x7), -- 7 Attack Power formula = memory.readbyte(address + 0x8), -- 8 Attack formula Parameter1 = memory.readbyte(address + 0x9), -- 9 Parameter 1 \ Parameter2 = memory.readbyte(address + 0xA), -- A Parameter 2 > Parameter3 = memory.readbyte(address + 0xB) -- B Parameter 3 / } elseif within ( 0x80, ID, 0xDF ) then -- Armor address = 0xD10000 + (ID*12) item = { index = ID, itemType = "armor", Slot = memory.readbyte(address + 0x0), -- 0 Equipment slots Weight = memory.readbyte(address + 0x1), -- 1 Equipment weight Throwable = splitBot(memory.readbyte(address+0x2), 0x40), -- 2a Throwable EquipType = splitTop(memory.readbyte(address+0x2), 0x40), -- 2b Equipment category StatsUpCheck = splitBot(memory.readbyte(address+0x3), 0x80), -- 3a Stats up check bit ElementBoost = splitTop(memory.readbyte(address+0x3), 0x80), -- 3b Elemental Boost StatsUp = math.floor((memory.readbyte(address+0x3)%0x80)/8), -- 3c Bonus Stats StatsValue = memory.readbyte(address + 0x3)%8, -- 3d Stats up value Description = memory.readbyte(address + 0x4)%64, -- 4a Description Double = math.floor(memory.readbyte(address+0x4)/64), -- 4b Double Grip info Special = memory.readbyte(address + 0x5), -- 5 Special properties Evade = memory.readbyte(address + 0x6), -- 6 Evade % Defense = memory.readbyte(address + 0x7), -- 7 Defense MagicEvade = memory.readbyte(address + 0x8), -- 8 Magic evade % MagicDefense = memory.readbyte(address + 0x9), -- 9 Magic defense ElementDefense = memory.readbyte(address + 0xA), -- A Element defense StatusProperty = memory.readbyte(address + 0xB), -- B Status properties Parameter1 = 0, -- Dummy Parameter2 = 0, -- Dummy Parameter3 = 0, -- Dummy formula = 0, -- Dummy } else --if ID >= 0xE0 then -- Consumables address = 0xD10A80 + (ID-0xE0)*8 item = { index = ID, itemType = "consumable", Target = memory.readbyte(address + 0x0), -- 0 Targeting AttackType = memory.readbyte(address + 0x1), -- 1 Attack Type? (N/U) Restrictions = memory.readbyte(address + 0x2), -- 2 Restrictions Properties = math.floor(memory.readbyte(address+0x3)/128), -- 3a Properties Description = memory.readbyte(address + 0x3)%128, -- 3b Description Unavoidable = math.floor(memory.readbyte(address+0x4)/128), -- 4a Unavoidable formula = memory.readbyte(address + 0x4)%128, -- 4b Attack formula Parameter1 = memory.readbyte(address + 0x5), -- 5 Parameter 1 \ Parameter2 = memory.readbyte(address + 0x6), -- 6 Parameter 2 > Parameter3 = memory.readbyte(address + 0x7) -- 7 Parameter 3 / } end return item end -------------------------------------------------------------------------------- local function EnemyInfo(Enemy) -- Table with the parameters of monsters -------------------------------------------------------------------------------- local ram = 0 local enemy = Enemy - 1 local enemyTable = {} enemyTable = { Level = memory.read_u8(0x2202 + enemy*(0x80)) , CurrentHp = memory.read_u16_le(0x2206 + enemy*(0x80)) , TotalHp = memory.read_u16_le(0x2208 + enemy*(0x80)) , CurrentMp = memory.read_u16_le(0x220A + enemy*(0x80)) , TotalMp = memory.read_u16_le(0x220C + enemy*(0x80)) , StatusC = memory.read_u8(0x221A + enemy*(0x80)) , StatusT = memory.read_u8(0x221B + enemy*(0x80)) , StatusD = memory.read_u8(0x221C + enemy*(0x80)) , StatusP = memory.read_u8(0x221D + enemy*(0x80)) , Evade = memory.read_u8(0x222C + enemy*(0x80)) , Defense = memory.read_u8(0x222D + enemy*(0x80)) , MagicEvade = memory.read_u8(0x222E + enemy*(0x80)) , MagicDefense = memory.read_u8(0x222F + enemy*(0x80)) , ElementAbsorb = memory.read_u8(0x2230 + enemy*(0x80)) , ElementWeakness = memory.read_u8(0x2234 + enemy*(0x80)) , ElementImmune = memory.read_u8(0x2232 + enemy*(0x80)) , ImmunityC = memory.read_u8(0x2235 + enemy*(0x80)) , ImmunityT = memory.read_u8(0x2236 + enemy*(0x80)) , ImmunityD = memory.read_u8(0x2237 + enemy*(0x80)) , Attack = memory.read_u8(0x2244 + enemy*(0x80)) , AttackMult = memory.read_u8(0x2262 + enemy*(0x80)) , CantEvade = memory.read_u8(0x2264 + enemy*(0x80)) , CreatureType = memory.read_u8(0x2265 + enemy*(0x80)) , CommandImmunity = memory.read_u8(0x2266 + enemy*(0x80)) , Experience = memory.read_u16_le(0x2267 + enemy*(0x80)) , Gil = memory.read_u16_le(0x2269 + enemy*(0x80)) , InitialStatusC = memory.read_u8(0x2270 + enemy*(0x80)) , InitialStatusT = memory.read_u8(0x2271 + enemy*(0x80)) , InitialStatusD = memory.read_u8(0x2272 + enemy*(0x80)) , InitialStatusP = memory.read_u8(0x2273 + enemy*(0x80)) , AttackGauge = memory.read_u8(0x3DAB + enemy*(0x0B)) , Name = memory.read_u16_le(0x4008 + enemy*(0x02)) , Position = memory.read_u8(0x4000 + enemy*(0x01)) , PositionY = bit.lshift(bit.band(memory.read_u8(0x4000 + enemy),0x0F),3) + 1 , -- low nibble PositionX = bit.rshift(bit.band(memory.read_u8(0x4000 + enemy),0xF0),1) + 5 , -- high nibble StealRare = 0, -- Can't read right now, need to switch to ROM StealCommon = 0, -- same DropRare = 0, -- same DropCommon = 0 -- same } ram = memory.read_u16_le(0x4008 + enemy*(2))*4 memory.usememorydomain("CARTROM") -- Read from ROM enemyTable.StealRare = memory.read_u8(0x105000+ ram + 0) --Overwritting Steals & Drops enemyTable.StealCommon = memory.read_u8(0x105000+ ram + 1) enemyTable.DropRare = memory.read_u8(0x105000+ ram + 2) enemyTable.DropCommon = memory.read_u8(0x105000+ ram + 3) memory.usememorydomain("WRAM") -- Change back to RAM return enemyTable end -------------------------------------------------------------------------------- local function CharacterInfoBattle(Character) -- Table with the parameters of allies in BATTLE -------------------------------------------------------------------------------- local character = Character - 1 local characterTable = {} local misc = memory.read_u8(0x2000 + character*(0x80)) characterTable = { Character = misc % 8, Gender = math.floor( misc / 0x08) % 2, Present = 1 - (math.floor( misc / 0x40) % 2), BackRow = math.floor( misc / 0x80) % 2, Job = memory.read_u8(0x2001 + character*(0x80)) , Level = memory.read_u8(0x2002 + character*(0x80)) , Experience = memory.read_u24_le(0x2003 + character*(0x80)) , CurrentHp = memory.read_u16_le(0x2006 + character*(0x80)) , TotalHp = memory.read_u16_le(0x2008 + character*(0x80)) , CurrentMp = memory.read_u16_le(0x200A + character*(0x80)) , TotalMp = memory.read_u16_le(0x200C + character*(0x80)) , EquipHead = memory.read_u8(0x200E + character*(0x80)) , EquipBody = memory.read_u8(0x200F + character*(0x80)) , EquipRelic = memory.read_u8(0x2010 + character*(0x80)) , EquipRHandSh = memory.read_u8(0x2011 + character*(0x80)) , EquipLHandSh = memory.read_u8(0x2012 + character*(0x80)) , EquipRHandWpn = memory.read_u8(0x2013 + character*(0x80)) , EquipLHandWpn = memory.read_u8(0x2014 + character*(0x80)) , MonsterCaught = memory.read_u8(0x2015 + character*(0x80)) , Command1 = memory.read_u8(0x2016 + character*(0x80)) , --(Up) Command2 = memory.read_u8(0x2017 + character*(0x80)) , --(Left) Command3 = memory.read_u8(0x2018 + character*(0x80)) , --(Right) Command4 = memory.read_u8(0x2019 + character*(0x80)) , --(Down) StatusC = memory.read_u8(0x201A + character*(0x80)) , StatusT = memory.read_u8(0x201B + character*(0x80)) , StatusD = memory.read_u8(0x201C + character*(0x80)) , StatusP = memory.read_u8(0x201D + character*(0x80)) , Actions = memory.read_u8(0x201E + character*(0x80)) , DamageMod = memory.read_u8(0x201F + character*(0x80)) , InateAbility = memory.read_u16_le(0x2020 + character*(0x80)) , MagicElementUp = memory.read_u8(0x2022 + character*(0x80)) , Weight = memory.read_u8(0x2023 + character*(0x80)) , BaseStrength = memory.read_u8(0x2024 + character*(0x80)) , BaseAgility = memory.read_u8(0x2025 + character*(0x80)) , BaseStamina = memory.read_u8(0x2026 + character*(0x80)) , BaseMgPower = memory.read_u8(0x2027 + character*(0x80)) , CurrStrength = memory.read_u8(0x2028 + character*(0x80)) , CurrAgility = memory.read_u8(0x2029 + character*(0x80)) , CurrStamina = memory.read_u8(0x202A + character*(0x80)) , CurMgPower = memory.read_u8(0x202B + character*(0x80)) , Evade = memory.read_u8(0x202C + character*(0x80)) , Defense = memory.read_u8(0x202D + character*(0x80)) , MgEvade = memory.read_u8(0x202E + character*(0x80)) , MgDefense = memory.read_u8(0x202F + character*(0x80)) , ElementAbsorb = memory.read_u8(0x2030 + character*(0x80)) , ElementImmune = memory.read_u8(0x2032 + character*(0x80)) , ElementHalf = memory.read_u8(0x2033 + character*(0x80)) , ElementWeak = memory.read_u8(0x2034 + character*(0x80)) , WeaponSpecial = memory.read_u8(0x2038 + character*(0x80)) , EquipSpecial = memory.read_u8(0x2039 + character*(0x80)) , JobLevel = memory.read_u8(0x203A + character*(0x80)) , ABP = memory.read_u8(0x203B + character*(0x80)) , EquipableItem = memory.read_u32_le(0x2040 + character*(0x80)) , Attack = memory.read_u8(0x2044 + character*(0x80)) , CommandUsed = memory.read_u8(0x2057 + character*(0x80)) , SongSung = memory.read_u8(0x206F + character*(0x80)) , InitialStatusC = memory.read_u8(0x2070 + character*(0x80)) , InitialStatusT = memory.read_u8(0x2071 + character*(0x80)) , InitialStatusD = memory.read_u8(0x2072 + character*(0x80)) , InitialStatusP = memory.read_u8(0x2073 + character*(0x80)) , SongStrength = memory.read_u8(0x2074 + character*(0x80)) , SongSpeed = memory.read_u8(0x2075 + character*(0x80)) , SongMagic = memory.read_u8(0x2077 + character*(0x80)) , SongHero = memory.read_u8(0x2078 + character*(0x80)) , AttackGauge = memory.read_u8(0x3D7F + character*(0x0B)) } return characterTable end -------------------------------------------------------------------------------- local function CharacterInfoWorld(Character) -- Table with the parameters of allies in WORLD MAP -------------------------------------------------------------------------------- local character = Character - 1 local characterTable = {} local misc = memory.read_u8(0x0500 + character*(0x50)) characterTable = { Character = misc % 8, Gender = math.floor( misc / 0x08) % 2, Present = 1 - (math.floor( misc / 0x40) % 2), BackRow = math.floor( misc / 0x80) % 2, Job = memory.read_u8(0x0501 + character*(0x50)) , Level = memory.read_u8(0x0502 + character*(0x80)) , Experience = memory.read_u24_le(0x0503 + character*(0x50)) , CurrentHp = memory.read_u16_le(0x0506 + character*(0x50)) , TotalHp = memory.read_u16_le(0x0508 + character*(0x50)) , CurrentMp = memory.read_u16_le(0x050A + character*(0x50)) , TotalMp = memory.read_u16_le(0x050C + character*(0x50)) , EquipHead = memory.read_u8(0x050E + character*(0x50)) , EquipBody = memory.read_u8(0x050F + character*(0x50)) , EquipRelic = memory.read_u8(0x0510 + character*(0x50)) , EquipRHandSh = memory.read_u8(0x0511 + character*(0x50)) , EquipLHandSh = memory.read_u8(0x0512 + character*(0x50)) , EquipRHandWpn = memory.read_u8(0x0513 + character*(0x50)) , EquipLHandWpn = memory.read_u8(0x0514 + character*(0x50)) , MonsterCaught = memory.read_u8(0x0515 + character*(0x50)) , Command1 = memory.read_u8(0x0516 + character*(0x50)) , --(Up) Command2 = memory.read_u8(0x0517 + character*(0x50)) , --(Left) Command3 = memory.read_u8(0x0518 + character*(0x50)) , --(Right) Command4 = memory.read_u8(0x0519 + character*(0x50)) , --(Down) StatusC = memory.read_u8(0x051A + character*(0x50)) , StatusT = memory.read_u8(0x051B + character*(0x50)) , StatusD = memory.read_u8(0x051C + character*(0x50)) , StatusP = memory.read_u8(0x051D + character*(0x50)) , Actions = memory.read_u8(0x051E + character*(0x50)) , DamageMod = memory.read_u8(0x051F + character*(0x50)) , InateAbility = memory.read_u16_le(0x0520 + character*(0x50)) , MagicElementUp = memory.read_u8(0x0522 + character*(0x50)) , Weight = memory.read_u8(0x0523 + character*(0x50)) , BaseStrength = memory.read_u8(0x0524 + character*(0x50)) , BaseAgility = memory.read_u8(0x0525 + character*(0x50)) , BaseStamina = memory.read_u8(0x0526 + character*(0x50)) , BaseMgPower = memory.read_u8(0x0527 + character*(0x50)) , CurrStrength = memory.read_u8(0x0528 + character*(0x50)) , CurrAgility = memory.read_u8(0x0529 + character*(0x50)) , CurrStamina = memory.read_u8(0x052A + character*(0x50)) , CurMgPower = memory.read_u8(0x052B + character*(0x50)) , Evade = memory.read_u8(0x052C + character*(0x50)) , Defense = memory.read_u8(0x052D + character*(0x50)) , MgEvade = memory.read_u8(0x052E + character*(0x50)) , MgDefense = memory.read_u8(0x052F + character*(0x50)) , ElementAbsorb = memory.read_u8(0x0530 + character*(0x50)) , ElementImmune = memory.read_u8(0x0532 + character*(0x50)) , ElementHalf = memory.read_u8(0x0533 + character*(0x50)) , ElementWeak = memory.read_u8(0x0534 + character*(0x50)) , WeaponSpecial = memory.read_u8(0x0538 + character*(0x50)) , EquipSpecial = memory.read_u8(0x0539 + character*(0x50)) , JobLevel = memory.read_u8(0x053A + character*(0x50)) , ABP = memory.read_u16_le(0x053B + character*(0x50)) , EquipableItem = memory.read_u32_le(0x0540+ character*(0x50)) , Attack = memory.read_u16_le(0x0544 + character*(0x50)) , } return characterTable end -------------------------------------------------------------------------------- local function BattleInfo(n) -- -------------------------------------------------------------------------------- local monsterID = {} memory.usememorydomain("CARTROM") -- Read from ROM local address = 0x103000 + n*16 local Boss = math.floor( memory.readbyte(address + 15) / 0x20 ) % 2 -- Flag @ 0x20 local ID = 0 for i = 1, EnemiesMax do ID = (memory.readbyte(address + 3 + i) + 256*Boss + 1) if ID % 256 ~= 0 then monsterID[i] = TableEnemy[ID] else break end --txt(0, (6+i)*gapY, string.format("%u) %s", i, monsterID[i] ), color.black, color.yellow) end memory.usememorydomain("WRAM") -- Change back to RAM end -------------------------------------------------------------------------------- local function AttackFormula() -- Prints Attack Formula used in battle -------------------------------------------------------------------------------- local formula = memory.read_u8(0x7B2D) if formula < 0x7F then txt ( 1, 656, string.format("Formula: %2X) %s", formula, TableAttackFormula[formula+1]), color.black, color.green ) else txt ( 1, 656, "Formula: ?", color.black, color.red ) end end -------------------------------------------------------------------------------- local function target() -- WIP - Target -------------------------------------------------------------------------------- --[[ local selected = memory.read_u8( 0x7AFC ) -- local flag = memory.read_u8( 0xD0C2 ) -- single / multiple flag? local single = memory.read_u8( 0xD0C4 ) -- 00 to 07 Enemies, 08 to 0B Characters local group = memory.read_u8( 0xD0C5 ) -- 01 Targets all enemies, 02 Targets all characters local txt = "" --txt ( 1, 186, string.format("%2X", selected)) --txt ( 1, 194, string.format("%2X", flag)) if single < 8 then -- 00 to 07 Enemies txt = string.format("Enemy %u, ", single+1) elseif within (8, single, 0x0B) then -- 08 to 0B Characters txt = string.format("Player %u, ", single-7) else -- ? txt = "?, " end if group == 01 then txt = txt .. string.format("%2X - Targets all ENEMIES", group) elseif group == 02 then txt = txt .. string.format("%2X - Targets all PLAYERS", group) elseif group == 00 then txt = txt .. string.format("%2X - Single target", group) else txt = txt .. string.format("%2X - ?", group) end gui.text ( 1, 210, txt) --]] end -------------------------------------------------------------------------------- local function coordinates() -- Prints the coordinates with the position of the vehicles -------------------------------------------------------------------------------- local x = -1 -- move icons in X local y = 152 -- move icons in Y local world = memory.read_u16_le( 0x0AD6 ) if world < 5 then for i=1, 6 do --sprite = memory.read_u8( 0x0ADD + 4*(i-1)) -- sprite used?! --height = memory.read_u8( 0x0ADE + 4*(i-1)) -- height + riding X = memory.read_u8( 0x0ADF + 4*(i-1)) Y = memory.read_u8( 0x0AE0 + 4*(i-1)) txt (x+24, y+(25*i)+286, string.format ( "(%3u,%3u)", X, Y ), color.black, color.aqua) end end drawTransport(x, y) local posX = memory.read_u8( 0x0AD8 ) local posY = memory.read_u8( 0x0AD9 ) txt (x+24, 608, string.format ( "(%3u,%3u)", posX, posY ), color.black, color.white) --txt ( 200, 0*(gapY), string.format ( "Coord(%03u,%03u)", posX, posY ), color.black, color.white ) end -------------------------------------------------------------------------------- local function zone() -- Prints the zone in world map -------------------------------------------------------------------------------- -- 1 2 3 4 5 6 7 8 -- ___ ___ ___ ___ ___ ___ ___ ___ -- 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | -- |___|___|___|___|___|___|___|___| -- 2 | 2 | 3 | 2 | 3 | 2 | 3 | 2 | 3 | -- |___|___|___|___|___|___|___|___| -- 3 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | -- |___|___|___|___|___|___|___|___| -- 4 | 2 | 3 | 2 | 3 | 2 | 3 | 2 | 3 | -- |___|___|___|___|___|___|___|___| -- 5 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | -- |___|___|___|___|___|___|___|___| -- 6 | 2 | 3 | 2 | 3 | 2 | 3 | 2 | 3 | -- |___|___|___|___|___|___|___|___| -- 7 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | -- |___|___|___|___|___|___|___|___| -- 8 | 2 | 3 | 2 | 3 | 2 | 3 | 2 | 3 | -- |___|___|___|___|___|___|___|___| local world = memory.read_u16_le( 0x0AD6 ) if world < 5 then local posX = memory.read_u8( 0x0AD8 ) local posY = memory.read_u8( 0x0AD9 ) local zone = { math.floor(posX / 32) + 1, math.floor(posY / 32) + 1} local COLOR = color.white -- Color the zone in 4 parts, so you can immediately notice when you change zones, even if you're close to a corner if (zone[1] % 2 == 0) and (zone[2] % 2 == 0) then -- 0 COLOR = color.yellow elseif (zone[1] % 2 == 0) and (zone[2] % 2 == 1) then -- 1 COLOR = color.green elseif (zone[1] % 2 == 1) and (zone[2] % 2 == 0) then -- 2 COLOR = color.orange else--if (zone[1] % 2 == 1) and (zone[2] % 2 == 1) then -- 3 COLOR = color.red end txt ( 1, 626, string.format ( "Zone [%0u,%0u]", zone[1], zone[2] ), color.black, COLOR) --txt ( 200, 1*(gapY), string.format ( "Zone [%0u,%0u]", zone[1], zone[2] ), color.black, COLOR) end end -------------------------------------------------------------------------------- local function step() -- Prints all information regarding walking -------------------------------------------------------------------------------- local fsteps = memory.read_u8( 0x16A5 ) -- Dungeon steps local steps = memory.read_u8( 0x0B4F ) -- World Map steps local stepD = memory.read_u8( 0x0B56 ) -- Dungeon steps local Danger = memory.read_u16_le( 0x16A8 ) -- Danger meter local DangerH = memory.read_u8( 0x16A9 ) -- High part of Danger local DangerSeed = memory.read_u8( 0x0B60 ) -- Danger meter seed local battles = memory.read_u16_le( 0x09C0 ) -- # of battles local rBattles = memory.read_u8( 0x0B50 ) -- Random Battle index local rBattlesSeed = memory.read_u8( 0x0B5F ) -- Random battles seed --local escapes = memory.read_u16_le( 0x09B5 ) -- # of escaped battles --local group = memory.read_u16_le( 0x04F0 ) -- Enemy group local text = "" local pos = 0 -- Retrieve the next 19 values that will be compared to the Danger for i=0, 18 do pos = steps+i if pos < 256 then text = text .. string.format("%03u ", ( battle_lut[pos % 256] + DangerSeed ) % 256) else text = text .. string.format("%03u ", ( battle_lut[pos % 256] + DangerSeed+17 ) % 256) end end txt ( 0, 0*gapY, text, color.black, color.aqua ) local group, groupEncounter = 0, 0 text = "" pos = 0 -- Retrieve the next 26 values that will be used for group encounter for i=0, 25 do pos = rBattles+i if pos < 256 then groupEncounter = ((battle_lut[pos % 256]) + rBattlesSeed ) % 256 else groupEncounter = ((battle_lut[pos % 256]) + rBattlesSeed+23 ) % 256 end if groupEncounter < 90 then -- Common 1 (90/256) group = 1 elseif within( 90, groupEncounter, 179) then -- Common 2 (90/256) group = 2 elseif within(180, groupEncounter, 239) then -- Uncommon (60/256) group = 3 else -- Rare (16/256) group = 4 end text = text .. string.format("%u ", group) end --txt ( 196, 3*gapY, string.format("Group: %u [%03u]", group, groupEncounter), color.black, color.white) txt ( 60, 1*gapY, text, color.black, color.orange) txt ( 0, 1*gapY, string.format("%03u", DangerH), color.black, color.red ) txt ( 600, 1*gapY, string.format("Danger: %04X [%02X]", Danger, DangerSeed), color.black, color.red ) txt ( 580, 2*gapY, string.format("Steps: %3u %3u %3u", fsteps, steps, stepD), color.black, color.white ) txt ( 570, 3*gapY, string.format("Battle: %3u", battles) , color.black, color.white ) --txt ( 566, 4*gapY, string.format("#Battle: %3u [%02X]", rBattles, rBattlesSeed) , color.black, color.white ) --txt ( 556, 5*gapY, string.format("#Escapes: %u", escapes) , color.black, color.white) end -------------------------------------------------------------------------------- local function timer() -- Prints In-game clock timer -------------------------------------------------------------------------------- local timer = memory.read_u32_le( 0x094A ) local seconds = math.floor(timer / 60) local minutes = math.floor(seconds / 60) local hours = math.floor(minutes / 60) local frames = timer % 60 seconds = seconds % 60 minutes = minutes % 60 --hours = hours % 24 txt ( 618, 656, string.format("%02uh %02um %02us %02uf", hours, minutes, seconds, frames), color.black, color.white ) end -------------------------------------------------------------------------------- local function timerEv() -- Prints Timed Events clock timer -------------------------------------------------------------------------------- local timer = memory.read_u16_le( 0x0AFC ) if timer ~= 0 and timer ~= 0x8000 then local seconds = math.floor(timer / 60) local minutes = math.floor(seconds / 60) local frames = timer % 60 seconds = seconds % 60 minutes = minutes % 60 txt ( 618, 642, string.format(" %02um %02us %02uf", minutes, seconds, frames), color.black, "orange" ) end end -------------------------------------------------------------------------------- local function ATB( x, y, w, h, speed, Color, bgColor) -- Function that draws ATB -------------------------------------------------------------------------------- colour = transparency(Color, 0x80) bgColor = transparency(bgColor, 0xC0) gui.drawBox (x, y, x+w, y+h, colour, colour) gui.drawBox (x, y, x+w*((0x80-speed)/0x80), y+h, bgColor, bgColor) TEXT ( x, y-2, speed , color.black, 9, "Arial", "bold" ) end -------------------------------------------------------------------------------- local function battle_stats() -- Prints battle stats -------------------------------------------------------------------------------- local escape = memory.read_u8( 0x3EF0 ) local counter = memory.read_u8( 0x7C5F ) if escape == 0x80 then TEXT ( 100, -2, "Can't Escape", color.red ) else TEXT ( 84, -2, string.format("%u%% chance to Escape", escape), color.white ) end -- txt (60, 0, string.format("(%2u)", 20-counter), color.white) end -------------------------------------------------------------------------------- local function enemy_data() -- Displays enemy data in battle -------------------------------------------------------------------------------- local enemy = {} -- Holds the enemy's information local visibleTable = {} -- Determines if an enemy is visible local boxwidth = 45 -- Enemy's ATB box width local boxheight = 6 -- Enemy's ATB box height local x = 0 -- Enemy's coord X local y = 0 -- Enemy's coord Y local name = 0xFFFF -- Enemy's name local hp = 0 -- Enemy's CURRENT HP local HP = 0 -- Enemy's TOTAL HP local mp = 0 -- Enemy's CURRENT MP local MP = 0 -- Enemy's TOTAL MP local Lv = 0 -- Enemy's Level local COLOR = 0x00000000 -- Changes HP color depending on % local BackAttack = memory.read_u8(0x7C19) -- Back Attack flag -- Draws enemy's Box --BGbox ( 9, 159, 103, 214, color.gray, color.navy ) -- Change enemy page info by pressing L if keydown.L then -- L is pressed if (not Lheld) then -- L not held Lheld = true enemyPage = (enemyPage + 1) % (enemyPageMax + 1) -- Changes page end else Lheld = false -- L is lifted end -- Determine which enemies are hidden or visible visibleTable = BitOn(memory.read_u8(0x00DE), 8) for i=1, EnemiesMax do enemy[i] = EnemyInfo(i) -- Populate the enemy's information name = enemy[i].Name hp = enemy[i].CurrentHp HP = enemy[i].TotalHp mp = enemy[i].CurrentMp MP = enemy[i].TotalMp Lv = enemy[i].Level x = enemy[i].PositionX y = enemy[i].PositionY if BackAttack == 1 then x = 240 - x end -- Display the enemy's information if hp > 0 and visibleTable[9-i] == 1 and name ~= 0xFFFF then -- Display current enemyPage local chapter = { [0] = "HP, MP, ATB", [1] = "Initial Status", [2] = "Elemental Affinity\n(Absorb/Weak/Immune)", [3] = "Status Immunity", [4] = "Can't Evade", [5] = "Creature Type", [6] = "Vulnerable Commands", -- Command Immunity (reversed) [7] = "Steal & Drop" } TEXT (0, 140, positionPage(enemyPage, enemyPageMax), "aqua",10, "Arial", "regular" ) TEXT (0, 148, chapter[enemyPage], "aqua", 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ if enemyPage == 0 then -- Display Basic Info (HP, MP, ATB) ------------------------------------------------------------------------------------------------------------------------------ -- Name TEXT ( x, y + 0, string.format("%u) %s [Lv %u]", i, TableEnemy[name +1], Lv), transparency(color.white, 0xE0), 9, "Arial", "regular" ) -- Attack Gauge (painted) ATB( x, y + 10, boxwidth, boxheight, enemy[i].AttackGauge, color.black, color.yellow ) -- HP if (hp > HP/2) then -- Cannot be catched COLOR = color.lime elseif within (HP/8, hp, HP/2) then -- Needs Cornago Jar COLOR = color.yellow else --hp < HP/8 COLOR = color.red -- Can be catched end TEXT ( x, y + 16, string.format("%u/%u", hp, HP), transparency(COLOR, 0xC0), 9, "Arial", "regular" ) -- MP TEXT ( x, y + 24, string.format("%u mp", mp), transparency(color.aqua, 0xC0), 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 1 then -- Initial Status C/T/D/P ------------------------------------------------------------------------------------------------------------------------------ drawCurable ( x, y+27, enemy[i].InitialStatusC ) drawTemporary ( x, y+35, enemy[i].InitialStatusT ) drawDispellable( x, y+43, enemy[i].InitialStatusD ) drawPermanent ( x, y+51, enemy[i].InitialStatusP ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 2 then -- Elemental Affinities ------------------------------------------------------------------------------------------------------------------------------ TEXT ( x-9, y+27, "A: ", color.white, 8, "Courier New", "regular" ) drawElement ( x, y+27, enemy[i].ElementAbsorb ) TEXT ( x-9, y+35, "W: ", color.white, 8, "Courier New", "regular" ) drawElement ( x, y+35, enemy[i].ElementWeakness ) TEXT ( x-9, y+43, "I: ", color.white, 8, "Courier New", "regular" ) drawElement ( x, y+43, enemy[i].ElementImmune ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 3 then -- Status Immunity C/T/D ------------------------------------------------------------------------------------------------------------------------------ drawCurable ( x, y+27, enemy[i].ImmunityC ) drawTemporary ( x, y+35, enemy[i].ImmunityT ) drawDispellable( x, y+43, enemy[i].ImmunityD ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 4 then -- Can't Evade ------------------------------------------------------------------------------------------------------------------------------ TEXT ( x, y+27, string.format("%s", readBitwiseTable(enemy[i].CantEvade, TableAttackType)), transparency(color.white, 0xC0), 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 5 then -- Creature Type ------------------------------------------------------------------------------------------------------------------------------ TEXT ( x, y+27, string.format("%s", readBitwiseTable(enemy[i].CreatureType, TableCreature)), transparency(color.white, 0xC0), 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 6 then -- Command Immunity ------------------------------------------------------------------------------------------------------------------------------ TEXT ( x, y+27, string.format("%s", readBitwiseTable(0xFF - enemy[i].CommandImmunity, TableCommand)), transparency(color.white, 0xC0), 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ elseif enemyPage == 7 then -- Steal & Drop ------------------------------------------------------------------------------------------------------------------------------ -- Steals TEXT ( x-8, y+27, string.format ("Steals: %s, %s", TableItem[enemy[i].StealCommon+1], TableItem[enemy[i].StealRare+1]), transparency(color.lime, 0xC0), 9, "Arial", "regular" ) -- Drops TEXT ( x-8, y+35, string.format (" Drops: %s, %s", TableItem[enemy[i].DropCommon+1], TableItem[enemy[i].DropRare+1]), transparency(color.lime, 0xC0), 9, "Arial", "regular" ) ------------------------------------------------------------------------------------------------------------------------------ else -- something went wrong XD ------------------------------------------------------------------------------------------------------------------------------ print ("whoops", enemyPage) end end end end -------------------------------------------------------------------------------- local function character_data() -- Displays character data in battle -------------------------------------------------------------------------------- local character = {} -- Holds the character's information local COLOR = 0x00000000 -- Change color if hero's in 1/8 of health or less local boxwidth = 31 -- Character's ATB box width local boxheight = 6 -- Character's ATB box height local hp = 0 -- Hero's CURRENT HP local HP = 0 -- Hero's TOTAL HP local mp = 0 -- Hero's CURRENT MP local MP = 0 -- Hero's TOTAL MP local j = 0 local BackAttack = memory.read_u8(0x7C19) -- Back Attack flag -- Draws character's Box --BGbox ( 104, 159, 247, 214, color.gray, color.navy ) -- Change character's page info by pressing R if keydown.R then -- R is pressed if (not Rheld) then -- R not held Rheld = true characterPage = (characterPage + 1) % (characterPageMax + 1) -- Changes page end else Rheld = false -- R is lifted end for i=1, CharacterMax do character[i] = CharacterInfoBattle(i) -- Populate the character's information -- Display the character's information if character[i].Present == 1 then -- Display only info of current party hp = character[i].CurrentHp HP = character[i].TotalHp mp = character[i].CurrentMp MP = character[i].TotalMp x = 220 y = 35 + 26*i if BackAttack == 1 then x = 240 - x end -- Character Name + Job --[[ --TEXT == gui.drawText( x, y, str, Color, fontsize, fontfamily, fontstyle ) gui.drawBox ( 112, 167 + 12*j, 144, 165 + 12*j + 10, windowColor, windowColor) -- JOB TEXT ( 110, 164 + 12*j, TableCharacter[(character[i].Character) + 1] .. ' - ' .. TableJob[(character[i].Job)+1], transparency(color.green, 0xC0), 11, "Arial", "bold" ) --]] --MgEvade --TEXT (243, 165 + 12*j, character[i].MgEvade, color.green) -- HP if (hp) > (HP)/8 then COLOR = color.lime else COLOR = color.red end TEXT ( x, y, string.format("%u/%u", hp, HP), transparency(COLOR, 0xC0), 9, "Arial", "regular" ) -- MP TEXT ( x+8, y+8, string.format("%u/%u", mp, MP), transparency(color.aqua, 0xC0), 9, "Arial", "regular" ) -- Attack Gauge (painted) ATB ( 208, 168 + 12*j, boxwidth, boxheight, character[i].AttackGauge, color.black, color.yellow ) -- Display current characterPage local chapter = { [0] = " ", [1] = "Curable Status", [2] = "Temporary Status", [3] = "Dispellable Status", [4] = "Permanent Status", [5] = "Magic Element Up", [6] = "Element Absorb", [7] = "Element Immune", [8] = "Element Half", [9] = "Element Weak", } --txt(108, 154, positionPage(characterPage, characterPageMax), color.blue) --txt(108, 217, chapter[characterPage], color.blue) if characterPage == 0 then -- Nothing extra elseif characterPage == 1 then -- Curable Status drawCurable( 106, 154+12*i, character[i].StatusC ) elseif characterPage == 2 then -- Temporary Status drawTemporary( 106, 154+12*i, character[i].StatusT ) elseif characterPage == 3 then -- Dispellable Status drawDispellable( 106, 154+12*i, character[i].StatusD ) elseif characterPage == 4 then -- Permanent Status drawPermanent( 106, 154+12*i, character[i].StatusP ) elseif characterPage == 5 then -- Magic Element Up drawElement( 106, 154+12*i, character[i].MagicElementUp ) elseif characterPage == 6 then -- Element Absorb drawElement( 106, 154+12*i, character[i].ElementAbsorb ) elseif characterPage == 7 then -- Element Immune drawElement( 106, 154+12*i, character[i].ElementImmune ) elseif characterPage == 8 then -- Element Half drawElement( 106, 154+12*i, character[i].ElementHalf ) elseif characterPage == 9 then -- Element Weak drawElement( 106, 154+12*i, character[i].ElementWeak ) else -- something went wrong XD print ("whoops") end j = j+1 end end end -------------------------------------------------------------------------------- local function battle_RNG() -- Prints counters used for battle RNG (useful in a TAS) -------------------------------------------------------------------------------- RNG = memory.read_u8( 0x0033 ) selector = memory.read_u8( 0x7C55 ) -- 0/1 - B/A counterA = memory.read_u8( 0x003A ) counterB = memory.read_u8( 0x003B ) txt( 640, (5*gapY), string.format( "%1X [%3i,%3i]", selector, counterB, counterA), color.white, color.black ) --txt( 600, (6*gapY), string.format("%02X", RNG ), color.black, color.aqua ) end -------------------------------------------------------------------------------- local function predictRNGBattle() -- Predicts random battle stuff -------------------------------------------------------------------------------- local n = 300 -- Theoretically 256 is more than enough... local pos = 0 local encounterID = 0 local value = 0 local dangerTable = {} local valueTable = {0x0010, 0x0040, 0x00E0, 0x0100, 0x0180, 0x0200} -- {sea, ghost town, dungeon, world map, special, infested} local Danger = memory.read_u16_le( 0x16A8 ) -- Danger meter local DangerSeed = memory.read_u8( 0x0B60 ) -- Danger overflow offset local steps = memory.read_u8( 0x0B4F ) -- World Map steps local rBattle = memory.read_u8( 0x0B50 ) -- Random Battle index local rBattlesSeed = memory.read_u8( 0x0B5F ) -- random battle seed local map = memory.read_u16_le( 0x0AD6 ) -- map ID local NextEncounter = (battle_lut[(rBattle+1) % 256] + rBattlesSeed ) % 256 local EnemyFormation = 0 if NextEncounter < 90 then -- Common 1 (90/256) encounterID = 0 elseif within( 90, NextEncounter, 179) then -- Common 2 (90/256) encounterID = 1 elseif within(180, NextEncounter, 239) then -- Uncommon (60/256) encounterID = 2 else -- Rare (16/256) encounterID = 3 end memory.usememorydomain("CARTROM") -- Read from ROM local GroupFormation = memory.read_u16_le( 0x108000 + map*2 ) -- Dungeon local EnemyFormation = memory.read_u16_le( 0x106800 + (8 * GroupFormation) + (2 * encounterID) ) memory.usememorydomain("WRAM") -- Change back to RAM BattleInfo(EnemyFormation) --if Danger > 0 then -- Calculate the next n danger values to compare them later for i=1, n do pos = steps+i dangerTable[i] = ( battle_lut[pos % 256] + DangerSeed + 17*(bit.rshift(pos, 8)) ) % 256 -- Add 17 every time it loops the table end -- Determine steps in the SEA (0x0010) for i=1, n do value = bit.rshift( Danger + i*valueTable[1], 8 ) if value > dangerTable[i] then n = i txt (0, 2*gapY, string.format("%3i 0x010 steps, %2i > %2i", n, value, dangerTable[i]), color.black, color.fuchsia) break end end -- Determine steps in "GHOST TOWNS" (0x0040) for i=1, n do value = bit.rshift( Danger + i*valueTable[2], 8 ) if value > dangerTable[i] then n = i txt (0, 3*gapY, string.format("%3i 0x040 steps, %2i > %2i", n, value, dangerTable[i]), color.black, color.fuchsia) break end end -- Determine steps in DUNGEONS (0x00E0) for i=1, n do value = bit.rshift( Danger + i*valueTable[3], 8 ) if value > dangerTable[i] then n = i txt (0, 4*gapY, string.format("%3i 0x0E0 steps, %2i > %2i", n, value, dangerTable[i]), color.black, color.fuchsia) break end end -- Determine steps in WORLD MAP (0x0100) for i=1, n do value = bit.rshift( Danger + i*valueTable[4], 8 ) if value > dangerTable[i] then n = i txt (0, 5*gapY, string.format("%3i 0x100 steps, %2i > %2i", n, value, dangerTable[i]), color.black, color.fuchsia) break end end --[[ -- Determine steps in SPECIAL occasions (Moogle Sands, Fork Tower base) for i=1, n do value = bit.rshift( Danger + i*valueTable[5], 8 ) if value > dangerTable[i] then n = i txt (0, 6*gapY, string.format("%3i MOOGLE DESERT steps", i), color.black, color.fuchsia) break end end --]] --end end -------------------------------------------------------------------------------- local function room() -- Prints in which room you are (names from GBA version) -------------------------------------------------------------------------------- --local village = memory.read_u16_le( 0x0AD4 ) local map = memory.read_u16_le( 0x0AD6 ) txt (200, 42*gapY, string.format ("%03X - %s", map, TableRoom[(map % #TableRoom)+1]), color.black, color.aqua) end -------------------------------------------------------------------------------- local function terrain() -- Checks for terrain type and prints it -------------------------------------------------------------------------------- local battleground = memory.read_u8(0x04F2) -- Display battleground type if battleground < 34 then -- There are up to 34 terrains, including ID 0 txt ( 0, 656, TableBattleground[(battleground+1)], color.black, color.aqua ) end end -------------------------------------------------------------------------------- local function GroupFormation() -- Checks for group formation and prints it -------------------------------------------------------------------------------- local group = memory.read_u16_le( 0x04F0 ) if group < 0x200 then BattleInfo(group) --txt (32, 486, string.format("#%u", group), color.black, color.yellow) end end -------------------------------------------------------------------------------- local function menu_main() -- 01) Menu MAIN -------------------------------------------------------------------------------- local character = {} local flag = 0 local colour = { [0] = color.gray, -- Disabled [1] = color.white -- Enabled } local disabled = 0 local pointer = memory.read_u8(0x0153) -- Menu Selected pointer local selected = { [0] = "Job", [1] = "Ability", [2] = "Item", [3] = "Magic", [4] = "Equip", [5] = "Stats", [6] = "Config", [7] = "Save", [8] = "", -- Form (Change row) - 1st Character [9] = "", -- Form (Change row) - 2nd Character [10] = "", -- Form (Change row) - 3rd Character [11] = "", -- Form (Change row) - 4th Character [12] = "", -- 1st Character's Job/Ability/Magic/Equip/Stats [13] = "", -- 2nd Character's Job/Ability/Magic/Equip/Stats [14] = "", -- 3rd Character's Job/Ability/Magic/Equip/Stats [15] = "", -- 4th Character's Job/Ability/Magic/Equip/Stats } gui.drawBox ( 200, 15, 238, 26, windowColor, windowColor) -- JOB flag = memory.read_u24_le(0x0840) if flag == 0x040000 then -- Only Freelancer Job, so changing jobs is disabled TEXT(199, 17, string.format("%s", selected[0]), colour[0]) else TEXT(199, 17, string.format("%s", selected[0]), colour[1]) end gui.drawBox ( 200, 33, 238, 44, windowColor, windowColor) -- Ability flag = memory.read_u32_le(0x08F3) if flag == 0x00000000 then -- No one has learned any ability TEXT(199, 33, string.format("%s", selected[1]), colour[0]) else TEXT(199, 33, string.format("%s", selected[1]), colour[1]) end gui.drawBox ( 200, 64, 238, 150, windowColor, windowColor) -- Item/Magic/Equip/Stats/Config/Save TEXT(199, 61, string.format("%s", selected[2]), color.white) TEXT(199, 77, string.format("%s", selected[3]), color.white) TEXT(199, 93, string.format("%s", selected[4]), color.white) TEXT(199, 109, string.format("%s", selected[5]), color.white) TEXT(199, 125, string.format("%s", selected[6]), color.white) flag = math.floor( memory.read_u24_le(0x0144) / 0x80 ) -- "Disable" SAVE if you cannot save TEXT(199, 141, string.format("%s", selected[7]), colour[flag]) gui.drawBox ( 200, 201, 238, 210, windowColor, windowColor) -- Gil (Money) TEXT(224, 199, string.format("Gil"), color.white) for i=1, CharacterMax do character[i] = CharacterInfoWorld(i) -- Populate the character's information -- Display the character's information if character[i].Present == 1 then -- Display only info of current party gui.drawBox ( 16, 16 + 48*(i-1), 175, 26+ 48*(i-1), windowColor, windowColor) -- Character 1 TEXT(16, 17 + 48*(i-1), string.format("%s", TableCharacter[(character[i].Character) % 8 + 1]), color.white) TEXT(70, 17 + 48*(i-1), string.format("%s", TableJob[(character[i].Job)+ 1]), color.white) end end --]] end -------------------------------------------------------------------------------- local function menu_ability() -- 02) Menu ABILITY -------------------------------------------------------------------------------- local character = {} local charSelected = memory.read_u8(0x0171) -- Character selected (0-3) character = CharacterInfoWorld(charSelected+1) gui.drawBox ( 48, 15, 182, 26, windowColor, windowColor) -- Ability TEXT( 45, 17, string.format("%s", TableCharacter[character.Character+1]), color.white) TEXT(102, 17, string.format("%s", TableJob[character.Job+1]), color.white) gui.drawBox ( 200, 15, 238, 26, windowColor, windowColor) -- Ability TEXT(199, 17, "Ability", color.white) gui.drawBox ( 16, 45, 61, 54, windowColor, windowColor) -- Can Equip TEXT(12, 44, "Can Equip", color.white) gui.drawBox ( 136, 45, 205, 54, windowColor, windowColor) -- Ability TEXT(148, 44, "# of Abilities", color.white) if character.Job < 20 then -- Most Jobs (Equips 1 item ) gui.drawBox ( 24, 65, 78, 74, windowColor, windowColor) -- Job Menu TEXT(22, 64, "Job Menu", color.white) gui.drawBox ( 24, 86, 78, 94, windowColor, windowColor) -- Ability #2 (Main) TEXT(25, 85, string.format("%s", TableAttackCommand[character.Command2 + 1]), color.white) gui.drawBox ( 24, 109, 78, 118, windowColor, windowColor) -- Job Menu TEXT(22, 108, "Ability", color.white) gui.drawBox ( 24, 128, 86, 138, windowColor, windowColor) -- Ability #3 (Optional) TEXT(25, 127, string.format("%s", TableAttackCommand[character.Command3 + 1]), color.white) elseif character.Job == 20 then -- MIME (Equips 3 items) gui.drawBox ( 24, 65, 78, 74, windowColor, windowColor) -- Ability TEXT(22, 64, "Ability", color.white) gui.drawBox ( 24, 90, 78, 98, windowColor, windowColor) -- Ability #2 (Optional) TEXT(25, 89, string.format("%s", TableAttackCommand[character.Command2 + 1]), color.white) gui.drawBox ( 24, 109, 78, 118, windowColor, windowColor) -- Ability #3 (Optional) TEXT(25, 108, string.format("%s", TableAttackCommand[character.Command3 + 1]), color.white) gui.drawBox ( 24, 128, 86, 138, windowColor, windowColor) -- Ability #4 (Optional) TEXT(25, 127, string.format("%s", TableAttackCommand[character.Command4 + 1]), color.white) else -- character.Job == 21 -- FREELANCER (Equips 2 items) gui.drawBox ( 72, 45, 101, 54, windowColor, windowColor) -- Can Equip Any TEXT(70, 44, "Any", color.white) gui.drawBox ( 24, 81, 78, 90, windowColor, windowColor) -- Abilities TEXT(22, 80, "Ability", color.white) gui.drawBox ( 24, 109, 78, 118, windowColor, windowColor) -- Ability #2 (Optional) TEXT(25, 108, string.format("%s", TableAttackCommand[character.Command2 + 1]), color.white) gui.drawBox ( 24, 128, 86, 138, windowColor, windowColor) -- Ability #3 (Optional) TEXT(25, 127, string.format("%s", TableAttackCommand[character.Command3 + 1]), color.white) end if memory.read_u8(0x0204) == 0 then gui.drawBox ( 24, 163, 86, 170, windowColor, windowColor) -- Done TEXT(22, 161, "Done", color.white) end end -------------------------------------------------------------------------------- local function menu_job() -- 03) Menu JOB -------------------------------------------------------------------------------- local character = {} local charSelected = memory.read_u8(0x0171) -- Character selected (0-3) local jobSelected = memory.read_u8(0x01D8) -- Job selected (0-21) character = CharacterInfoWorld(charSelected+1) gui.drawBox ( 48, 15, 182, 26, windowColor, windowColor) -- JOB TEXT( 45, 17, string.format("%s", TableCharacter[character.Character+1]), color.white) TEXT(102, 17, string.format("%s", TableJob[character.Job+1]), color.white) gui.drawBox ( 200, 15, 238, 26, windowColor, windowColor) -- JOB TEXT(199, 17, "Job", color.white) gui.drawBox ( 16, 168, 70, 178, windowColor, windowColor) -- Description TEXT(15, 169, string.format("%s", TableJob[jobSelected+1]), color.white) gui.drawBox ( 168, 168, 190, 178, windowColor, windowColor) -- Equip TEXT(164, 169, "Equip", color.white) end -------------------------------------------------------------------------------- local function menu_equip() -- 04) Menu EQUIP -------------------------------------------------------------------------------- local charSelected = memory.read_u8(0x0171) -- Character selected (0-3) local jobSelected = memory.read_u8(0x01D8) -- Job selected (0-21) character = CharacterInfoWorld(charSelected+1) gui.drawBox ( 24, 13, 46, 23, windowColor, windowColor) -- EQUIP TEXT(22, 13, string.format("Equip"), color.white) gui.drawBox ( 64, 13, 101, 23, windowColor, windowColor) -- OPTIMUM TEXT(62, 13, string.format("Optimum"), color.white) gui.drawBox ( 120, 13, 142, 23, windowColor, windowColor) -- REMOVE TEXT(118, 13, string.format("Rmv"), color.white) gui.drawBox ( 160, 13, 199, 23, windowColor, windowColor) -- EMPTY (Can't remove last letter because of an overlap) TEXT(158, 13, string.format("Empty"), color.white) gui.drawBox ( 216, 13, 238, 23, windowColor, windowColor) -- END TEXT(214, 13, string.format("End"), color.white) gui.drawBox ( 16, 29, 53, 90, windowColor, windowColor) -- Part TEXT(14, 29, string.format("R. Hand"), color.white) TEXT(14, 41, string.format("L. Hand"), color.white) TEXT(14, 57, string.format("Head"), color.white) TEXT(14, 69, string.format("Body"), color.white) TEXT(14, 81, string.format("Relic"), color.white) gui.drawBox ( 80, 29, 140, 90, windowColor, windowColor) -- Item TEXT(78, 29, string.format("%s", TableItem[character.EquipRHandWpn+1]), color.white) -- R. Hand Weapon TEXT(78, 29, string.format("%s", TableItem[character.EquipRHandSh+1]), color.white) -- R. Hand Shield TEXT(78, 41, string.format("%s", TableItem[character.EquipLHandWpn+1]), color.white) -- L. Hand Weapon TEXT(78, 41, string.format("%s", TableItem[character.EquipLHandSh+1]), color.white) -- L. Hand Shield TEXT(78, 57, string.format("%s", TableItem[character.EquipHead+1]), color.white) -- Head TEXT(78, 69, string.format("%s", TableItem[character.EquipBody+1]), color.white) -- Body TEXT(78, 81, string.format("%s", TableItem[character.EquipRelic+1]), color.white) -- Relic gui.drawBox ( 176, 29, 238, 50, windowColor, windowColor) -- Character / Job TEXT(174, 29, string.format("%s", TableCharacter[character.Character+1]), color.white) TEXT(174, 41, string.format("%s", TableJob[character.Job+1]), color.white) gui.drawBox ( 152, 57, 175, 68, windowColor, windowColor) -- Equip TEXT(148, 57, "Equip", color.white) -- Equip --gui.drawBox ( 152, 69, 175, 80, windowColor, windowColor) -- 2-Handed --TEXT(148, 69, "2-Handed", color.white) -- Equip -- *** NEEDS WORK *** gui.drawBox ( 16, 98, 89, 211, windowColor, windowColor) -- Inventory for i = 0, 8 do item = memory.read_u8(0x7A00 + i) TEXT(14, 101+(12*i), string.format("%s", TableItem[item+1]), color.white) -- end gui.drawBox ( 128, 98, 190, 211, windowColor, windowColor) -- Attributes TEXT(126, 97, "Strength", color.white) -- Strength TEXT(126, 109, "Agility", color.white) -- Agility TEXT(126, 121, "Vitality", color.white) -- Vitality TEXT(126, 133, "Mg. Power", color.white) -- Magic Power TEXT(126, 149, "Attack", color.white) -- Attack TEXT(126, 161, "Defense", color.white) -- Defense TEXT(126, 173, "Evade %", color.white) -- Evade % TEXT(126, 185, "Mg. Defense", color.white) -- Magic Defense TEXT(126, 201, "Weight", color.white) -- Equipment Weight end -------------------------------------------------------------------------------- local function menu_status() -- 05) Menu STATUS -------------------------------------------------------------------------------- local charSelected = memory.read_u8(0x0171) -- Character selected (0-3) --local jobSelected = memory.read_u8(0x01D8) -- Job selected (0-21) character = CharacterInfoWorld(charSelected+1) gui.drawBox ( 200, 16, 240, 23, windowColor, windowColor) -- Stats TEXT(198, 14, "Status", color.white) -- Character gui.drawBox ( 16, 21, 102, 31, windowColor, windowColor) -- Character / Level TEXT(14, 21, string.format("%s", TableCharacter[character.Character+1]), color.white) -- Character TEXT(74, 21, "Level", color.white) -- Level gui.drawBox ( 145, 21, 174, 31, windowColor, windowColor) -- Commands (AKA Menu) TEXT(141, 21, "Ability", color.white) -- Command (Menu) gui.drawBox ( 156, 42, 210, 86, windowColor, windowColor) TEXT(154, 42, string.format("%s", TableAttackCommand[character.Command1+1]), color.white) -- Command 1 TEXT(154, 54, string.format("%s", TableAttackCommand[character.Command2+1]), color.white) -- Command 2 TEXT(154, 66, string.format("%s", TableAttackCommand[character.Command3+1]), color.white) -- Command 3 TEXT(154, 78, string.format("%s", TableAttackCommand[character.Command4+1]), color.white) -- Command 4 gui.drawBox ( 16, 36, 102, 46, windowColor, windowColor) -- Job TEXT(14, 36, string.format("%s", TableJob[character.Job+1]), color.white) -- Job gui.drawBox ( 23, 113, 118, 122, windowColor, windowColor) -- Experience TEXT(21, 112, "Experience", color.white) -- Xp gui.drawBox ( 23, 133, 118, 142, windowColor, windowColor) -- Next Level TEXT(21, 132, "Next Level", color.white) -- Next lv gui.drawBox ( 23, 157, 118, 166, windowColor, windowColor) -- Abilities TEXT(21, 156, "Abilities", color.white) -- Abilities gui.drawBox ( 23, 181, 118, 190, windowColor, windowColor) -- Can Equip TEXT(21, 179, "Can Equip", color.white) -- gui.drawBox ( 128, 99, 190, 206, windowColor, windowColor) -- Attributes TEXT(126, 97, "Strength", color.white) -- Strength TEXT(126, 109, "Agility", color.white) -- Agility TEXT(126, 121, "Vitality", color.white) -- Vitality TEXT(126, 133, "Mg. Power", color.white) -- Magic Power TEXT(126, 149, "Attack", color.white) -- Attack TEXT(126, 161, "Defense", color.white) -- Defense TEXT(126, 173, "Evade %", color.white) -- Evade % TEXT(126, 185, "Mg. Defense", color.white) -- Magic Defense TEXT(126, 197, "Weight", color.white) -- Equipment Weight end -------------------------------------------------------------------------------- local function menu_shop() -- 06) Menu SHOP -------------------------------------------------------------------------------- gui.drawBox ( 11, 10, 60, 35, windowColor, windowColor) -- WEAPON / ARMOR / ITEM / MAGIC local pointer = memory.read_u8( 0x0201 ) local store = memory.read_u8( 0x0135 ) --TEXT(15, 20, string.format("%s", TableShop[store+1]), color.white) gui.drawBox ( 24, 45, 37, 55, windowColor, windowColor) -- Buy TEXT(22, 45, "Buy", color.white) if store ~= 3 then -- Can't sell in magic store gui.drawBox ( 56, 45, 70, 55, windowColor, windowColor) -- Sell TEXT(54, 45, "Sell", color.white) end gui.drawBox ( 88, 45, 102, 55, windowColor, windowColor) -- End TEXT(86, 45, "End", color.white) gui.drawBox (128, 45, 149, 55, windowColor, windowColor) -- Have TEXT(126, 45, "Have", color.white) gui.drawBox (224, 45, 238, 55, windowColor, windowColor) -- Gil TEXT(222, 45, "Gil", color.white) if pointer % 12 == 2 then -- Buy Items gui.drawBox ( 32, 72, 102, 170, windowColor, windowColor) for i=0, 7 do ID = memory.read_u8(0x2826 + i) if ID == 0 then break end if store ~= 3 then -- No magic store TEXT(30, 73 + (12*i), string.format("%s", TableItem[ID+1]), color.white) else TEXT(30, 73 + (12*i), string.format("%s", TableMagicID[ID+1]), color.white) end end elseif pointer % 12 == 6 then -- Sell Items gui.drawBox ( 32, 76, 97, 206, windowColor, windowColor) -- Sell Items (Left) gui.drawBox (144, 76, 209, 206, windowColor, windowColor) -- Sell Items (Right) local scroll = memory.read_u8( 0x016B ) -- How much has the screen scrolled for i=0, 10 do ID = memory.read_u8( 0x0640 + scroll + 2*i + 0 ) TEXT( 30, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item ID = memory.read_u8( 0x0640 + scroll + 2*i + 1 ) TEXT( 141, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item end elseif pointer % 12 == 4 then -- Quantity gui.drawBox ( 67, 10, 244, 35, windowColor, windowColor) -- Description TEXT( 71, 20, "How Many?", color.white ) gui.drawBox ( 32, 76, 97, 86, windowColor, windowColor) -- Item ID = memory.read_u8(0x2826 + memory.read_u8(0x2807) ) -- Works fine for buy / problems with sell TEXT( 30, 77, TableItem[ID+1], color.white ) gui.drawBox ( 24, 97, 97, 106, windowColor, windowColor) -- Owned TEXT( 22, 95, "Owned", color.white ) gui.drawBox ( 24, 113, 97, 122, windowColor, windowColor) -- Equipped TEXT( 22, 111, "Equipped", color.white ) gui.drawBox ( 184, 89, 198, 98, windowColor, windowColor) -- Owned TEXT( 182, 87, "Gil", color.white ) end end -------------------------------------------------------------------------------- local function menu_item() -- 07) Menu ITEM -------------------------------------------------------------------------------- local scroll = memory.read_u8( 0x016B ) -- How much has the screen scrolled local pos = memory.read_u8( 0x0153 ) -- Position of the pointer gui.drawBox (12, 10, 51, 27, windowColor, windowColor) -- ITEM TEXT(16, 13, "ITEM", color.white) gui.drawBox (80, 15, 103, 22, windowColor, windowColor) TEXT(78, 13, "USE", color.white) gui.drawBox (128, 15, 158, 22, windowColor, windowColor) TEXT(126, 13, "SORT", color.white) gui.drawBox (184, 13, 237, 22, windowColor, windowColor) TEXT(182, 13, "SPECIAL", color.white) txt (30, 177, string.format("%s / %s", pos, scroll ), color.black, color.yellow) if pos == 0 then -- USE TEXT( 78, 13, "USE", color.orange ) gui.drawBox ( 32, 76, 97, 206, windowColor, windowColor) -- Background to block Japanese text gui.drawBox (144, 76, 209, 206, windowColor, windowColor) -- Background to block Japanese text for i=0, 10 do local ID = memory.read_u8( 0x0640 + scroll + 2*i + 0 ) TEXT( 30, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item local ID = memory.read_u8( 0x0640 + scroll + 2*i + 1 ) TEXT( 142, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item end elseif pos == 1 then -- ITEM??? TEXT( 0, 0, "?", color.orange ) elseif pos == 2 then -- SORT TEXT( 126, 13, "SORT", color.orange ) gui.drawBox ( 32, 76, 97, 206, windowColor, windowColor) -- Background to block Japanese text gui.drawBox (144, 76, 209, 206, windowColor, windowColor) -- Background to block Japanese text for i=0, 10 do local ID = memory.read_u8( 0x0640 + scroll + 2*i + 0 ) TEXT( 30, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item local ID = memory.read_u8( 0x0640 + scroll + 2*i + 1 ) TEXT( 142, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item end elseif pos == 3 then -- SPECIAL TEXT( 182, 13, "SPECIAL", color.orange ) elseif within(4, pos, 25) then -- Item selected gui.drawBox ( 32, 76, 97, 206, windowColor, windowColor) -- Background to block Japanese text gui.drawBox (144, 76, 209, 206, windowColor, windowColor) -- Background to block Japanese text for i=0, 10 do local ID = memory.read_u8( 0x0640 + scroll + 2*i + 0 ) TEXT( 30, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item local ID = memory.read_u8( 0x0640 + scroll + 2*i + 1 ) TEXT( 142, 77 + 12*i, TableItem[ID+1], color.white ) -- NAME of item end --TEXT( 29, 77, TableItem[ID+1], color.orange ) -- NAME of item --TEXT( 29, 88, TableItem[ID+1], color.orange ) -- NAME of item elseif within(28, pos, 31) then -- Used on a hero TEXT( 0, -3, string.format("Character %u", pos-27 ), color.orange ) end end -------------------------------------------------------------------------------- local function menu_magic() -- 08) Menu MAGIC -------------------------------------------------------------------------------- --local row = memory.read_u8(0x0200) --0950 to 0963 = Magic local address = memory.read_u8(0x0157) -- Has a minor bug when loading menu... local selected = memory.read_u8(0x29E2) local magic = { [0] = "Sword", [1] = "White", [2] = "Black", [3] = "Time", [4] = "Summon", [5] = "Blue", [6] = "Song", } if address == 18 then gui.drawBox ( 16, 15, 54, 54, windowColor, windowColor) TEXT(14, 13, "White", color.white) TEXT(14, 29, "Black", color.white) TEXT(14, 45, "Time", color.white) gui.drawBox ( 16, 70, 54, 126, windowColor, windowColor) TEXT(14, 68, "Summon", color.white) TEXT(14, 84, "Sword", color.white) TEXT(14, 100, "Blue", color.white) TEXT(14, 116, "Song", color.white) else local charSelected = memory.read_u8(0x0171) -- Character selected (0-3) character = CharacterInfoWorld(charSelected+1) gui.drawBox ( 16, 13, 54, 27, windowColor, windowColor) TEXT( 14, 17, string.format("%s", magic[selected]), color.white) gui.drawBox ( 48, 43, 80, 54, windowColor, windowColor) -- Character TEXT( 45, 45, string.format("%s", TableCharacter[character.Character+1]), color.white) end gui.drawBox (160, 43, 238, 54, windowColor, windowColor) -- Job TEXT(158, 45, string.format("%s", TableJob[character.Job+1]), color.white) end -------------------------------------------------------------------------------- local function menu_config() -- 09) Menu CONFIG -------------------------------------------------------------------------------- local x1, x2, x3, x4 = 29, 117, 174, 222 local flag = 0 local colour = { [0] = color.gray, -- unselected [1] = color.white -- selected } gui.drawBox (186, 9, 237, 28, color.gray, windowColor) -- CONFIG TEXT(195, 12, "Config", color.white ) gui.drawBox (32, 33, 102, 182, windowColor, windowColor) -- Background to block Japanese text TEXT(x1, 33, "Battle Mode", color.white ) gui.drawBox (x2+2, 33, x4, 42, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2C9C) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 33, "Active", colour[1-flag] ) TEXT(x3, 33, "Wait", colour[flag] ) TEXT(x1, 49, "Battle Speed", color.white ) gui.drawBox (x2+2, 59, x4, 66, windowColor, windowColor) -- Background to block Japanese text TEXT(x2, 57, "Fast", color.white ) TEXT(x3, 57, "Slow", color.white ) TEXT(x1, 65, "Message Speed", color.white ) TEXT(x1, 77, "Command Set", color.white ) gui.drawBox (x2+2, 77, x4, 86, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2C9F) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 77, "Window", colour[1-flag] ) TEXT(x3, 77, "Short", colour[flag] ) TEXT(x1, 89, "ATB Gauge", color.white ) gui.drawBox (x2+2, 89, x4, 98, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA0) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 89, "On", colour[1-flag] ) TEXT(x3, 89, "Off", colour[flag] ) TEXT(x1, 105, "Sound", color.white ) gui.drawBox (x2+2, 105, x4, 114, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA1) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 105, "Stereo", colour[1-flag] ) TEXT(x3, 105, "Mono", colour[flag] ) TEXT(x1, 117, "Cursor Position", color.white ) gui.drawBox (x2+2, 117, x4, 126, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA2) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 117, "Reset", colour[1-flag] ) TEXT(x3, 117, "Memory", colour[flag] ) TEXT(x1, 129, "Re-equip", color.white ) gui.drawBox (x2+2, 129, x4, 138, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA3) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 129, "Optimum", colour[1-flag] ) TEXT(x3, 129, "Empty", colour[flag] ) TEXT(x1, 145, "Controller", color.white ) gui.drawBox (x2+2, 145, x4, 154, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA4) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 145, "Normal", colour[1-flag] ) TEXT(x3, 145, "Custom", colour[flag] ) gui.drawBox (x2+2, 157, x4, 166, windowColor, windowColor) -- Background to block Japanese text flag = memory.read_u8(0x2CA5) % 2 -- It should normally be either 0 or 1, but lets make sure it'll be TEXT(x2, 157, "Single", colour[1-flag] ) TEXT(x3, 157, "Multi", colour[flag] ) TEXT(x1, 173, "Color", color.white ) --gui.drawLine (102, 0, 102, 255) end -------------------------------------------------------------------------------- local function menu_dropped() -- 10) Menu DROPPED ITEM -------------------------------------------------------------------------------- end -------------------------------------------------------------------------------- local function menu_save() -- 11) Menu SAVE -------------------------------------------------------------------------------- gui.drawBox (112, 17, 134, 26, windowColor, windowColor) -- SAVE TEXT(110, 15, "Save", color.white) end -------------------------------------------------------------------------------- local function menu_load() -- 12) Menu LOAD (& START of game) -------------------------------------------------------------------------------- --gui.drawBox (104, 17, 155, 26, windowColor, windowColor) -- NEW GAME --TEXT(102, 15, "New Game", color.white) end -------------------------------------------------------------------------------- local function menu_rename() -- 13) Menu RENAME Buttz -------------------------------------------------------------------------------- gui.drawBox ( 80, 13, 110, 22, windowColor, windowColor) -- HIRAGANA TEXT( 78, 11, "Hiragana", color.white) gui.drawBox ( 129, 13, 158, 22, windowColor, windowColor) -- KATAKANA TEXT(127, 11, "Katakana", color.white) gui.drawBox ( 208, 13, 230, 22, windowColor, windowColor) -- END TEXT(206, 11, "End", color.white) end -------------------------------------------------------------------------------- local function lua_credits() -- LUA credits to me, samurai goroh -------------------------------------------------------------------------------- TEXT( 0, 204, '-----------------------------------------------', color.green) TEXT( 0, 211, 'FFV Lua script by samurai goroh', color.green) TEXT( 0, 216, '-----------------------------------------------', color.green) end -------------------------------------------------------------------------------- local function main() -- MAIN -------------------------------------------------------------------------------- local address = memory.read_u16_le(0x014D) windowColor = getWindowColor() -- Gets color of window (although the conversion is a bit off) if (address == 0x0310) then -- In Battle keydown = joypad.get(1) -- Gets joypad input of controller #1 --battle_RNG() battle_stats() enemy_data() character_data() AttackFormula() --target() GroupFormation() --terrain() timer() timerEv() elseif (address == 0x0000) then -- Not in Battle local world = memory.read_u8( 0x014B ) local menu = memory.read_u8( 0x0143 ) timer() timerEv() if world == 2 or world == 1 then -- World Map (sort of) coordinates() zone() predictRNGBattle() step() room() terrain() else if menu == 1 then -- MAIN menu or WORLD MAP menu_main() elseif menu == 2 then -- ABILITY menu menu_ability() elseif menu == 3 then -- JOB menu menu_job() elseif menu == 4 then -- EQUIP menu menu_equip() elseif menu == 5 then -- STATUS menu menu_status() elseif menu == 6 then -- SHOP menu menu_shop() elseif menu == 7 then -- ITEM menu menu_item() elseif menu == 8 then -- MAGIC menu menu_magic() elseif menu == 9 then -- CONFIG menu menu_config() elseif menu == 10 then -- DROPPED ITEM menu menu_dropped() elseif menu == 11 then -- SAVE GAME menu menu_save() elseif menu == 12 then -- LOAD GAME menu menu_load() elseif menu == 13 then -- RENAME Butz menu_rename() elseif menu == 14 then -- START of the game --txt (200, 200, "HELLO WORLD", color.red) end end else --print (address) -- Unknown, print it to find out lua_credits() end --sandbox() end -------------------------------------------------------------------------------- local function battle_LUT() -- Retrieve the LUT located @ C0/FEC0 -------------------------------------------------------------------------------- memory.usememorydomain("CARTROM") -- Read from ROM for i=0, 255 do battle_lut[i] = memory.read_u8( 0x00FEC0 + i) -- Look Up Table for RNG end memory.usememorydomain("WRAM") -- Change back to RAM end -------------------------------------------------------------------------------- local function sandbox() -- Sandbox -------------------------------------------------------------------------------- local h1, h2, h3 = client.borderheight() , client.bufferheight(), client.screenheight() local w1, w2, w3 = client.borderwidth(), client.bufferwidth(), client.screenwidth() TEXT (0, 0, string.format("(%u, %u)", h1,w1), color.white, 10, "Arial", "regular") TEXT (0, 10, string.format("(%u, %u)", h2,w2), color.white, 10, "Arial", "regular") TEXT (0, 20, string.format("(%u, %u)", h3,w3), color.white, 10, "Arial", "regular") end --****************************************************************************-- battle_LUT() -- Run once while true do -- Idle loop. Prevents pre-LUA pause state main() emu.frameadvance() end --****************************************************************************-- --readbyte -> 1 byte XX read_u8 --readword -> 2 bytes XXXX read_u16_le --... -> 3 bytes XXXXXX read_u24_le --readdword -> 4 bytes XXXXXXXX read_u32_le