Modified to include AABB autofire, battle analysis, and a "minimal mode"
-- Lua Script made by MKDasher
-- Based on gen 3 lua scripts by FractalFusion
-- Japanese D/P support added by Fortranm
--TODO:
-- Roaming pkm (birds)
-- Next pkrs frame
-- Object rate for pokemon
-------------------------
--Keys:
-- 1: Activate AABB autofire
-- Risk of dropping inputs if emulation speed is too high (0.5x speed is usually safe)
-- (AABB isn't optimal on level-up stat dialogs for some reason, so don't use it there)
-- 3: Go to previous mode
-- 4: Go to next mode
-- 6: In RNG analysis (battle mode), subtract 2 from the RNG seed being analyzed
-- 7: In RNG analysis (battle mode), add 2 to the RNG seed being analyzed
-- 8: In RNG analysis (battle mode), subtract 1 from the highest byte of the RNG seed being analyzed
-- 9: In RNG analysis (battle mode), add 1 to the highest byte of the RNG seed being analyzed
-----
-- Analysis
-- First of all, the base RNG will now update whenever it is reseeded entering battle, so that the RNG distance resets to 0 on the first seed. Only exception is if it is too close to the overworld seed (but when does that happen anyway)
-- The following is used to do battle analysis.
-- rngdelay indicates the smallest RNG distance to check for crits/misses/etc.
-- mode=1 for critical hit, 2 for miss
-- probabilities works like this:
---- If mode is 1, probabilities should be a number from 0 to 15. 100 minus this number is the minimum allowable percentage of the max range for the crit. 0 means max crit (1/256 chance). 15 means any crit.
---- If mode is 2, probabilities is the accuracy of the move that you want to make miss (95, 90, etc.).
-- maxdelay is the maximum number of delay frames allowed in the result. ">max" will display if the total delay exceeds this.
-- Analysis will automatically be performed any time the base RNG is reseeded, or 6/7/8/9 is pressed.
-- The analyzed RNG will be displayed, followed by the delays for each rngdelay point, and then the total delay, and then the targeted RNG indices (distances).
-- Keys 6 and 7 add/subtract 2 to/from the analyzed RNG seed, so you don't have to keep loading savestates. Each addition of 2 corresponds to delaying 1 input frame (2 frames). However, if the seconds value changes, then you also need keys 8 and 9 to adjust the highest byte of the RNG. But you don't need to use 8 or 9 if you are only looking for crits/range, because the highest byte has no effect on crits/range, only on misses and any mechanic that is calculated mod 100.
-- You need to find and enter these values yourself.
local rngdelay = {565,862,935,1095}
local mode = {1, 2, 2, 1} -- 1 = critical hit, 2 = miss
local probabilities = {15, 95, 95, 10}
local maxdelay=50
-------------------------
local testingseed_forRNG = 0x160e0f55 --put overworld rng seed here
-------------------------
local land_mode = 1 -- menu mode (Auto = default)
local land_modehitbox = {0, 70, 106, 143}
local curland_mode = 0 -- real mode
local land = 0 -- selected mode
local landstr = {"Grass", "Water"}
local movement_mode = 1
local curmovement_mode = 1
local movement_rate
local movement_str = {"Walk", "Swim", "Bike"}
local movement_modehitbox = {0,64,94,124,155}
local encrate_mode = 1
local encrate_modehitbox = {0, 53, 71, 89, 107, 125, 143}
local hitboxstart = 73
local hitboxheight = -35
local menuvisible = 0
local bottommenu_mode = 1
local bottommenu_str = {" Battle ", "Next encs ", " Slots "," Misc "}
local encrate = 0
local curencrate = 0
local stepcounter = 0
local maxstepcounter = 0
local rshift, lshift=bit.rshift, bit.lshift
local lastRNG = 0
local i
local tabl={}
local prev={}
local hour = 0
local game = 1
local gamename = ""
local pointerAddr = {0x02106FAC, 0x02101D2C, 0x02108804}
local stepcounterAddrOffset = {0x2FA40, 0x2E834, 0x2FA40}
local stepcnt128AddrOffset = {0xE044, 0xDE34, 0xE044}
local RNGAddr = {0x021C4D48, 0x021BFB14, 0x021C65A8}
local curlandmodeAddrOffset = {0x31AE2, 0x3090A, 0x31AE2}
local curmovementmodeAddrOffset = {0x31950, 0x30778, 0x31950}
local grassEncAddrOffset = {0x315C0, 0x303C4, 0x315C0}
local waterEncAddrOffset = {0x3168C, 0x30490, 0x3168C}
local framecountAddr = {0x021C48E4, 0x021BF6A8, 0x021C6144}
local IGTAddrOffset = {0xD29A, 0xD07E, 0xD29A}
local clockAddr = {0x021C4828, 0x021BF5E8, 0x021C6088}
local TIDAddrOffset = {0xD288, 0xD06C, 0xD288}
local LIDAddrOffset = {0xE028, 0xDE18, 0xE028}
local encslots_pkm = {}
local encslots_lvl = {}
local waterslots_pkm = {}
local waterslots_minlvl = {}
local waterslots_maxlvl = {}
function drawsquare(a,b,c)
gui.box(a,b,a+4,b+4,c)
end
function drawarrowdown(a,b,c)
gui.line(a,b,a-2,b-2,c)
gui.line(a,b,a+2,b-2,c)
gui.line(a,b,a,b-6,c)
end
function drawarrowleft(a,b,c)
gui.line(a,b+3,a+2,b+5,c)
gui.line(a,b+3,a+2,b+1,c)
gui.line(a,b+3,a+6,b+3,c)
end
function drawarrowright(a,b,c)
gui.line(a,b+3,a-2,b+5,c)
gui.line(a,b+3,a-2,b+1,c)
gui.line(a,b+3,a-6,b+3,c)
end
function mult32(a,b)
local c=rshift(a,16)
local d=a%0x10000
local e=rshift(b,16)
local f=b%0x10000
local g=(c*f+d*e)%0x10000
local h=d*f
local i=g*0x10000+h
return i
end
function gettop(a)
return(rshift(a,16))
end
function getbits(a,b,d)
return rshift(a,b)%lshift(1,d)
end
local multspa={
0x41C64E6D, 0xC2A29A69, 0xEE067F11, 0xCFDDDF21, 0x5F748241, 0x8B2E1481, 0x76006901, 0x1711D201,
0xBE67A401, 0xDDDF4801, 0x3FFE9001, 0x90FD2001, 0x65FA4001, 0xDBF48001, 0xF7E90001, 0xEFD20001,
0xDFA40001, 0xBF480001, 0x7E900001, 0xFD200001, 0xFA400001, 0xF4800001, 0xE9000001, 0xD2000001,
0xA4000001, 0x48000001, 0x90000001, 0x20000001, 0x40000001, 0x80000001, 0x00000001, 0x00000001}
local multspb={
0x00006073, 0xE97E7B6A, 0x31B0DDE4, 0x67DBB608, 0xCBA72510, 0x1D29AE20, 0xBA84EC40, 0x79F01880,
0x08793100, 0x6B566200, 0x803CC400, 0xA6B98800, 0xE6731000, 0x30E62000, 0xF1CC4000, 0x23988000,
0x47310000, 0x8E620000, 0x1CC40000, 0x39880000, 0x73100000, 0xE6200000, 0xCC400000, 0x98800000,
0x31000000, 0x62000000, 0xC4000000, 0x88000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000}
function rngAdvance(a)
return mult32(a,0x41C64E6D) + 0x6073
end
local baseRNGseed=testingseed_forRNG
function getSeedDistance(a)
test=baseRNGseed
distseed=0
for j=0,31,1 do
if getbits(a,j,1)~=getbits(test,j,1) then
test=mult32(test,multspa[j+1])+multspb[j+1]
distseed=distseed+bit.lshift(1,j)
--if j==31 then
-- distseed=distseed+0x100000000
--end
end
end
return distseed
end
function fillEncSlots()
-- fill grass slots
slotAddr = pointer + grassEncAddrOffset[game] + 4
for i=1,12,1 do
encslots_lvl[i] = memory.readdword(slotAddr)
slotAddr = slotAddr + 4
encslots_pkm[i] = memory.readdword(slotAddr)
slotAddr = slotAddr + 4
end
-- overwrite slot 2 and 3 (3 and 4 in the array) with day / night encounters
slotAddr = pointer + grassEncAddrOffset[game] + 0x6c
if hour >= 10 and hour < 20 then --day
encslots_pkm[3] = memory.readdword(slotAddr)
encslots_pkm[4] = memory.readdword(slotAddr + 4)
elseif hour >= 20 or hour < 4 then --night
encslots_pkm[3] = memory.readdword(slotAddr + 8)
encslots_pkm[4] = memory.readdword(slotAddr + 12)
end
-- fill water slots
slotAddr = pointer + waterEncAddrOffset[game] + 4
for i=1,5,1 do
waterslots_maxlvl[i] = memory.readbyte(slotAddr)
slotAddr = slotAddr + 1
waterslots_minlvl[i] = memory.readbyte(slotAddr)
slotAddr = slotAddr + 3
waterslots_pkm[i] = memory.readdword(slotAddr)
slotAddr = slotAddr + 4
end
end
function ModeHandler()
curland_mode = memory.readbyte(pointer + curlandmodeAddrOffset[game])
if (curland_mode == 16 or curland_mode == 21) then --16 and 21 are water values
curland_mode = 2
else
curland_mode = 1
end
if land_mode == 2 then -- Grass
land = 1
elseif land_mode == 3 then --(Water)
land = 2
else --(Auto)
land = curland_mode
end
if land == 1 then -- Grass
curencrate = memory.readbyte(pointer + grassEncAddrOffset[game])
else -- land == 2 --(Water)
curencrate = memory.readbyte(pointer + waterEncAddrOffset[game])
end
maxstepcounter = 8 - lshift(curencrate,8) / 2560
encrate = curencrate
if encrate_mode > 1 then
encrate = 5 * encrate_mode
end
-- 1 = walk, 6 = swim, 3 = bike
curmovement_mode = memory.readdword(pointer + curmovementmodeAddrOffset[game])
-- Since I store mode on array [walk, swim, bike], I convert mode 6 (swim) to 2
if curmovement_mode == 6 then
curmovement_mode = 2
elseif curmovement_mode ~= 3 then
curmovement_mode = 1 -- just to avoid lua crashing
end
movement_rate = 40
if (movement_mode == 1 and curmovement_mode == 3) or movement_mode == 4 then --bike
movement_rate = 70 -- bike enc rate
end
--print modes
if menuvisible == 0 then
gui.box(0,hitboxheight-5,12,0,"#00FF00B0")
gui.text(3,hitboxheight-3, "S\nH\nO\nW\n", "#88FF88B0")
else
gui.box(0,hitboxheight,256,0,"#000000B0")
gui.box(0,hitboxheight-5,12,0,"#FF0000B0")
gui.text(3,hitboxheight-3, "H\nI\nD\nE\n", "#FF8888B0")
gui.box(land_modehitbox[1]+hitboxstart,hitboxheight,land_modehitbox[4]+hitboxstart,hitboxheight+10,"#FF0000B0", "#00000000")
gui.box(movement_modehitbox[1]+hitboxstart,hitboxheight+10,movement_modehitbox[5]+hitboxstart,hitboxheight+20,"#FF0000B0", "#00000000")
gui.box(encrate_modehitbox[1]+hitboxstart,hitboxheight+20,encrate_modehitbox[7]+hitboxstart,hitboxheight+30,"#FF0000B0", "#00000000")
gui.box(land_modehitbox[land_mode]+hitboxstart,hitboxheight,land_modehitbox[land_mode+1]+hitboxstart,hitboxheight+10,"#0000FFFF", "#00000000")
gui.box(movement_modehitbox[movement_mode]+hitboxstart,hitboxheight+10,movement_modehitbox[movement_mode+1]+hitboxstart,hitboxheight+20,"#0000FFFF", "#00000000")
gui.box(encrate_modehitbox[encrate_mode]+hitboxstart,hitboxheight+20,encrate_modehitbox[encrate_mode+1]+hitboxstart,hitboxheight+30,"#0000FFFF", "#00000000")
gui.text(15, hitboxheight+2, "LandType: Auto(" .. landstr[curland_mode] .. ") Grass Water","#FFFFFFB0")
gui.text(15, hitboxheight+12, "Movement: Auto(" .. movement_str[curmovement_mode] .. ") Walk Swim Bike","#FFFFFFB0")
if curencrate == 0 then
gui.text(15, hitboxheight+22, "Enc.rate: Auto( 0) 10 15 20 25 30","#FFFFFFB0")
else
gui.text(15, hitboxheight+22, "Enc.rate: Auto(" .. curencrate .. ") 10 15 20 25 30","#FFFFFFB0")
end
end
end
local delaycount=0
local results = {}
local baseseedstring = "?"
local rngstring = "?"
local rngstring2 = "?"
function analyze(startRNG,RNGshift)
baseseedstring = bit.tohex(startRNG) .. " (" .. RNGshift .. ")"
rng=startRNG
delaycount=0
for i=1,#rngdelay,1 do
local delays=rngdelay[1]
if i>1 then
delays=rngdelay[i]-rngdelay[i-1]
end
for j=1,delays,1 do
rng=rngAdvance(rng)
end
--check for crit/miss
if mode[i]==1 then --crit
while delaycount<=maxdelay do
if gettop(rng)%16==0 then
rng2=rng
rng2=rngAdvance(rng2)
rng2=rngAdvance(rng2)
if gettop(rng2)%16<=probabilities[i] then
results[i]=delaycount
break
end
end
rng=rngAdvance(rng)
delaycount=delaycount+1
--dbgcnt=dbgcnt+1
end
elseif mode[i]==2 then --miss
while delaycount<=maxdelay do
if gettop(rng)%100>=probabilities[i] then
results[i]=delaycount
break
end
rng=rngAdvance(rng)
delaycount=delaycount+1
end
end
if delaycount>maxdelay then --exceeded limit
break
end
end
if delaycount>maxdelay then --exceeded limit
rngstring=">max"
rngstring2=""
else --form rngstring of results
rngstring=""
rngstring2=""
for i=1,#rngdelay,1 do
if i==1 then
rngstring=rngstring..results[1].." "
else
rngstring=rngstring..results[i]-results[i-1].." "
end
rngstring2=rngstring2..rngdelay[i]+results[i].." "
end
rngstring=rngstring.."tl:"..delaycount
end
end
analyze(baseRNGseed,0)
local autofire=false
local shifted_baseRNG=baseRNGseed
local shifted_baseRNG_count=0
function UpdateTab()
tabl = input.get()
if tabl["1"] and not prev["1"] then
if autofire then
autofire=false
else
autofire=true
end
end
--local rngdelay = {100,200,300}
--local mode = {1, 1, 1} -- 1 = critical hit, 2 = miss
--local probabilities = {0, 0, 0}
--local maxdelay=100
--local delaycount
--local results
--if tabl["2"] and not prev["2"] then
--testingseed_forRNG=memory.readdword(RNGAddr[game])
--analysis mode
--analyze(baseRNGseed)
--end
if tabl["6"] and not prev["6"] then
shifted_baseRNG=shifted_baseRNG-2
shifted_baseRNG_count=shifted_baseRNG_count-1
analyze(shifted_baseRNG,shifted_baseRNG_count)
end
if tabl["7"] and not prev["7"] then
shifted_baseRNG=shifted_baseRNG+2
shifted_baseRNG_count=shifted_baseRNG_count+1
analyze(shifted_baseRNG,shifted_baseRNG_count)
end
if tabl["8"] and not prev["8"] then
shifted_baseRNG=shifted_baseRNG-0x1000000
analyze(shifted_baseRNG,shifted_baseRNG_count)
end
if tabl["9"] and not prev["9"] then
shifted_baseRNG=shifted_baseRNG+0x1000000
analyze(shifted_baseRNG,shifted_baseRNG_count)
end
--if tabl["6"] and not prev["6"] then
-- cur=memory.readdword(RNGAddr[game])
-- cur=mult32(cur,0XEEB9EB65) + 0XA3561A1
-- memory.writedword(RNGAddr[game], bit.band(cur))
--end
--if tabl["7"] and not prev["7"] then
-- cur=memory.readdword(RNGAddr[game])
-- cur=mult32(cur,0x41C64E6D) + 0x6073
-- memory.writedword(RNGAddr[game], bit.band(cur))
--end
if tabl["3"] and not prev["3"] then
if bottommenu_mode == 0 then
bottommenu_mode = 4
else
bottommenu_mode = bottommenu_mode - 1
end
end
if tabl["4"] and not prev["4"] then
if bottommenu_mode == 4 then
bottommenu_mode = 0
else
bottommenu_mode = bottommenu_mode + 1
end
end
-- if tabl["5"] and not prev["5"] then
-- memory.writedword(RNGAddr[game], bit.band(testingseed_forRNG))
-- end
if tabl['leftclick'] and not prev['leftclick'] then
x = tabl['xmouse']
y = tabl['ymouse']
if menuvisible == 1 then
if y >= hitboxheight and y < hitboxheight+10 then
for i = 1, 3, 1 do
if x >= land_modehitbox[i]+hitboxstart and x < land_modehitbox[i+1]+hitboxstart then
land_mode = i
break
end
end
end
if y >= hitboxheight+10 and y < hitboxheight+20 then
for i = 1, 4, 1 do
if x >= movement_modehitbox[i]+hitboxstart and x < movement_modehitbox[i+1]+hitboxstart then
movement_mode = i
break
end
end
end
if y >= hitboxheight+20 and y < hitboxheight+30 then
for i = 1, 6, 1 do
if x >= encrate_modehitbox[i]+hitboxstart and x < encrate_modehitbox[i+1]+hitboxstart then
encrate_mode = i
break
end
end
end
end
if x > 0 and x < 12 and y >= hitboxheight and y < hitboxheight+30 then
if menuvisible == 1 then
menuvisible = 0
else
menuvisible = 1
end
end
if x > 1 and x < 15 and y > 177 and y < 189 then
if bottommenu_mode == 0 then
bottommenu_mode = 4
else
bottommenu_mode = bottommenu_mode - 1
end
end
if x > 79 and x < 93 and y > 177 and y < 189 then
if bottommenu_mode == 4 then
bottommenu_mode = 0
else
bottommenu_mode = bottommenu_mode + 1
end
end
end
prev=tabl
end
local pokemonname = {"none", "Bulbasaur", "Ivysaur", "Venusaur", "Charmander", "Charmeleon", "Charizard",
"Squirtle", "Wartortle", "Blastoise", "Caterpie", "Metapod", "Butterfree",
"Weedle", "Kakuna", "Beedrill", "Pidgey", "Pidgeotto", "Pidgeot", "Rattata", "Raticate",
"Spearow", "Fearow", "Ekans", "Arbok", "Pikachu", "Raichu", "Sandshrew", "Sandslash",
"NidoranF", "Nidorina", "Nidoqueen", "NidoranM", "Nidorino", "Nidoking",
"Clefairy", "Clefable", "Vulpix", "Ninetales", "Jigglypuff", "Wigglytuff",
"Zubat", "Golbat", "Oddish", "Gloom", "Vileplume", "Paras", "Parasect", "Venonat", "Venomoth",
"Diglett", "Dugtrio", "Meowth", "Persian", "Psyduck", "Golduck", "Mankey", "Primeape",
"Growlithe", "Arcanine", "Poliwag", "Poliwhirl", "Poliwrath", "Abra", "Kadabra", "Alakazam",
"Machop", "Machoke", "Machamp", "Bellsprout", "Weepinbell", "Victreebel", "Tentacool", "Tentacruel",
"Geodude", "Graveler", "Golem", "Ponyta", "Rapidash", "Slowpoke", "Slowbro",
"Magnemite", "Magneton", "Farfetch'd", "Doduo", "Dodrio", "Seel", "Dewgong", "Grimer", "Muk",
"Shellder", "Cloyster", "Gastly", "Haunter", "Gengar", "Onix", "Drowzee", "Hypno",
"Krabby", "Kingler", "Voltorb", "Electrode", "Exeggcute", "Exeggutor", "Cubone", "Marowak",
"Hitmonlee", "Hitmonchan", "Lickitung", "Koffing", "Weezing", "Rhyhorn", "Rhydon", "Chansey",
"Tangela", "Kangaskhan", "Horsea", "Seadra", "Goldeen", "Seaking", "Staryu", "Starmie",
"Mr. Mime", "Scyther", "Jynx", "Electabuzz", "Magmar", "Pinsir", "Tauros", "Magikarp", "Gyarados",
"Lapras", "Ditto", "Eevee", "Vaporeon", "Jolteon", "Flareon", "Porygon", "Omanyte", "Omastar",
"Kabuto", "Kabutops", "Aerodactyl", "Snorlax", "Articuno", "Zapdos", "Moltres",
"Dratini", "Dragonair", "Dragonite", "Mewtwo", "Mew",
"Chikorita", "Bayleef", "Meganium", "Cyndaquil", "Quilava", "Typhlosion",
"Totodile", "Croconaw", "Feraligatr", "Sentret", "Furret", "Hoothoot", "Noctowl",
"Ledyba", "Ledian", "Spinarak", "Ariados", "Crobat", "Chinchou", "Lanturn", "Pichu", "Cleffa",
"Igglybuff", "Togepi", "Togetic", "Natu", "Xatu", "Mareep", "Flaaffy", "Ampharos", "Bellossom",
"Marill", "Azumarill", "Sudowoodo", "Politoed", "Hoppip", "Skiploom", "Jumpluff", "Aipom",
"Sunkern", "Sunflora", "Yanma", "Wooper", "Quagsire", "Espeon", "Umbreon", "Murkrow", "Slowking",
"Misdreavus", "Unown", "Wobbuffet", "Girafarig", "Pineco", "Forretress", "Dunsparce", "Gligar",
"Steelix", "Snubbull", "Granbull", "Qwilfish", "Scizor", "Shuckle", "Heracross", "Sneasel",
"Teddiursa", "Ursaring", "Slugma", "Magcargo", "Swinub", "Piloswine", "Corsola", "Remoraid", "Octillery",
"Delibird", "Mantine", "Skarmory", "Houndour", "Houndoom", "Kingdra", "Phanpy", "Donphan",
"Porygon2", "Stantler", "Smeargle", "Tyrogue", "Hitmontop", "Smoochum", "Elekid", "Magby", "Miltank",
"Blissey", "Raikou", "Entei", "Suicune", "Larvitar", "Pupitar", "Tyranitar", "Lugia", "Ho-Oh", "Celebi",
"Treecko", "Grovyle", "Sceptile", "Torchic", "Combusken", "Blaziken", "Mudkip", "Marshtomp",
"Swampert", "Poochyena", "Mightyena", "Zigzagoon", "Linoone", "Wurmple", "Silcoon", "Beautifly",
"Cascoon", "Dustox", "Lotad", "Lombre", "Ludicolo", "Seedot", "Nuzleaf", "Shiftry",
"Taillow", "Swellow", "Wingull", "Pelipper", "Ralts", "Kirlia", "Gardevoir", "Surskit",
"Masquerain", "Shroomish", "Breloom", "Slakoth", "Vigoroth", "Slaking", "Nincada", "Ninjask",
"Shedinja", "Whismur", "Loudred", "Exploud", "Makuhita", "Hariyama", "Azurill", "Nosepass",
"Skitty", "Delcatty", "Sableye", "Mawile", "Aron", "Lairon", "Aggron", "Meditite", "Medicham",
"Electrike", "Manectric", "Plusle", "Minun", "Volbeat", "Illumise", "Roselia", "Gulpin",
"Swalot", "Carvanha", "Sharpedo", "Wailmer", "Wailord", "Numel", "Camerupt", "Torkoal",
"Spoink", "Grumpig", "Spinda", "Trapinch", "Vibrava", "Flygon", "Cacnea", "Cacturne", "Swablu",
"Altaria", "Zangoose", "Seviper", "Lunatone", "Solrock", "Barboach", "Whiscash", "Corphish",
"Crawdaunt", "Baltoy", "Claydol", "Lileep", "Cradily", "Anorith", "Armaldo", "Feebas",
"Milotic", "Castform", "Kecleon", "Shuppet", "Banette", "Duskull", "Dusclops", "Tropius",
"Chimecho", "Absol", "Wynaut", "Snorunt", "Glalie", "Spheal", "Sealeo", "Walrein", "Clamperl",
"Huntail", "Gorebyss", "Relicanth", "Luvdisc", "Bagon", "Shelgon", "Salamence", "Beldum",
"Metang", "Metagross", "Regirock", "Regice", "Registeel", "Latias", "Latios", "Kyogre",
"Groudon", "Rayquaza", "Jirachi", "Deoxys",
"Turtwig", "Grotle", "Torterra", "Chimchar", "Monferno", "Infernape", "Piplup", "Prinplup",
"Empoleon", "Starly", "Staravia", "Staraptor", "Bidoof", "Bibarel", "Kricketot", "Kricketune",
"Shinx", "Luxio", "Luxray", "Budew", "Roserade", "Cranidos", "Rampardos", "Shieldon", "Bastiodon",
"Burmy", "Wormadam", "Mothim", "Combee", "Vespiquen", "Pachirisu", "Buizel", "Floatzel", "Cherubi",
"Cherrim", "Shellos", "Gastrodon", "Ambipom", "Drifloon", "Drifblim", "Buneary", "Lopunny",
"Mismagius", "Honchkrow", "Glameow", "Purugly", "Chingling", "Stunky", "Skuntank", "Bronzor",
"Bronzong", "Bonsly", "Mime Jr.", "Happiny", "Chatot", "Spiritomb", "Gible", "Gabite", "Garchomp",
"Munchlax", "Riolu", "Lucario", "Hippopotas", "Hippowdon", "Skorupi", "Drapion", "Croagunk",
"Toxicroak", "Carnivine", "Finneon", "Lumineon", "Mantyke", "Snover", "Abomasnow", "Weavile",
"Magnezone", "Lickilicky", "Rhyperior", "Tangrowth", "Electivire", "Magmortar", "Togekiss",
"Yanmega", "Leafeon", "Glaceon", "Gliscor", "Mamoswine", "Porygon-Z", "Gallade", "Probopass",
"Dusknoir", "Froslass", "Rotom", "Uxie", "Mesprit", "Azelf", "Dialga", "Palkia", "Heatran",
"Regigigas", "Giratina", "Cresselia", "Phione", "Manaphy", "Darkrai", "Shaymin", "Arceus",
}
nature = {"Hardy","Lonely(+ATK-DEF)","Brave(+ATK-SPE)","Adamant(+ATK-SAT)","Naughty(+ATK-SDF)",
"Bold(+DEF-ATK)","Docile","Relaxed(+DEF-SPE)","Impish(+DEF-SAT)","Lax(+DEF-SDF)",
"Timid(+SPE-ATK)","Hasty(+SPE-DEF)","Serious","Jolly(+SPE-SAT)","Naive(+SPE-SDF)",
"Modest(+SAT-ATK)","Mild(+SAT-DEF)","Quiet(+SAT-SPE)","Bashful","Rash(+SAT-SDF)",
"Calm(+SDF-ATK)","Gentle(+SDF-DEF)","Sassy(+SDF-SPE)","Careful(+SDF-SAT)","Quirky"}
function MethodJ(initialrng, a)
frame = getSeedDistance(initialrng)
rng2 = initialrng
rng = rngAdvance(initialrng)
slot = math.floor(gettop(rng2) / 656)
pkmstr = ""
lvlnum = 0
if land == 1 then --(Grass)
if (slot < 20) then slot = 0
elseif (slot < 40) then slot = 1
elseif (slot < 50) then slot = 2
elseif (slot < 60) then slot = 3
elseif (slot < 70) then slot = 4
elseif (slot < 80) then slot = 5
elseif (slot < 85) then slot = 6
elseif (slot < 90) then slot = 7
elseif (slot < 94) then slot = 8
elseif (slot < 98) then slot = 9
elseif (slot == 98) then slot = 10
else slot = 11
end
pkmstr = pokemonname[encslots_pkm[slot+1]+1]
lvlnum = encslots_lvl[slot+1]
else -- land == 2 (Water)
if (slot < 60) then slot = 0
elseif (slot < 90) then slot = 1
elseif (slot < 95) then slot = 2
elseif (slot < 99) then slot = 3
else slot = 4
end
pkmstr = pokemonname[waterslots_pkm[slot+1]+1]
lvlnum = gettop(rng) % (waterslots_maxlvl[slot+1] - waterslots_minlvl[slot+1] + 1) + waterslots_minlvl[slot+1]
rng = rngAdvance(rng)
frame = frame + 1
end
mynat = math.floor(gettop(rng) / 0xA3E)
loop = 0
while (true) do
rng2 = rngAdvance(rng)
rng = rngAdvance(rng2)
pid = gettop(rng)*65536 + gettop(rng2)
if (pid % 25 == mynat) then break end
end
rng = rngAdvance(rng)
IV = gettop(rng)
rng = rngAdvance(rng)
IV2 = gettop(rng)
gui.text(120,a, "F:".. frame ..
", " .. pkmstr, "#FFFFFF80")
gui.text(120,a+10, "IV: [".. IV%32 .. "," .. math.floor(IV/32)%32 .. ","
.. math.floor(IV/1024)%32 .. "," .. math.floor(IV2/32)%32 .. ","
.. math.floor(IV2/1024)%32 .. "," .. IV2%32 .. "]", "#FFFFFF80")
gui.text(120,a+20, nature[mynat+1] .. " L." .. lvlnum, "#FFFFFF80")
end
function drawGrid()
test = currentRNG
lastRNG = currentRNG
futureencs = {}
futureencs_n = 0
gui.box(3,3,103,79,"#AAAAAAA0", "white")
if bottommenu_mode == 1 then
for i = 0, 11, 1 do
for j = 0, 15, 1 do
clr = "#000000FF" -- init square color to black
if j % 4 == 0 then
clr = "#404040FF"
end
randvalue = gettop(test)
if randvalue % 16 == 0 then
if randvalue % 100 >= 95 then
clr = "magenta"
else
clr = "red"
end
--elseif randvalue % 16 ==9 then
--clr = "green"
else
if randvalue % 100 >= 95 then
clr = "blue"
end
end
drawsquare(6+6*j,6+6*i, clr)
test=rngAdvance(test)
end
end
drawarrowdown(8,6, "red")
drawarrowdown(26,6, "red")
drawarrowdown(44,6, "blue")
else
for i = 0, 11, 1 do
for j = 0, 15, 1 do
clr = "#000000FF" -- init square color to black
randvalue = gettop(test)
test2 = test
if (stepcounter >= maxstepcounter) or (encrate_mode > 1) or (randvalue / 0x290 < 5) then
if (stepcounter < maxstepcounter and encrate_mode == 1) then
clr = "#666666FF"
test2=rngAdvance(test2)
randvalue=gettop(test2)
end
if (randvalue / 0x290 < movement_rate) then
clr = "#666666FF"
test2=rngAdvance(test2)
randvalue=gettop(test2)
if (randvalue / 0x290 < encrate) then
clr = "#FF0000FF"
if futureencs_n < 10 then
futureencs[futureencs_n] = rngAdvance(test2)
futureencs_n = futureencs_n + 1
end
end
end
end
drawsquare(6+6*j,6+6*i, clr)
test=rngAdvance(test)
end
end
end
end
local buttons1={}
local buttons2={}
buttons1.A=true
buttons1.B=false
buttons2.B=true
buttons2.A=false
function fn()
if autofire then
if emu.framecount()%4==0 or emu.framecount()%4==1 then
joypad.set(buttons1)
else
joypad.set(buttons2)
end
end
gameIDAddr = memory.readdword(0x23FFE0C)
if gameIDAddr == 0x45415041 then
game = 1
gamename = "Pearl (U)"
elseif gameIDAddr == 0x45414441 then
game = 1
gamename = "Diamond (U)"
elseif gameIDAddr == 0x45555043 then
game = 2
gamename = "Platinum (U)"
elseif gameIDAddr == 0x4A415041 then
game = 3
gamename = "Pearl (J)"
elseif gameIDAddr == 0x4A414441 then
game = 3
gamename = "Diamond (J)"
else
game = -1
gamename = "Invalid game"
end
if bottommenu_mode~=0 then
gui.box(0,-192,256,-181,"#00000080")
gui.box(0,0,256,192,"#000000A0")
gui.text(0,-190,"Game: " .. gamename,"#FFFFFFB0")
gui.text(140,-190,"Base seed: " .. bit.tohex(baseRNGseed),"#FFFFFFB0")
if game == -1 then
return
end
pointer = memory.readdword(pointerAddr[game])
stepcounter = memory.readbyte(pointer + stepcounterAddrOffset[game])
stepcnt128 = memory.readbyte(pointer + stepcnt128AddrOffset[game])
UpdateTab()
ModeHandler()
currentRNG = memory.readdword(RNGAddr[game])
nextRNG = rngAdvance(currentRNG)
test = lastRNG
for i = 0, 150, 1 do
if bit.tohex(currentRNG)==bit.tohex(test) then
gui.text(0,113,"Dist last: "..i, "#FFFF00A0")
break
elseif i >= 150 then
gui.text(0,113,"Dist last: >150", "#FFFF00A0")
break
end
test=rngAdvance(test)
end
gui.text(0,83,"Curr RNG: "..bit.tohex(currentRNG), "#FFFF00A0")
gui.text(0,93,"Next RNG: "..bit.tohex(nextRNG), "#FFFF00A0")
gui.text(0,103, "Step Cnt (128): ".. stepcnt128, "#FFFF00A0")
distanceseed = getSeedDistance(currentRNG)
if distanceseed>30000 or distanceseed<-1000 then
baseRNGseed=testingseed_forRNG
distanceseed = getSeedDistance(currentRNG)
if distanceseed>30000 or distanceseed<-1000 then
baseRNGseed=currentRNG
distanceseed=0
end
analyze(baseRNGseed, 0)
shifted_baseRNG=baseRNGseed
shifted_baseRNG_count=0
end
gui.text(0,123,"Dist seed: " .. distanceseed, "#FFFF00A0")
gui.text(0,133, "Enc. Rate Cnt: ".. stepcounter .. "/".. maxstepcounter, "#FFFF00A0")
hour = memory.readdword(clockAddr[game])
gui.text(0,143, "Clock: "
.. hour .. ":"
.. memory.readdword(clockAddr[game]+4) .. ":"
.. memory.readdword(clockAddr[game]+8)
, "#FFFF00A0")
gui.text(0,153, "IGT: "
.. memory.readbyte(pointer + IGTAddrOffset[game]) .. ":"
.. memory.readbyte(pointer + IGTAddrOffset[game]+2) .. ":"
.. memory.readbyte(pointer + IGTAddrOffset[game]+3)
, "#FFFF00A0")
gui.text(0,163, "IG Framecount: " .. memory.readdword(framecountAddr[game]), "#FFFF00A0")
-- Enc Slots
fillEncSlots()
-- Point Grid
drawGrid()
gui.box(2,177,93,189,"#00000080","#FFFFFFFF")
drawarrowleft(5,180,"#FFFFFFFF")
gui.text(20,180, bottommenu_str[bottommenu_mode], "#FFFFFFFF")
drawarrowright(90,180,"#FFFFFFFF")
if bottommenu_mode == 1 then
gui.text(115,5,"RNG Analysis","#FFFFFFB0")
gui.text(115,15,"" .. baseseedstring,"#FFFFFFB0")
gui.text(115,25,"" .. rngstring,"#FFFFFFB0")
gui.text(115,35,"" .. rngstring2,"#FFFFFFB0")
elseif bottommenu_mode == 2 then
--gui.text(50, -170, "Stationary:", "#FFFFFF80")
--local tempRNG=rngAdvance(currentRNG)
--MethodJ(tempRNG,-170)
gui.text(86, -137, "Wild:", "#FFFFFF80")
for i = 0, futureencs_n-1, 1 do
MethodJ(futureencs[i],-170 + 33*(i+1))
end
elseif bottommenu_mode == 3 then
gui.text(115,5, "Encounter slots (" .. landstr[land] .. ")", "#00FF00FF")
if land == 1 then -- (Grass)
for i = 1, 12, 1 do
gui.text(115, (i+1)*10, i-1 .. " - " .. pokemonname[encslots_pkm[i]+1] .. " L." .. encslots_lvl[i])
end
else --land == 2 (Water)
for i = 1, 5, 1 do
gui.text(115, (i+1)*10, i-1 .. " - " .. pokemonname[waterslots_pkm[i]+1] .. " L." .. waterslots_minlvl[i] .. "-" .. waterslots_maxlvl[i])
end
end
elseif bottommenu_mode == 4 then
gui.text(115,5, "Misc. Data", "#00FF00FF")
gui.text(115,20, "Trainer ID: " .. memory.readword(pointer + TIDAddrOffset[game]))
gui.text(115,30, "Secret ID: " .. memory.readword(pointer + TIDAddrOffset[game]+2))
gui.text(115,40, "Lottery ID: " .. memory.readword(pointer + LIDAddrOffset[game]))
end
else --minimal mode
gui.text(0,0,"Minimal mode")
pointer = memory.readdword(pointerAddr[game])
UpdateTab()
currentRNG = memory.readdword(RNGAddr[game])
distanceseed = getSeedDistance(currentRNG)
if distanceseed>30000 or distanceseed<-1000 then
baseRNGseed=testingseed_forRNG
distanceseed = getSeedDistance(currentRNG)
if distanceseed>30000 or distanceseed<-1000 then
baseRNGseed=currentRNG
distanceseed=0
end
analyze(baseRNGseed, 0)
shifted_baseRNG=baseRNGseed
shifted_baseRNG_count=0
end
gui.text(0,10,"Dist seed: " .. distanceseed, "#FFFF00A0")
gui.text(0,160,"Press 3 or 4 to leave mode")
end
end
gui.register(fn)
--while false do
--if autofire then
-- if emu.framecount()%4==0 or emu.framecount()%4==1 then
-- joypad.set(buttons1)
-- else
-- joypad.set(buttons2)
-- end
--end
-- gui.text(120,0,"hello")
-- emu.frameadvance()
--end