nes-contra-us/docs/lua_scripts/mesen/Show Enemy Positions.lua

106 lines
3.7 KiB
Lua

-- shows the player - enemy collision boxes
-- does not show the player bullet - enemy collision boxes
-- doesn't currently handle collision code f (rising spiked walls and fire beams)
function check_player_x_collision(player_index)
local PLAYER_STATE = emu.read(0x90 + player_index, emu.memType.cpu)
if PLAYER_STATE ~= 0x01 then
-- exit if player not in normal state
return nil
end
-- @check_in_water_crouched
local collision_box = 0x00
local LEVEL_LOCATION_TYPE = emu.read(0x40 + player_index, emu.memType.cpu)
local PLAYER_WATER_STATE = emu.read(0xb2 + player_index, emu.memType.cpu)
if LEVEL_LOCATION_TYPE & 0xfe == 0x00 then
-- outdoor
local PLAYER_SPRITE_SEQUENCE = emu.read(0xbc + player_index, emu.memType.cpu)
if PLAYER_WATER_STATE ~= 0x00 and PLAYER_SPRITE_SEQUENCE == 0x02 then
-- exit if player crouched in water, no collision can happen with player
return nil
end
end
if PLAYER_WATER_STATE == 0x00 then
collision_box = collision_box + 1
end
-- not checking for crouched while on indoor level, because non-bullets can
-- collide when crouching player on indoor levels
local PLAYER_JUMP_STATUS = emu.read(0xa0 + player_index, emu.memType.cpu)
local PLAYER_SPRITE_CODE = emu.read(0xd6 + player_index, emu.memType.cpu)
if PLAYER_JUMP_STATUS == 0x00 then
-- player not jumping
collision_box = collision_box + 1
if PLAYER_SPRITE_CODE ~= 0x17 then
collision_box = collision_box + 1
end
end
-- draw player collision point
local SPRITE_Y_POS = emu.read(0x031a + player_index, emu.memType.cpu)
local SPRITE_X_POS = emu.read(0x0334 + player_index, emu.memType.cpu)
emu.drawRectangle(SPRITE_X_POS, SPRITE_Y_POS, 1, 1, 0x0000ff, false)
for i = 0,0xf do
local ENEMY_ROUTINE = emu.read(0x04b8 + i, emu.memType.cpu)
local ENEMY_ROUTINE = emu.read(0x04b8 + i, emu.memType.cpu)
local ENEMY_STATE_WIDTH = emu.read(0x0598 + i, emu.memType.cpu)
local should_test_collision = ENEMY_STATE_WIDTH & 0x01 == 0x00
if ENEMY_ROUTINE ~= 0x00 and should_test_collision then
set_enemy_collision_box(player_index, i, collision_box)
end
end
end
function set_enemy_collision_box(player_index, i, collision_box)
local ENEMY_SCORE_COLLISION = emu.read(0x0588 + i, emu.memType.cpu) & 0x0f
if ENEMY_SCORE_COLLISION == 0x0f then
-- todo handle (fire beam and rising spiked wall)
return
end
local collision_box_addr = emu.readWord(0xe4e8 + (collision_box * 2), emu.memType.cpu) -- collision_box_codes_tbl
local offset = ENEMY_SCORE_COLLISION * 4
local y0 = emu.read(collision_box_addr + offset, emu.memType.cpu)
local x0 = emu.read(collision_box_addr + offset + 1, emu.memType.cpu)
local height = emu.read(collision_box_addr + offset + 2, emu.memType.cpu)
local width = emu.read(collision_box_addr + offset + 3, emu.memType.cpu)
local ENEMY_Y_POS = emu.read(0x0324 + i, emu.memType.cpu)
local ENEMY_X_POS = emu.read(0x033e + i, emu.memType.cpu)
local topY = ENEMY_Y_POS
if y0 > 0x80 then
y0 = negateInt(y0)
topY = ENEMY_Y_POS - y0
else
topY = ENEMY_Y_POS + y0
end
local topX = ENEMY_X_POS
if x0 > 0x80 then
x0 = negateInt(x0)
topX = ENEMY_X_POS - x0
else
topX = ENEMY_X_POS + x0
end
emu.drawRectangle(topX, topY, width, height, 0x0000ff, false)
end
function negateInt(num)
if(num > 0x80) then
num = (~num + 1) & 0xff
end
return num
end
function Main()
check_player_x_collision(0)
end
emu.addEventCallback(Main, emu.eventType.endFrame)