Better enemy health display, when an enemy is invulnerable, the correct health remaining is now displayed instead of a negative value.
To show that the enemy is in an invulnerable phase, the health is in brackets.
-- local nes_screen_height = 240
-- local nes_screen_width = 256
local player_health
local player_lives
local current_weapon
local weapon_power
local player_xspeed
local player_yspeed
local player_xpos
local player_ypos
local camera_xpos
local camera_ypos
local enemy_struct_start = 0x03AB
local enemy_struct_size = 0x10
local enemy_struct_count = 32
-- offset enum:
-- 0x00 xpos (2 byte)
-- 0x02 ypos (2 byte)
-- 0x04 unknown data
-- 0x05 unknown data
-- 0x06 unknown data
-- 0x07 unknown data
-- 0x08 timer
-- 0x09 unknown data
-- 0x0A hp
-- 0x0B unknown data
-- 0x0C unknown data
-- 0x0D unknown data
-- 0x0E unknown data
-- 0x0F unknown data
local enemy_struct_offset_xpos = 0x00
local enemy_struct_offset_ypos = 0x02
local enemy_struct_offset_timer = 0x07
local enemy_struct_offset_hp = 0x09
local enemy_struct2_start = 0x046A
local enemy_struct2_size = 0x06
local enemy_struct2_count = 32
-- offset enum:
-- How to index?
-- 0x00 unknown data
-- 0x01 unknown data
-- 0x02 unknown data
-- 0x03 unknown data
-- 0x04 unknown data
-- 0x05 enemy dead flag
local enemy_struct2_offset_dead = 0x05
local main_hud_pos_base = 300 -- places us below the game area
local function do_hud()
player_health = memory.read_u8(0x031C)
player_lives = memory.read_u8(0x031B)
if (memory.read_u8(0x03A4) == 0) then -- this is technically a boolean
current_weapon = "Wave Blade"
else
current_weapon = "Boomerang "
end
weapon_power = memory.read_u8(0x03A5) + 1 -- +1 to compensate for 0-based level-scale
player_xspeed = memory.read_s8(0x002B)
player_yspeed = memory.read_s8(0x002C)
player_xpos = memory.read_s16_le(0x002E)
player_ypos = memory.read_s16_le(0x0030)
camera_xpos = memory.read_s16_le(0x0034)
camera_ypos = memory.read_s16_le(0x0036)
local hud_pos = main_hud_pos_base * client.getwindowsize() -- compensate for scaled game windows.
gui.text(5,hud_pos, string.format("Health: %2d Extra lives: %d", player_health, player_lives))
gui.text(5,hud_pos+15, string.format("Weapon: %s Strength: %d", current_weapon, weapon_power))
gui.text(5,hud_pos+30, string.format("Speed: X: %3d Y: %3d", player_xspeed, player_yspeed))
gui.text(5,hud_pos+45, string.format("Position: (%5d,%5d) Camera: (%5d,%5d)", player_xpos, player_ypos, camera_xpos, camera_ypos))
for i=0,enemy_struct_size do
local current_struct = enemy_struct_start + (enemy_struct_size * i)
local timer = memory.read_u8(current_struct + enemy_struct_offset_timer)
local hp = memory.read_s8(current_struct + enemy_struct_offset_hp)
local xpos = memory.read_s16_le(current_struct + enemy_struct_offset_xpos)
local ypos = memory.read_s16_le(current_struct + enemy_struct_offset_ypos)
local draw_x = (player_xpos - camera_xpos) + (xpos - player_xpos) - 15 -- enemy x position and camera position do not directly relate
local draw_y = (ypos + camera_ypos) + 10
if hp > 0 then -- HP = 0 means enemy is dead
gui.drawText(draw_x, draw_y, string.format("H:%2d\nT:%2d", hp, timer), "red")
elseif hp < 0 then -- hp < 0 means enemy is invulnerable, the game takes the enemy's health - 128 to mark it, undo that, and put the HP in guards.
hp = hp + 128
gui.drawText(draw_x, draw_y, string.format("H:[%2d]\nT:%2d", hp, timer), "red")
end
end
end
event.onframestart(do_hud)
while true do
emu.frameadvance();
end