Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Features:
- -- 1. Encounter prediction: predicts steps until encounter, and what will be encountered.
- -- Does not predict front/back/pincer/side/preemptive variants, not will it work properly
- -- on the floating continent. (there is tentative support for this (which actually makes up
- -- a good part of the code), but it is buggy, and only works well when one is on the world map,
- -- and has 3 or 4 chars in party, so it is disabled by default)
- -- 2. Outline treasure chests and show their contents and status (green = untaken, red = taken)
- -- 3. Outline squares that trigger events. Blue = transition to new area, light blue = transition
- -- to same area, very light blue = transition to map, yellow = unclassified event.
- -- 4. In battle, hp and mp bars are displayed over the enemies, as well as their battle gauges.
- -- Their level is also displayed. On gau's turns, a "?" is displayed by any monster whose
- -- rage is not known. Additionally, the enemies' resistances etc. are displayed in a compact
- -- but hopefully readable manner, as a set of 4 3x3 sqares of pixels, where each has the
- -- following format:
- -- fil ; fire (red) ice (blue) lightning (yellow)
- -- pwp ; poison (green) wind (gray) holy (white)
- -- ew ; earth (brown) water (blue)
- -- The order of the sqares is, from left to right, absorb, nullify, resist, weak.
- -- 5. Extra information is displayed for the currently selected monster.
- -- normally, only its drops and hp/mp are displayed, but if locke is selecting the
- -- monster with the steal command, its steals are also listed. If relm is selecting
- -- a monster with control or sketch, that information will also be indicated.
- -- 6. While in the rage menu, information about what the selected rage does is
- -- displayed. Only the attack part of the rage is displayed so far, since I haven't thought
- -- of a compact way of displaying all the status information associated with a rage.
- addHours = 0
- addMinutes = 4
- addSeconds = 9
- addFrames = 21
- textX = 160
- textY = 120
- lMode1 = memory.readword(0x7e1501)
- lMode2 = memory.readbyte(0x7e1503)
- lMode3 = memory.readbyte
- cMode1 = memory.readword(0x7e1501)
- cMode2 = memory.readbyte(0x7e1503)
- autoText = false
- drawpixel = function(x,y,color)
- if x < 0 or y < 0 then return end
- if x >= 0x100 or y >= 0xE0 then return end
- gui.drawpixel(x,y,color)
- end
- -- the following section handles out of bounds checking.
- -- This will hopefully not be necessary in later versions of snes9x-lua
- -- The bounds checking for lines is slightly more complicated, so I did
- -- not bother implementing it properly.
- min = function(a,b) if a < b then return a else return b end end
- max = function(a,b) if a < b then return b else return a end end
- order = function(a,b) if a > b then return b, a else return a,b end end
- olddrawbox = gui.drawbox
- gui.drawbox = function(x1,y1,x2,y2,color)
- x1,x2 = order(x1,x2)
- y1,y2 = order(y1,y2)
- x1 = min(max(0,x1),255)
- y1 = min(max(0,y1),238)
- x2 = min(max(0,x2),255)
- y2 = min(max(0,y2),238)
- olddrawbox(x1,y1,x2,y2,nil,color)
- end
- oldtext = gui.text
- gui.text = function(x,y,text)
- if x >= 0 and x < 256 and y >= 0 and y < 239 then
- oldtext(x,y,text)
- end
- end
- horline = function(x1,y,x2,color)
- x1,x2 = order(x1,x2)
- x1 = min(max(0,x1),255)
- x2 = min(max(0,x2),255)
- if y >= 0 and y < 239 then
- gui.drawline(x1,y,x2,y,color)
- end
- end
- vertline = function(x,y1,y2,color)
- y1,y2 = order(y1,y2)
- y1 = min(max(0,y1),238)
- y2 = min(max(0,y2),238)
- if x >= 0 and x < 256 then
- gui.drawline(x,y1,x,y2,color)
- end
- end
- startgauge = function(x,y,w)
- gx, gy, gw = x, y, w
- end
- drawgauge = function(c,m,col)
- if m == 0 then m = 1 end
- local g = c*gw/m
- horline(gx,gy,gx+g,col)
- horline(gx+g,gy,gx+gw,"#000000")
- gy = gy-1
- end
- tochar = function(i)
- if i < 0x80 then return ""
- elseif i < 0x9a then return string.char(string.byte("A")+i-0x80)
- elseif i < 0xb4 then return string.char(string.byte("a")+i-0x9a)
- elseif i < 0xbe then return string.char(string.byte("0")+i-0xb4)
- elseif i == 0xfe then return " "
- else return "" end
- end
- readsnesstring = function(from,maximum)
- local res = ""
- local tmp = memory.readbyte(from)
- local i = 0
- while tmp ~= 0xFF do
- if i == maximum then break end
- res = res .. tochar(tmp)
- from = from+1
- tmp = memory.readbyte(from)
- i = i+1
- end
- return res
- end
- getitemname = function(id)
- return readsnesstring(0xd2b300+0xd*id+1,12)
- end
- getmonstername = function(id)
- return readsnesstring(0xcfc050+0xa*id,10)
- end
- getattackname = function(id)
- local x = 0
- local maxlen = 10
- if id < 0x36 then
- x = id*7
- maxlen = 7
- elseif id < 0x51 then
- x = id*8-0x36
- maxlen = 8
- elseif id < 0x56 then x = id*0xA-0xd8
- else x = id*0xA-0xd8 -- vet ikke hvorfor indeksen blir d8 her.
- --else id < 0x5b then x = id*0xA-0xc4
- end
- return readsnesstring(0xe6f567+x,maxlen)
- end
- -- This is probably not the best way of determining the game mode, but it works.
- mode_battle = function()
- return memory.readword(0x7e1501) == 0x0ba7 and memory.readbyte(0x7e1503) == 0xC1
- end
- mode_cave = function()
- return memory.readword(0x7e1501) == 0x0182 and memory.readbyte(0x7e1503) == 0xC0
- end
- mode_map = function()
- return memory.readword(0x7e1501) == 0xa728 and memory.readbyte(0x7e1503) == 0xEE
- end
- mode_menu = function()
- return memory.readword(0x7e1501) == 0x1387 and memory.readbyte(0x7e1503) == 0xC3
- end
- function HandleKeys()
- keys = input.get()
- if press('T') then
- autoText = not autoText
- end
- last_keys = keys
- end
- function press(button)
- if keys[button] and not last_keys[button] then
- return true
- end
- return false
- end
- hours = 0
- minutes = 0
- seconds = 0
- milliseconds = 0
- function CalculateTime()
- frames = snes9x.framecount()
- frames = frames + addHours * 216000 + addMinutes * 3600 + addSeconds * 60 + addFrames
- hours = math.floor(frames / 216000)
- minutes = math.floor((frames - hours * 216000) / 3600)
- seconds = math.floor((frames - hours * 216000 - minutes * 3600) / 60)
- milliseconds = math.floor((frames - hours * 216000 - minutes * 3600 - seconds * 60) * 100 / 60)
- end
- function OutputTime()
- gui.text(textX, textY, "Time: " .. hours .. ":" .. string.format("%02d",minutes) .. ":" .. string.format("%02d",seconds) .. "." .. string.format("%02d",milliseconds))
- gui.text(textX, textY + 10, "Offset: " .. addHours .. ":" .. string.format("%02d",addMinutes) .. ":" .. string.format("%02d",addSeconds) .. "." .. string.format("%02d",math.floor(addFrames * 100 / 60)))
- end
- -- prints a compact representation of elemental properties.
- -- There are 8 elements. Each is assigned a color, and a place
- -- in a 3x3 matrix of pixels.
- -- fil ; fire (red) ice (blue) lightning (yellow)
- -- pwp ; poison (green) wind (gray) holy (white)
- -- ew ; earth (brown) water (blue)
- -- Colors need not be uniqe, as the position fixes things.
- -- This is then surrounded by black border.
- print_element = function(x,y,elem)
- -- first draw the border
- horline(x, y, x+4, "#404040")
- vertline(x+4, y, y+4, "#404040")
- vertline(x, y, y+4, "#404040")
- horline(x, y+4, x+4, "#404040")
- -- now draw the elements
- local x,y=x+1,y+1
- putpix = function(x,y,b,c)
- if b == 1 then drawpixel(x,y,c) else drawpixel(x,y,"#000000") end
- end
- cols = {
- "#ff0000","#0000ff","#ffff00",
- "#00ff00","#808080","#ffffff",
- "#a08000","#0000ff","#000000"
- }
- for i = 1, 9 do
- dx, dy = (i-1)%3, math.floor((i-1)/3)
- putpix(x+dx,y+dy,elem % 2,cols[i])
- elem = math.floor(elem/2)
- end
- end
- get_special = function(id)
- -- Information about the special attack
- -- This is used by rage, sketch, control.
- local special = memory.readbyte(0xcf001f+0x20*id)
- local specialn = readsnesstring(0xcfd0d0+id*10,10)
- local no_damage,no_dodge = bit(special, 6),bit(special,7)
- special = special % 0x40
- desc = "???"
- if special == 0x30 then desc = "absorb hp"
- elseif special == 0x31 then desc = "absorb mp"
- elseif special >= 0x32 then desc = "remove reflect"
- elseif special >= 0x20 then desc = string.format("+%d%%",(special-0x1f)*50)
- else
- local descs = { "Dark","Zombie","Poison","MagiTek","Clear","Imp","Petrify",
- "Death", "Condemned", "Near Fatal", "Image", "Mute", "Berserk",
- "Muddle", "Seizure", "Sleep", "Dance", "Regen", "Slow", "Haste",
- "Stop", "Shell", "Safe", "Reflect", "Rage", "Freeze", "Life 3",
- "Morph", "Chant!", "Disappear!", "Dog block", "Float" }
- desc = descs[special+1]
- end
- specialn = specialn.." ("..desc..")"
- return specialn, no_damage, no_dodge
- end
- print_status = function(status)
- -- Må finne ut hva bitsene i hver status byte betyr.
- end
- -- bit operations, since lua is silly enough to miss these
- bit = function(n,i) return math.floor(n/2^i) % 2 end
- bor = function(a,b)
- local c = 0
- local pot = 1
- while a ~= 0 or b ~= 0 do
- if a % 2 == 1 or b % 2 == 1 then c = c+pot end
- a = math.floor(a/2)
- b = math.floor(b/2)
- pot = pot*2
- end
- return c
- end
- -- to get the pixel distance from an encounter, we
- -- need to fix an occational off-by-1 error for
- -- count. this happens on the first frame when we reach
- -- a whole square. we thus need to keep track of whether
- -- the last position was whole or not
- last_position_whole = true
- while true do
- -- Are we in battle?
- offset = 100
- if mode_battle() then
- --snes9x.speedmode("maximum")
- -- memory.writebyte(0x7e3bfc, 0)
- -- memory.writebyte(0x7e3bfd, 0)
- -- memory.writebyte(0x7e3bfe, 0)
- -- memory.writebyte(0x7e3bff, 0)
- -- memory.writebyte(0x7e3c00, 0)
- -- memory.writebyte(0x7e3c01, 0)
- -- memory.writebyte(0x7e3c02, 0)
- -- memory.writebyte(0x7e3c03, 0)
- -- memory.writebyte(0x7e3c04, 0)
- -- memory.writebyte(0x7e3c05, 0)
- -- memory.writebyte(0x7e3c06, 0)
- -- memory.writebyte(0x7e3c07, 0)
- sel_side, sel_i = memory.readbyte(0x7e7ace), memory.readbyte(0x7e7acf)
- sel_enemy, sel_party = memory.readbyte(0x7e7b7e),memory.readbyte(0x7e7b7d)
- sel_multi = memory.readbyte(0x7e7b7f)
- -- loop through present monsters
- for i = 0, 5 do
- -- a few shortcuts
- j, k = 2*i, 2*(4+i)
- state = memory.readword(0x7e3aa0+k)
- if state ~= 0 and bit(state,15) ~= 1 then
- -- get coordinates (we should know the size of the monster too, but we don't)
- x = memory.readbyte(0x7e80c2+1+j)
- -- this size is really the x-offset of the pointing hand relative to the start
- -- of the sprite. For a normal attack, this works fine, but for monsters on the
- -- right hand side of the screen, this offset is 0, as the hand is on their left
- -- side. To do things properly, I should get this in a more direct fashion, but
- -- I can't be bothered
- xsize = memory.readbyte(0x7e807a+1+j)
- if xsize == 0 then xsize = 0x20 end
- y = memory.readbyte(0x7e80ce+1+j)
- -- other interesting information
- id = memory.readword(0x7e3388+j)
- xp = memory.readword(0x7e3d8c+j)
- gold = memory.readword(0x7e3da0+j)
- hp = memory.readword(0x7e3bf4+k)
- mp = memory.readword(0x7e3c08+k)
- mhp = memory.readword(0x7e3c1c+k)
- mmp = memory.readword(0x7e3c30+k)
- level= memory.readbyte(0x7e3b18+k)
- speed= memory.readbyte(0x7e3b19+k)
- gauge= memory.readword(0x7e3218+k)
- -- elements
- absorb = memory.readbyte(0x7e3bcc+k)
- nullify = memory.readbyte(0x7e3bcd+k)
- resist = memory.readbyte(0x7e3be1+k)
- weak = memory.readbyte(0x7e3be0+k)
- stealn = memory.readbyte(0x7e3311+j)
- stealr = memory.readbyte(0x7e3310+j)
- dropn = memory.readbyte(0xcf3000+4*id+3)
- dropr = memory.readbyte(0xcf3000+4*id+2)
- name = getmonstername(id)
- -- Print the gauges
- startgauge(x,y,xsize)
- drawgauge(mp, mmp, "#0000ff")
- drawgauge(hp, mhp, "#00ff00")
- drawgauge(gauge, 0x10000, "#ff0000")
- by = gy
- gui.text(x-16, by-8, string.format("%2d",level))
- print_element(x, by-6, absorb)
- print_element(x+4, by-6, nullify)
- print_element(x+8, by-6, resist)
- print_element(x+12, by-6, weak)
- gui.text(x+18, by-8, ""..hp)
- active_slot = memory.readbyte(0x7e0201)
- active_player = memory.readbyte(0x7e3ed8+active_slot*2)
- menu_pos = memory.readbyte(0x7e890f+active_slot)
- relm_info = active_player == 8 and menu_pos == 1
- locke_info = active_player == 1 and menu_pos == 1
- gau_info = active_player == 0xb
- if gau_info then
- local id_byte, id_bit = math.floor(id/8), id % 8
- if bit(memory.readbyte(0x7e1d2c+id_byte),id_bit) == 0 then
- -- monster not known!
- gui.text(x-8,y,"?")
- end
- end
- -- More detailed information for the monster we point to.
- -- This will depend on how it is being pointed to
- if (sel_side == 0 or sel_side == 2) and sel_i == i and
- sel_multi == 0 and sel_enemy ~= 0 then
- --gui.text(10,offset,"Level "..level.." "..name)
- --offset = offset+10
- gui.text(10,offset,string.format("HP:%d/%d, MP:%d/%d",hp,mhp,mp,mmp))
- offset = offset+10
- --gui.text(10,offset,string.format("XP:%d, gold:%d",xp,gold))
- --offset = offset+10
- if locke_info then
- gui.text(10,offset,string.format("Steal %s/%s", getitemname(stealn), getitemname(stealr)))
- offset = offset+10
- end
- gui.text(10,offset,string.format("Drops %s/%s", getitemname(dropn), getitemname(dropr)))
- offset = offset+10
- -- Special attack description
- specialn = get_special(id)
- -- Sketch
- sketch1 = memory.readbyte(0xcf4300+2*id)
- sketch2 = memory.readbyte(0xcf4300+2*id+1)
- -- control
- control, controln = {}, {}
- for ctrl_i = 0, 3 do
- control[ctrl_i] = memory.readbyte(0xcf3d00+4*id+ctrl_i)
- end
- if sketch1 == 0xEF then sketch1n = specialn else sketch1n = getattackname(sketch1) end
- if sketch2 == 0xEF then sketch2n = specialn else sketch2n = getattackname(sketch2) end
- for ctrl_i = 0, 3 do
- local ctrl,foo = control[ctrl_i]
- if ctrl == 0xEF then foo = specialn
- elseif ctrl == 0xFF then foo = "Nothing"
- else foo = getattackname(ctrl) end
- controln[ctrl_i] = foo
- end
- if relm_info then
- gui.text(10,offset,string.format("Sketch %s/%s", sketch2n, sketch1n))
- offset = offset+10
- gui.text(10,offset,string.format("Control %s/%s",controln[0],controln[1]))
- offset = offset+10
- gui.text(10,offset,string.format(" %s/%s",controln[2],controln[3]))
- offset = offset+10
- end
- end
- end end
- -- Rage information when in the rage menu
- if memory.readbyte(0x7e7bd4) == 0x24 then
- x = memory.readbyte(0x7e892f)
- y = memory.readbyte(0x7e8933)
- scroll = memory.readbyte(0x7e892b)
- i = 2*(y+scroll)+x
- id = memory.readbyte(0x7e257e + i)
- if id ~= 0xFF then
- -- What rages does this monster have?
- rage1 = memory.readbyte(0xcf4600+2*id)
- rage2 = memory.readbyte(0xcf4600+2*id+1)
- -- Special attack description
- specialn = get_special(id)
- if rage1 == 0xEF then rage1n = specialn else rage1n = getattackname(rage1) end
- if rage2 == 0xEF then rage2n = specialn else rage2n = getattackname(rage2) end
- gui.text(10,offset,string.format("%s/%s", rage1n, rage2n))
- offset = offset+10
- end
- end
- elseif mode_cave() then
- snes9x.speedmode("normal")
- -- get the screen position
- sx = memory.readword(0x7e8297)
- sy = memory.readword(0x7e8299)
- if sx >= 0x8000 then sx = sx-0x10000 end
- if sy >= 0x8000 then sy = sy-0x10000 end
- -- prepare to loop through treasures
- area = memory.readword(0x7e0082)
- table = 0xed8634
- i = memory.readword(0xed82f4+2*area)
- to = memory.readword(0xed82f4+2*(area+1))
- -- loop through the treasures
- while i ~= to do
- -- read from the treasure information array
- xi = memory.readbyte(table+i)
- yi = memory.readbyte(table+i+1)
- flagi = memory.readword(table+i+2)
- item = memory.readbyte(table+i+4)
- name = getitemname(item)
- -- Has the box been taken? To find out, we need to
- -- do some bit manipulation.
- byte_index = math.floor(flagi/8)
- bit_index = flagi % 8
- if byte_index >= 0x40 then
- byte_index = byte_index - 0x40*math.floor(byte_index/0x40)
- end
- flag = memory.readbyte(0x7e1e40+byte_index)
- flag = flag % (2^(bit_index+1))
- flag = math.floor(flag/ 2^bit_index)
- -- flag is now 0 if not taken and 1 if taken
- if flag == 0 then color = "#00ff00" else color = "#ff0000" end
- -- get the real x,y position, using the fact that
- -- each square is 0x10 big.
- x,y = 0x10*xi, 0x10*yi
- -- relative coordinates
- rx, ry = x-sx, y-sy
- -- draw a nice red box around the treasure box
- gui.drawbox(rx, ry, rx+0x10, ry+0x10, color)
- gui.text(rx, ry-5, name)
- i = i + 5
- end
- table = 0xdfbb00
- i = memory.readword(table+2*area)
- to = memory.readword(table+2*(area+1))
- -- loop through the transitions
- while i ~= to do
- -- read from the treasure information array
- xi = memory.readbyte(table+i)
- yi = memory.readbyte(table+i+1)
- hmm = memory.readword(table+i+2)
- xti = memory.readbyte(table+i+4)
- yti = memory.readbyte(table+i+5)
- area2 = hmm % 0x200
- -- is it to the same area? If so, color it
- -- light blue. Else make it normal blue.
- if area2 == area then color = "#8080ff"
- else color = "#0000ff" end
- -- get the real x,y position, using the fact that
- -- each square is 0x10 big.
- x,y = 0x10*xi, 0x10*yi
- -- relative coordinates
- rx, ry = x-sx, y-sy
- gui.drawbox(rx, ry, rx+0x10, ry+0x10, color)
- i = i + 6
- end
- table = 0xedf480
- i = memory.readword(table+2*area)
- to = memory.readword(table+2*(area+1))
- -- loop through the wide transitions
- while i ~= to do
- -- read from the treasure information array
- xi = memory.readbyte(table+i)
- yi = memory.readbyte(table+i+1)
- dxi = memory.readbyte(table+i+2)
- dyi = 0
- hmm = memory.readword(table+i+3)
- xti = memory.readbyte(table+i+5)
- yti = memory.readbyte(table+i+6)
- area2 = hmm % 0x200
- if dxi >= 0x80 then dxi, dyi = 0, dxi % 0x80 end
- -- is it to the same area? If so, color it
- -- light blue. Else make it normal blue.
- if area2 == area then color = "#8080ff"
- elseif area2 == 0x1ff then color = "#b0b0ff"
- else color = "#0000ff" end
- -- get the real x,y position, using the fact that
- -- each square is 0x10 big.
- x,y,dx,dy = 0x10*xi, 0x10*yi, 0x10*dxi, 0x10*dyi
- -- relative coordinates
- rx, ry = x-sx, y-sy
- gui.drawbox(rx, ry, rx+dx+0x10, ry+dy+0x10, color)
- i = i + 7
- end
- table= 0xc40000
- i = memory.readword(0xc40000+2*area)
- to = memory.readword(0xc40000+2*(area+1))
- -- loop through the reactions
- while i ~= to do
- -- read from the treasure information array
- xi = memory.readbyte(table+i)
- yi = memory.readbyte(table+i+1)
- react1 = memory.readword(table+i+2)
- react2 = memory.readbyte(table+i+4)
- color = "#ffff00"
- -- get the real x,y position, using the fact that
- -- each square is 0x10 big.
- x,y = 0x10*xi, 0x10*yi
- -- relative coordinates
- rx, ry = x-sx, y-sy
- gui.drawbox(rx, ry, rx+0x10, ry+0x10, color)
- i = i + 5
- end
- else
- snes9x.speedmode("normal")
- end
- -- encounter counter
- if mode_map() or mode_cave() then
- -- Equipment-derived information is not kept permanently, it is recomputed
- -- at the beginning of every frame, I think. We need to know if the party
- -- has the moogle charm or charm bangle effect.
- -- We will therefore loop through the equipment of all characters.
- field_effects = 0
- status_effects = 0
- char_in_party = 0
- for id = 0, 0xF do
- tmp = memory.readbyte(0x7e1850+id)
- if tmp % 8 == memory.readbyte(0x7e1a6d) then
- -- character is present. If necessary, information about
- -- row and slot is also awailable in tmp.
- char_in_party = char_in_party + 1
- x = id*0x25+0x1F -- start of equipment
- for i = 0, 5 do
- item = memory.readbyte(0x7e1600+x+i)
- if item ~= 0xFF then
- -- item actually equipped
- field_effects = bor(field_effects,memory.readbyte(0xd85005+item*0x1e))
- status_effects = bor(status_effects,memory.readbyte(0xd8500a+item*0x1e))
- end
- end
- end
- end
- -- field_effects is what is later put in 11df
- if mode_map() then
- terrain = memory.readbyte(0x7e11f9) % 8
- at_22 = memory.readbyte(0xc0c28f+terrain) -- lave tall, men hva betyr de?
- a = memory.readbyte(0xc0c297+terrain) -- denne arrayen følger rett etter. samme størrelsesorden.
- -- b og c er faktisk x og y-posisjonen på kartet til *forrige encounter*!
- last_x = memory.readbyte(0x7e1f60)
- last_y = memory.readbyte(0x7e1f61)
- zone_x, zone_y = math.floor(last_x/0x20),math.floor(last_y/0x20)
- zone = memory.readbyte(0x7e1f64)*0x40+zone_y*8+zone_x
- -- a må inneholde en mapping fra terreng til offsets i følgende array.
- -- merkelig at slikt trengs.
- pack_index = memory.readbyte(0xcf5400+zone*4+a)
- gui.text(textX, textY + 30, "pack index: " .. pack_index)
- -- den høye byten her angir kanskje om det er world of balance eller ruin eller noe annet?
- encounter_rate_index = math.floor(memory.readbyte(0xcf5800+zone) / 4^at_22) % 4
- -- field_effects har info om charm bangle etc. encounter_rate_index info om more/less enc.
- x = (field_effects)%4*8 + encounter_rate_index*2
- -- x er nå indeks inn i encounter rate-tabellen.
- encounter_rate = memory.readword(0xc0c29f+x)
- else
- area = memory.readword(0x7e0082)
- ax,ay = math.floor(area/4), area % 4
- a = (memory.readbyte(0xcf5880+ax) / 4^ay) % 4
- x = ((memory.readbyte(0x7e11df) % 4) * 4 + a) * 2
- encounter_rate = memory.readword(0xc0c2bf+x)
- if bit(memory.readbyte(0x7e0525),7) == 0 then
- encounter_rate = 0
- end
- pack_index = memory.readbyte(0xcf5600+area)
- gui.text(textX, textY + 30, "pack index: " .. pack_index)
- end
- enc1 = memory.readword(0x7e1f6e)
- enc2 = memory.readbyte(0x7e1fa1)
- enc3 = memory.readbyte(0x7e1fa4)
- count = 1
- if encounter_rate ~= 0 then
- for i = 0, 100 do
- enc1 = enc1 + encounter_rate
- if enc1 >= 0x10000 then enc1 = 0xff00 end
- enc2 = (enc2+1) % 0x100
- if enc2 == 0 then enc3 = (enc3 + 0x11) % 0x100 end
- if (memory.readbyte(0xc0fd00+enc2)+enc3) % 0x100 < math.floor(enc1/0x100) then break end
- count = count+1
- end
- gui.text(10,offset,"Encounter in ".. count.." steps.")
- offset = offset+10
- -- Veldt?
- if pack_index == 0xFF then
- enc_veldt = (memory.readbyte(0x7e1fa5)+1) % 0x40
- -- find a nonzero byte in the encountered formations bitarray.
- while memory.readbyte(0x7e1ddd+enc_veldt) == 0 do
- enc_veldt = (enc_veldt+1) % 0x40
- end
- enc5 = memory.readbyte(0x7e1fa3)
- enc4 = (memory.readbyte(0x7e1fa2)+1) % 0x100
- if enc4 == 0 then enc5 = enc5 + 0x17 end
- bit_index = (memory.readbyte(0x7ec0fd00+enc4)+enc5) % 0x8
- bitset = memory.readbyte(0x7e1ddd+enc_veldt)
- -- find a nonzero bit, starting at a random position
- while bit(bitset,bit_index) == 0 do
- bit_index = (bit_index+1) % 8
- end
- formation = enc_veldt*8+bit_index
- else
- x = pack_index*8
- -- Encounter type. x is the index into the monster pack array
- enc1 = (memory.readbyte(0x7e1fa2)+1) % 0x100
- enc2 = memory.readbyte(0x7e1fa3)
- if enc1 == 0 then enc2 = enc2+0x17 end
- a = (memory.readbyte(0xc0fd00+enc1)+enc2) % 0x100
- if a > 0x50 then x = x+2 end
- if a > 0xa0 then x = x+2 end
- if a > 0xf0 then x = x+2 end
- formation = memory.readword(0xcf4800+x)
- end
- -- At this point, we have all the frame-independent information about the
- -- encounter we can get. The following is an attempt to handle the frame-
- -- dependent information by predicting at what frame an encounter will occur.
- -- This is formation variation (on the floating continent only), attack type
- -- (front, back, pincer, side) and preemptiv or not. However, this ended in
- -- failure. It works for 3-4 chars in party on the map, mostly, but not for
- -- fewer chars, and not when not on the world map. If you want to enable it,
- -- comment the following line
- skip_frame_dependent = true
- if not skip_frame_dependent then
- -- To find out more about the encounter, we need the frame-
- -- dependent be variable. We must first predict the number
- -- of pixels we are away from an encounter.
- if mode_map() then
- faceing = memory.readbyte(0x7e00f6)
- xpos = memory.readword(0x7e00c6)
- ypos = memory.readword(0x7e00c8)
- else
- -- have to loop through all chars to find out who is the leader?
- -- However, the position we get this way does not move smoothly. Bleh.
- for id = 0, 0xF do
- local delta = 0x29*id
- xpos, ypos = 0,0
- if bit(memory.readbyte(0x7e0867+delta),7) == 1 then
- faceing = memory.readbyte(0x7e086f+delta)
- xpos = memory.readword(0x7e086a+delta)
- ypos = memory.readword(0x7e086d+delta)
- break
- end
- end
- end
- if faceing == 0 then pixels = ypos % 0x10
- elseif faceing == 1 then
- pixels = xpos % 0x10
- if pixels ~= 0 then pixels = 0x10-pixels end
- elseif faceing == 2 then
- pixels = ypos % 0x10
- if pixels ~= 0 then pixels = 0x10-pixels end
- else pixels = xpos % 0x10
- end
- -- this is the pixels left in our current step. then add the number
- -- of whole steps
- standing_still = false
- if pixels == 0 then
- -- this is a whole position. was the last position whole too?
- if last_position_whole then
- standing_still = true
- pixels = 0x10*count
- else pixels = 0x10*(count-1) end
- last_position_whole = true
- else
- pixels = pixels + 0x10*(count-1)
- last_position_whole = false
- end
- -- sprint shoes?
- if mode_cave() and bit(status_effects,5) then
- pixels = math.floor(pixels/2)
- end
- -- compensate for the time it takes to start moving
- if standing_still then
- if mode_map() then pixels = pixels+2
- else
- if bit(status_effects,5) == 1 then
- pixels = pixels + memory.readbyte(0x7e0021e) % 4
- else pixels = pixels + memory.readbyte(0x7e0021e) % 4 end
- end
- end
- -- we assume that we are walking with maximum speed of 1 pixel per frame
- -- this will lead to be getting this value at the beginning of battle
- be = 4*((memory.readbyte(0x7e021e)+pixels+0x22) % 0x3c)
- gui.text(10,90,string.format("be: %x vs %x, %x %x", memory.readbyte(0x7e00be), be,pixels,xpos))
- if math.floor(formation / 0x8000) == 1 then
- -- High bit of formation set: randomly add 0..3 to formation
- be = (be+1) % 0x100
- a = memory.readbyte(0xc0fd00+be) % 4
- formation = (formation+a) % 0x8000
- end
- end
- info1 = memory.readbyte(0xcf5900+4*formation)
- info2 = memory.readbyte(0xcf5900+4*formation+1)
- info3 = memory.readbyte(0xcf5900+4*formation+2)
- info4 = memory.readbyte(0xcf5900+4*formation+3)
- -- Build monster list
- start = 0xcf6201+15*formation
- present = memory.readbyte(start)
- which = {}
- number_of_enemies = 0
- for i = 1, 6 do
- if present % 2 == 1 then
- id = memory.readbyte(start+i)
- if which[id] then which[id] = which[id]+1
- else which[id] = 1 end
- number_of_enemies = number_of_enemies + 1
- end
- present = math.floor(present/2)
- end
- -- Display list
- for id, num in pairs(which) do
- gui.text(10, offset, ""..num.." "..getmonstername(id))
- offset = offset + 10
- end
- if not skip_frame_dependent then
- -- What kind of encounter?
- variant = math.floor(info1 / 0x10) % 0x10
- -- variant is four bits long, and those bits are front, back, pincer, side; inverted.
- -- from high to low.
- -- let us extract these
- allowed = {}
- allowed_number = 0
- for i = 0, 3 do
- allowed[i] = 1 - variant % 2
- allowed_number = allowed_number + allowed[i]
- variant = math.floor(variant/2)
- end
- if bit(status_effects,1) == 1 then
- -- back guard, disable back and pincer.
- -- This will prefer to remove pincer if not
- -- both can be removed.
- for i = 1, 2 do if allowed_number > 1 then
- allowed[i] = 0
- allowed_number = allowed_number-1
- end end
- end
- if char_in_party < 3 and allowed_number > 1 then
- -- not enough characters to do side attack
- allowed[3] = 0
- allowed_number = allowed_number - 1
- end
- -- Now we pick one of the possibilities
- -- First find the sum of the weights
- local sum = 0
- for i = 0, 3 do if allowed[i] == 1 then
- sum = sum + memory.readbyte(0xc25279+i)+1
- end end
- -- before this point, be has been incremented by other things
- be = be + 0xa + 2*number_of_enemies + char_in_party
- -- get a random number from 0 to sum-1, using be
- be = (be+1) % 0x100
- rnd = math.floor(memory.readbyte(0xc0fd00+be)*sum/0x100)
- -- now loop through again, and pick the first that is bigger
- -- than the number
- sum = 0
- for i = 0, 3 do if allowed[3-i] == 1 then
- sum = sum + memory.readbyte(0xc25279+i)+1
- if sum > rnd then
- chosen = 3-i
- break
- end
- end end
- vardesc = { "Front", "Back", "Pincer", "Side" }
- -- Finally, describe the result
- if chosen ~= 0 then
- gui.text(10, offset, string.format("%s attack",vardesc[chosen+1]))
- offset = offset+10
- end
- end
- end
- end
- HandleKeys()
- if autoText then
- gui.text(textX,textY + 20,"(T) Auto Text : On")
- else
- gui.text(textX,textY + 20,"(T) Auto Text : Off")
- end
- if autoText and (snes9x.framecount() % 6 == 0 or ((snes9x.framecount() - 1) % 6 == 0)) then
- curPad = joypad.get()
- curPad.A = true
- joypad.set(curPad)
- end
- if (memory.readbyte(0x7e1dd2) % 2 == 0) and (memory.readword(0x7e1501) == 0xa509) and (memory.readbyte(0x7e1503) == 0xEE) then
- x1 = memory.readword(0x7e0b00)
- y1 = memory.readword(0x7e0b02)
- x2 = memory.readword(0x7e0b04)
- y2 = memory.readword(0x7e0b06)
- gui.line(x1 + 176, 156, x1 + 176, 219, "#008080")
- gui.line(176, y1 + 156, 239, y1 + 156, "#008080")
- gui.line(x2 + 176, 156, x2 + 176, 219, "#008080")
- gui.line(176, y2 + 156, 239, y2 + 156, "#008080")
- gui.pixel(x1 + 176, y1 + 156, "#00ffff")
- gui.pixel(x2 + 176, y2 + 156, "#00ffff")
- end
- --for moviemaking
- --cMode1, cMode2 = memory.readword(0x7e1501), memory.readbyte(0x7e1503)
- --if lMode1 ~= cMode1 and lMode2 ~= cMode2 then
- -- snes9x.pause()
- --end
- --lMode1 = cMode1
- --lMode2 = cMode2
- CalculateTime()
- OutputTime()
- snes9x.frameadvance()
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement