Working on a lua script, for displaying some useful info, like where hit boxes are.
Green means the hitbox is okay to hit.
Yellow means you should proceed through that hitbox with caution.
Red means you end up dead by hitting it.
The top number, if displayed, means HPs for that Hit box.
The bottom number, if displayed, is a timer related to what that sprite does.
Most of the bosses have specific handlers, to only show relevant info.
For Cleo, The attack color being used is shown. (not everyone can tell red/green apart.)
For Seahorse Turret, What turret will fire next, is shown by a yellow instead of a read hitbox, along with a counter counting number of frames left before it fires. (If you watch Sivak's latest video showing the challenge runs, in the commentary, he tells exactly how the next one is determined.)
-- Battle Kid: Fortress of Peril
-- Written by CaitSith2
-- 03 April, 2011
-- Displays Hitboxes, Enemy HP, and various stats on screen
local function box(x1,y1,x2,y2,color)
-- gui.text(50,50,x1..","..y1.." "..x2..","..y2);
-- if (x1 > 0 and x1 < 255 and x2 > 0 and x2 < 255 and y1 > 0 and y1 < 241 and y2 > 0 and y2 < 241) then
-- gui.drawbox(x1,y1,x2,y2,color);
gui.drawline(x1,y1,x1,y2,color);
gui.drawline(x1,y1,x2,y1,color);
gui.drawline(x2,y1,x2,y2,color);
gui.drawline(x1,y2,x2,y2,color);
-- end;
end;
local function text(x,y,str)
if (x > 0 and x < 255 and y > 0 and y < 240) then
gui.text(x,y,str);
end;
end;
local function pixel(x,y,color)
if (x > 0 and x < 255 and y > 0 and y < 240) then
gui.drawpixel(x,y,color);
end;
end;
while (true) do
local stuff = 0x0300; -- start of tile data, 4 bytes each, y, ?, ?, x. every tile appears to be 10x10px
local timmy = 0x0031; --V1.1
local timmyshots = 0x0290;
--local timmy = 0x0030; --Demo and V1.0
if(memory.readbyte(0x22) == 1) then
timmy = 0x30;
else
timmy = 0x31;
end;
--spritetype is structured bitwise as follows, ffffbbdd
--ffff = flags. 0001 = box backs off one color on sprites 3-15.
-- 0010 =
--bb = box color. 00 = red, 01 = yellow, 10 = green, 11 = no box.
--dd = display info. 00 = All info, 01 = no info, 10 = HP, 11 = Phase
local spritetype = { 0x00,0x00,0x00,0x00,0x00, 0x00,0x08,0x00,0x02,0x00,
0x09,0x00,0x04,0x00,0x01, 0x00,0x0A,0x00,0x08,0x00,
0x00,0x00,0x00,0x00,0x02, 0x00,0x08,0x00,0x00,0x00,
0x41,0x00,0x05,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x04,0x00,
0x14,0x00,0x08,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x00,0x00, 0x00,0x0D,0x00,0x02,0x00,
0x41,0x00,0x01,0x00,0x00, 0x00,0x20,0x00,0x03,0x00,
0x40,0x00,0x42,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x08,0x00,0x41,0x00,0x00, 0x00,0x41,0x00,0x08,0x00,
0x01,0x00,0x09,0x00,0x00, 0x00,0x41,0x00,0x00,0x00,
0x00,0x00,0x08,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x08,0x00,0x01,0x00,0x01, 0x00,0x05,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00, 0x00,
};
-- print boxes for all the tiles
-- invalid tiles are automatically hidden because their x/y coords are out of range, i guess
x1 = memory.readbyte(timmy);
x2 = memory.readbyte(timmy+1);
y1 = memory.readbyte(timmy+2) + 24;
y2 = memory.readbyte(timmy+3) + 24;
hp = memory.readbyte(0x20);
if(hp == 0) then
hp = 1;
else
hp = 0;
end;
text(x1+3,y1+3,hp);
box(x1,y1,x2,y2,"green");
for i=0,2 do
timmyshotexists = memory.readbyte(timmyshots+7+(i*8))
x1 = memory.readbyte(timmyshots+1+(i*8));
x2 = memory.readbyte(timmyshots+2+(i*8));
y1 = memory.readbyte(timmyshots+3+(i*8)) + 24;
y2 = memory.readbyte(timmyshots+4+(i*8)) + 24;
if(timmyshotexists ~= 0xF8) then
box(x1,y1,x2,y2,"green");
end;
end;
for i=0,15 do
stype = memory.readbyte(stuff+(i*16)) + 1;
spritedisplay = bit.band(spritetype[stype],3);
spritebox = bit.band(spritetype[stype],12)
spriteflags = bit.band(spritetype[stype],240);
spriteexists = memory.readbyte(stuff+8+(i*16));
if (bit.band(spriteflags,0x10) == 0x10) then
if (i >= 3) then
spritebox = spritebox - 4;
if (spritebox < 0) then
spritebox = 12;
end;
end;
end;
if (bit.band(spriteflags,0x20) == 0x20) then
if (i >= 3) then
spritedisplay = 1;
end;
end;
if (stype == (70+1)) then --Handle OwlBot
if (i == 4) then
spritedisplay = 0;
end;
end;
if (stype == (116 + 1)) then --Handle Cleo
cleo = memory.readbyte(stuff + 15);
if(cleo == 0) then
text(128,8,"Red")
end;
if(cleo == 1) then
text(128,8,"Blue")
end;
if(cleo == 2) then
text(128,8,"Purple")
end;
if(cleo == 3) then
text(128,8,"Pink")
end;
if(cleo == 4) then
text(128,8,"Yellow")
end;
if(cleo == 5) then
text(128,8,"Green")
end;
end;
if (stype == (96 + 1)) then --Handle Amethyst Angel
if(i == 0) then
spritedisplay = 0
end;
if(i == 1) then
spritebox = 12;
end;
end;
if (stype == (100 + 1)) then --Handle Zedd
if(i == 0) then
spritedisplay = 0
end;
end;
if (stype == (106 + 1)) then --Handle TY-524A4ET
if(i == 0) then
spritedisplay = 0
end;
end;
if (stype == (80+1)) then --Handle nagaconda displaying specifically.
nagaconda = memory.readbyte(stuff+10+(i*16))
if (i == 1) then
spritebox = 12;
end;
if((i >= 2)) then
spritedisplay = 1;
end;
if (i == 5) then
spritedisplay = 3;
end;
if (i == 12) then
if (nagaconda == 3) then
spritedisplay = 2;
end;
end;
end;
if (stype == (92+1)) then --Handle Seahorse Turret.
seahorsenext = {2,3,1,0,0}
seahorsefire = memory.readbyte(stuff+13)
seahorsetimer = memory.readbyte(stuff+12)
seahorsebullets = memory.readbyte(stuff+14)
j = 0;
if(seahorsebullets == 0) then
seahorsefire = 3;
end;
while((j < 4) and (seahorsefire < 4)) do
hp = memory.readbyte(stuff+5+((seahorsenext[seahorsefire+1]+1)*16))
--text(128,24+(8*seahorsefire),hp);
if (memory.readbyte(stuff+5+((seahorsenext[seahorsefire+1]+1)*16))==0) then
seahorsefire = seahorsefire - 1;
if(seahorsefire < 0) then
seahorsefire = 3;
end;
else
break;
end;
j = j + 1;
end;
if(seahorsefire < 4) then --Check that there is at least one seahorse turret still alive.
text(128,8,seahorsebullets/4);
--text(128,8,seahorsefire);
--text(128,16,seahorsenext[seahorsefire+1]);
if ((i >= 1) and (i <= 5)) then
spritedisplay = 2;
end;
if ((i-1) == (seahorsenext[seahorsefire+1])) then
spritebox = 4;
x1 = memory.readbyte(stuff+2+(i*16));
y1 = memory.readbyte(stuff+4+(i*16)) + 24;
text(x1,y1+10,seahorsetimer);
else
spritebox = 0;
end;
end;
end;
if((spriteexists < 248) or (i < 3)) then
if ((spriteexists == 248) and (i < 3)) then
spriteexists = memory.readbyte(stuff+7+(i*16));
end;
if((spriteexists < 248)) then
x1 = memory.readbyte(stuff+2+(i*16));
x2 = memory.readbyte(stuff+3+(i*16));
y1 = memory.readbyte(stuff+4+(i*16)) + 24;
y2 = memory.readbyte(stuff+5+(i*16)) + 24;
-- if((stype ~= (30+1)) and (stype ~= (80+1)) and (stype ~= (82+1))) then
if(bit.band(spriteflags,0x40) ~= 0x40) then
if (x2 <= x1) then
x2 = x1 + 15;
end;
if (y2 <= x1) then
y2 = y1 + 15;
end;
end;
--text(1,8+(i*8),stype-1); --Debug info on sprite identifier.
--text(26, 8+(i*8),spritedisplay)
--text(34, 8+(i*8),spritebox)
if (stype == (22+1)) then --Blinking spike room, display the phase counters in a visible spot.
phase = memory.readbyte(stuff+12+(i*16));
text(128,8,phase);
phase = memory.readbyte(stuff+13+(i*16));
text(128,16,phase);
end;
if ((spritedisplay == 0) or (spritedisplay == 2)) then
hp = memory.readbyte(stuff+6+(i*16));
if (hp > 0) then
text(x1+1,y1+1,hp);
end;
end;
if ((spritedisplay == 0) or (spritedisplay == 3)) then
if(stype == (74+1)) then --Colormancers use 14/12 for their attack counters.
phase = memory.readbyte(stuff+14+(i*16))
else
phase = memory.readbyte(stuff+12+(i*16));
end;
if(phase > 0) then
text(x1,y1+8,phase);
end;
if(phase == 0) then
if(stype == (74+1)) then
phase = memory.readbyte(stuff+12+(i*16))
else
phase = memory.readbyte(stuff+13+(i*16));
end;
if(phase > 0) then
text(x1,y1+8,phase);
end;
end;
end;
if(spritebox == 0) then
box(x1,y1,x2,y2,"red");
end;
if(spritebox == 4) then
box(x1,y1,x2,y2,"yellow");
end;
if(spritebox == 8) then
box(x1,y1,x2,y2,"green");
end;
end;
end;
end;
FCEU.frameadvance();
end;
Edit: Barring any bugs, the script should be complete.
Edit: Now shows hit boxes of timmy's shots. Also detects Demo from Version 1.1. Should work on Version 1.0, but can't confirm that, since there isn't a dump of 1.0 out there.