User File #42865558898069062

Upload All User Files

#42865558898069062 - Devil Island - Hitboxes and Watches v1.3

Devil Island - Hitboxes and Watches v1.3.lua
900 downloads
Uploaded 11/4/2017 10:40 AM by ThunderAxe31 (see all 111)
This script displays on screen:
  • Player absolute X position
  • Player absolute X lagged frames (counter resets at 9999)
  • Player money
  • Player experience points
  • Experience points left for next attack level
  • Current attack level
  • Player HP
  • Enemy HP
  • Drops content
  • Hitboxes of everything except D1 boss and final boss body
Also note that the watches will disappear while the pause menu is open!
This is probably going to be the final version. Enjoy!
--Hitboxes and Watches v1.3 for GBC Devil Island (Emo Dao) by ThunderAxe31

local R2ub= memory.read_u16_be
local R2ul= memory.read_u16_le
local R1u= memory.read_u8

local white = 0xFFFFFFFF
local black = 0xFF000000

local player_x = R1u(0xD001)
local actions  = R1u(0xD008)

local combined_x_old = -1
local combined_x_lagcount = 0
local framecount_old = -1

local function draw_watches()
	local combined_x = player_x + R2ul(0xC122) --add level x
	
	--count x lag
	local framecount = emu.framecount()
	if framecount_old ~= (framecount-1) then --if a state has been loaded, reset values
		combined_x_lagcount = 0
		combined_x_old = -1
	end
	if (combined_x_old > -1) and (combined_x_old == combined_x) then --checks if the x value is unchanged
		combined_x_lagcount = combined_x_lagcount + 1 --updates the movement lag count
		if combined_x_lagcount > 9999 then --reset counter
			combined_x_lagcount = 0
		end
	end
	combined_x_old = combined_x --updates the x value
	framecount_old = framecount --updates the frame count
	
	--exp stuff
	local exp_amount = R2ub(0xCFF8)
	local exp_next = 0
	local attack = 0
	if exp_amount < 3072 then
		attack = 1
		exp_next =  3072 - exp_amount
	elseif exp_amount <  6144 then
		attack = 2
		exp_next =  6144 - exp_amount
	elseif exp_amount <  8192 then
		attack = 3
		exp_next =  8192 - exp_amount
	elseif exp_amount < 10240 then
		attack = 4
		exp_next = 10240 - exp_amount
	elseif exp_amount < 12288 then
		attack = 5
		exp_next = 12288 - exp_amount
	elseif exp_amount < 14336 then
		attack = 6
		exp_next = 14336 - exp_amount
	elseif exp_amount < 16384 then
		attack = 7
		exp_next = 16384 - exp_amount
	else
		attack = 8
		exp_next = 0
	end
	
	--display watches
	if bit.band(actions, 128) ~= 128 then --if menu is open, don't display.
		gui.pixelText(0, 0, "X_POS:     EXP:      ATK: \nX_LAG:     NEXT:     HP:",  white, black)
		gui.pixelText(24, 0, string.format("%4s", combined_x), white, black) --current X position in level
		gui.pixelText(24, 7, string.format("%4s", combined_x_lagcount), white, black) --current movement X lag counted
		gui.pixelText(60, 0, string.format("%5s", exp_amount), white, black) --experience total
		gui.pixelText(64, 7, string.format("%4s", exp_next), white, black) --experience left for next level
		gui.pixelText(100,0, attack, white, black) --attack level
		gui.pixelText(96, 7, string.format("%2s", R1u(0xCFF5)),  white, black) --player HP
		gui.pixelText(108, 0, "$:" .. R2ul(0xCFF6), white, black) --money
	end
end

local function fix_negative(value) --wrap negative coordinates correctly
	if (value>212) then
		return value-256
	end
	return value
end

local function enemy_hitboxes()
	for i = 0, 3 do --yes, there are just 4 object slots
		local addr = 0xC200+i*0x20 --data chunks for objects are 32 bytes long
		if R1u(addr) ~= 0 then --enemy hitboxes
			gui.drawRectangle(fix_negative(R1u(addr+0x01))+R1u(addr+0x12)-8, fix_negative(R1u(addr+0x02))+R1u(addr+0x14)-16, R1u(addr+0x13)-1, R1u(addr+0x15)-1)
			local obj_type = R1u(addr+0x16)
			local label = ""
			if obj_type==0 then --if enemy, show HP
				if R1u(addr+0x0F)~=255 then
					label = R1u(addr+0x07)
				end
			elseif obj_type==1 then --if money, show how much
				label = "$"..R1u(addr+0x17)
			elseif obj_type==2 then --if health, display a simple hospital cross
				label = "+"
			elseif obj_type==3 then --if pass
				label = "PASS"
			elseif obj_type==4 then --if whip piece
				label = "WHIP\nPIECE"
			else --if unknown, just in case
				label = "?"
			end
			gui.pixelText(fix_negative(R1u(addr+0x01))-7, fix_negative(R1u(addr+0x02))-15, label, white, black)
		end
	end
	
	--since there is currently no better solution, we're simply gonna splat these bosses HP on the screen upper left...
	local head_hp = R1u(0xC1B3)
	local core_hp = R1u(0xC1B4)
	local boss_hp = R1u(0xC1A5)
	if head_hp > 0 then
		gui.pixelText(0, 14, "HEAD HP: " .. head_hp, white, black)
	end
	if core_hp > 0 then
		gui.pixelText(0, 21, "CORE HP: " .. core_hp, white, black)
	end
	if boss_hp > 0 then
		gui.pixelText(0, 28, "BOSS HP: " .. boss_hp, white, black) --using a different Y cooradinate, just in case
	end --and no, all other bosses use the regular enemy object structure. this would explain why only these three have an invicibility timer.
end

local function player_hitboxes()
	local player_y = R1u(0xD000)
	local whip_x = player_x + 8
	local whip_y = player_y - 8
	local player_height = 32
	local whip_height   = 32
		
	if bit.band(actions, 4) == 4 then --if crouched
		player_y = player_y + 8
		player_height = 24
		whip_y = whip_y + 8
		whip_height = 40
	end
	
	gui.drawRectangle(player_x, player_y, 16, player_height) --player hitbox
	
	if bit.band(actions, 2) == 2 then --if attacking
		if R1u(0xD005) == 2 then --if facing left
			whip_x = whip_x -16
		end
		gui.drawRectangle(whip_x, whip_y, 16, whip_height) --whip hitbox
	end
end

while true do
	player_x = R1u(0xD001)
	actions  = R1u(0xD008)
	
	draw_watches()
	enemy_hitboxes()
	player_hitboxes()
	
	emu.frameadvance()
end