local SCREEN_WIDTH = 384 local SCREEN_HEIGHT = 224 local AXIS_COLOUR = 0xFFFFFFFF local MINI_AXIS_COLOUR = 0xFFFF00FF local AXIS_SIZE = 25 local MINI_AXIS_SIZE = 2 local HITBOX_VULNERABILITY = 0 local HITBOX_ATTACK = 1 local HITBOX_PUSH = 2 local HITBOX_VULNERABILITY_COLOUR = 0x0000FF40 local HITBOX_ATTACK_COLOUR = 0xFF000040 local HITBOX_PUSH_COLOUR = 0x00FF0040 local address = { player1 = 0x00FF8400, player2 = 0x00FF8800, left_screen_edge = 0x00FF8026, top_screen_edge = 0x00FF8028, } local globals = { left_screen_edge = 0, top_screen_edge = 0, } local player1 = {} local player2 = {} function update_globals() globals.left_screen_edge = memory.readword(address.left_screen_edge) globals.top_screen_edge = memory.readword(address.top_screen_edge) end function hitbox_load(obj, i, type, facing_dir, offset_x, offset_y, addr) local hval = memory.readwordsigned(addr + 0) local vval = memory.readwordsigned(addr + 2) local hrad = memory.readwordsigned(addr + 4) local vrad = memory.readwordsigned(addr + 6) if facing_dir == 1 then hval = -hval end local left = offset_x + hval - hrad local top = offset_y + vval - vrad local right = offset_x + hval + hrad local bottom = offset_y + vval + vrad if type == HITBOX_VULNERABILITY then obj[HITBOX_VULNERABILITY][i] = { left = left, right = right, bottom = bottom, top = top, hval = offset_x+hval, vval = offset_y+vval, type = type } else obj[type] = { left = left, right = right, bottom = bottom, top = top, hval = offset_x+hval, vval = offset_y+vval, type = type } end end function update_game_object(obj, base) obj.facing_dir = memory.readbyte(base + 0xB) obj.pos_x = memory.readword(base + 0x10) obj.pos_y = memory.readword(base + 0x14) obj.opponent_dir = memory.readbyte(base + 0x5D) -- Load the vulnerability hitboxes obj[HITBOX_VULNERABILITY] = {} for i = 0, 2 do local v_hb_addr_table = memory.readdword(base + 0x80 + (i*4)) local v_hb_curr_id = memory.readbyte(base + 0x94 + i) hitbox_load(obj, i, HITBOX_VULNERABILITY, obj.facing_dir, obj.pos_x, obj.pos_y, v_hb_addr_table+(v_hb_curr_id*8)) end -- Load the attack hitbox local a_hb_addr_table = memory.readdword(base + 0x8c) local animation_ptr = memory.readdword(base + 0x1C) local a_hb_curr_id = memory.readbyte(animation_ptr + 0x0A) hitbox_load(obj, 0, HITBOX_ATTACK, obj.facing_dir, obj.pos_x, obj.pos_y, a_hb_addr_table+(a_hb_curr_id*0x20)) -- Load the push hitbox local p_hb_addr_table = memory.readdword(base + 0x90) local p_hb_curr_id = memory.readbyte(base + 0x97) hitbox_load(obj, 0, HITBOX_PUSH, obj.facing_dir, obj.pos_x, obj.pos_y, p_hb_addr_table+(p_hb_curr_id*8)) end function game_x_to_mame(x) return (x - globals.left_screen_edge) end function game_y_to_mame(y) -- Why subtract 17? No idea, the game driver does the same thing. return (SCREEN_HEIGHT - (y - 17) + globals.top_screen_edge) end function draw_hitbox(hb) local left = game_x_to_mame(hb.left) local bottom = game_y_to_mame(hb.bottom) local right = game_x_to_mame(hb.right) local top = game_y_to_mame(hb.top) local hval = game_x_to_mame(hb.hval) local vval = game_y_to_mame(hb.vval) if hb.type == HITBOX_VULNERABILITY then colour = HITBOX_VULNERABILITY_COLOUR elseif hb.type == HITBOX_ATTACK then colour = HITBOX_ATTACK_COLOUR elseif hb.type == HITBOX_PUSH then colour = HITBOX_PUSH_COLOUR end gui.drawline(hval, vval-MINI_AXIS_SIZE, hval, vval+MINI_AXIS_SIZE, MINI_AXIS_COLOUR) gui.drawline(hval-MINI_AXIS_SIZE, vval, hval+MINI_AXIS_SIZE, vval, MINI_AXIS_COLOUR) gui.box(left, top, right, bottom, colour) end function draw_game_object(obj) local x = game_x_to_mame(obj.pos_x) local y = game_y_to_mame(obj.pos_y) for i = 0, 2 do draw_hitbox(obj[HITBOX_VULNERABILITY][i]) end draw_hitbox(obj[HITBOX_ATTACK]) draw_hitbox(obj[HITBOX_PUSH]) gui.drawline(x, y-AXIS_SIZE, x, y+AXIS_SIZE, AXIS_COLOUR) gui.drawline(x-AXIS_SIZE, y, x+AXIS_SIZE, y, AXIS_COLOUR) end function render_vsav_hitboxes() update_globals() update_game_object(player1, address.player1) draw_game_object(player1) update_game_object(player2, address.player2) draw_game_object(player2) end gui.register( function() render_vsav_hitboxes() end)