/*
Wario Land 4 Boss HUD modification, Version 1
Created by Latius
Sprites used are from Wario Land 4, ripped by cl.exe
*/
if not rawget(_G, "warioHUD") then
	rawset(_G, "warioHUD", true)
else
	warioHUD = true
end

local boss

addHook("NetVars", function(net)
	boss = net(boss)
end)

local dontshow = "_DONTSHOWTHISBOSSMETER" -- hopefully no one makes a boss named this? :p

//These came from the SA1 HUD mod:
local bossnames = {
	-- Vanilla SRB2
	[MT_EGGMOBILE] = "Egg Mobile",
	[MT_EGGMOBILE2] = "Egg Slimer",
	[MT_EGGMOBILE3] = "Sea Egg",
	[MT_EGGMOBILE4] = "Egg Coliseum",
	[MT_FANG] = "Fang",
	[MT_METALSONIC_BATTLE] = "Metal Sonic",
	[MT_CYBRAKDEMON] = "Black Eggman",
	[MT_BLACKEGGMAN] = "Black Eggman",
}

local addonbosses = {
	-- SUGOI
	MT_SILVER_318 = "Silver",
	MT_TURRETMOBILE = "Turret Mobile",
	MT_PURPLEHEART = dontshow,
	-- SUBARASHII
	MT_EGGDOMINATOR = "Egg Dominator",
	MT_RRZBOSS = dontshow,
	MT_EGGWORLD = dontshow,
	MT_EXPSTAR = dontshow,
	-- KIMOKAWAIII
	MT_EGGGUNNER = "Egg Gunner",
	MT_BOUNCYBOI = "Bouncy Boi BoBo",
	MT_CYBERDETON = "Cyber Deton",
	MT_POINTYEGG = "Pointy Egg",
	MT_LJSONIC = "LJ Sonic",
	MT_CONFLEGGRATOR = "Confleggrator",
	MT_AALPBOSS = "Egg Robo",
	MT_DARKSTABOT = "Dark Stabot",
	MT_EGGLAS = "Egg Lasershow",
	MT_PROTAGONIST = "True Protag",
	MT_GUNDAM = dontshow,
	MT_SOAES = dontshow,
	-- (potential) character bosses
	MT_SONIC = "Sonic",
	MT_TAILS = "Tails",
	MT_KNUCKLES = "Knuckles",
	MT_AMY = "Amy Rose",
	MT_SHADOW = "Shadow",
	MT_SILVER = "Silver",
	-- Misc levels
	MT_EGGMOBILE7 = "Egg Boiler", -- True Arena name, I'd like to know if FuriousFox had an official name for this
	MT_STRAYBOLTS_BOSS = "Stray-Bolts",
	MT_OLDK = "K.T.E.",
	MT_ANASTASIA = dontshow,
	MT_BOSSRIDE = "Player", -- this one never gets used, included anyway to tell the game you have it loaded
	-- True Arena's ports
	MT_SANDSUB_326 = "Egg Sand Sub",
	MT_GREENHILLBOSS = "Ball & Chain",
	MT_ROBOHOOD_MINIBOSS = "Robo-Hood",
	MT_SUPERHOOD = "Super Robo-Hood",
	MT_INFINITE_318 = "Infinite",
}

local function setBoss(mo)
	if (mo.health <= 0) return end
	
	local clientplayer
	if netgame then
		if server.mo and server.mo.valid then
			clientplayer = server
		else
			for p in players.iterate do
				if IsPlayerAdmin(p) and p.mo and p.mo.valid then
					clientplayer = p
					break
				end
			end
		end
	else
		clientplayer = players[0]
	end
	
	if not ((clientplayer and clientplayer.valid) -- without client player, we'd have to iterate everyone TWICE AAA :v
	and (clientplayer.mo and clientplayer.mo.valid))
		return
	end 
	
	if (P_CheckSight(mo, clientplayer.mo))
		if ((boss and boss.valid) and not (P_CheckSight(boss, clientplayer.mo))) -- boss exists, but not in line of sight?
		or not (boss and boss.valid) -- or the boss just doesn't exist
			boss = mo
		end
	end
end

local function isMobjTypeValid(mt)
	if (pcall(do return _G[mt] end))
		return _G[mt]
	else
		return nil
	end
end

rawset(_G, "mapSet", function(mo)
	boss = nil
	
	for k,v in pairs(addonbosses)
		local mt = isMobjTypeValid(k)
		if not (mt) continue end
		bossnames[mt] = v
	end
end)

local function drawPlayerDamage(v, p)
	local hp = 6 - min(5, p.timeshit)
	if not p.mo.health then hp = 0 end
	local maxhealth = 6
	local x = 76
	local y = 162
	if modeattacking then y = 148 end
	local midHPatch = v.cachePatch("WLP_BHP")
	local endingHPatch = v.cachePatch("WLP_BHPE")
	local extraHPatch = v.cachePatch("WLP_BHPR")
	local color
	if hp == maxhealth then
		color = v.getColormap("sonic", SKINCOLOR_EMERALD)
	elseif hp > 1 then
		color = v.getColormap("sonic", SKINCOLOR_YELLOW)
	else
		color = v.getColormap("sonic", SKINCOLOR_NEON)
	end
	local flags = V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS
	
	if hp <= 0 then
		v.drawScaled((x*FRACUNIT)-(FRACUNIT/4), y*FRACUNIT, 3*FRACUNIT/2, v.cachePatch("WLP_BHPB"), flags)
		v.drawScaled(((x-2)*FRACUNIT)+(FRACUNIT/2),  y*FRACUNIT, 3*FRACUNIT/2, endingHPatch, flags)
		v.drawStretched(((x-4)*FRACUNIT)-(FRACUNIT/2), y*FRACUNIT, 74*3*FRACUNIT/2, 3*FRACUNIT/2, extraHPatch, flags)
	else
		v.drawScaled((x*FRACUNIT)-(FRACUNIT/4), y*FRACUNIT, 3*FRACUNIT/2, v.cachePatch("WLP_BHPS"), flags, color)
		if hp > 1 then
			for i = 2, (hp) do
				v.drawScaled((((x+7)-(i*6))*FRACUNIT), y*FRACUNIT, 3*FRACUNIT/2, midHPatch, flags, color)
			end
		end
		v.drawScaled((((x+1)-(hp*6))*FRACUNIT), y*FRACUNIT, 3*FRACUNIT/2, endingHPatch, flags)
		v.drawStretched((((x-1)-(hp*6))*FRACUNIT), y*FRACUNIT, (36+(x-(hp*6)))*FRACUNIT, 3*FRACUNIT/2, extraHPatch, flags)
	end
end

local function drawbossHPBarScaled(v)
	if not (boss and boss.valid) return end
	if (bossnames[boss.type] == dontshow) return end
	
	local maxhealth = boss.info.spawnhealth
	local healthbarlen = max(15, boss.info.spawnhealth + 1)
	local x = 321 - (6*healthbarlen)
	local y = 2
	local midHPatch = v.cachePatch("WL_BHP")
	local endingHPatch = v.cachePatch("WL_BHPE")
	local extraHPatch = v.cachePatch("WL_BHPR")
	local color
	local pinch = false
	local stageSecond = false
	
	if (boss.info.damage > 1) and (boss.info.damage <= boss.info.spawnhealth) then
		if boss.health <= boss.info.damage then pinch = true end
	elseif boss.info.damage >= 0 then
		if (boss.health <= maxhealth / 4) or (boss.health == 1) then pinch = true end
	end
	
	if isMobjTypeValid("MT_ROBOHOOD_MINIBOSS") then
		if boss.type == MT_ROBOHOOD_MINIBOSS then pinch = false end
	end
	
	if isMobjTypeValid("MT_STRAYBOLTS_BOSS") then
		if (boss.type == MT_STRAYBOLTS_BOSS) then
			if (boss.health <= 3) then pinch = true
			elseif (boss.health <= 6) then stageSecond = true end
		end
	end
	
	if pinch then
		color = v.getColormap("sonic", SKINCOLOR_NEON)
	elseif (boss.health <= (2*maxhealth) / 3) or stageSecond then
		color = v.getColormap("sonic", SKINCOLOR_YELLOW)
	else
		color = v.getColormap("sonic", SKINCOLOR_EMERALD)
	end
	
	if boss.health <= 0 then
		v.drawScaled((x*FRACUNIT)+(FRACUNIT/4), y*FRACUNIT, 3*FRACUNIT/2, v.cachePatch("WL_BHPB"), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.drawScaled(((x+2)*FRACUNIT)-(FRACUNIT/2),  y*FRACUNIT, 3*FRACUNIT/2, endingHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.drawStretched(((x+4)*FRACUNIT)+(FRACUNIT/2), y*FRACUNIT, (317-x)*3*FRACUNIT/2, 3*FRACUNIT/2, extraHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
	else
		v.drawScaled((x*FRACUNIT)+(FRACUNIT/4), y*FRACUNIT, 3*FRACUNIT/2, v.cachePatch("WL_BHPS"), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, color)
		if boss.health > 1 then
			for i = 2, (boss.health) do
				v.drawScaled((((x-7)+(i*6))*FRACUNIT), y*FRACUNIT, 3*FRACUNIT/2, midHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, color)
			end
		end
		v.drawScaled((((x-1)+(boss.health*6))*FRACUNIT), y*FRACUNIT, 3*FRACUNIT/2, endingHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.drawStretched((((x+1)+(boss.health*6))*FRACUNIT), y*FRACUNIT, (319-(x+(boss.health*6)))*FRACUNIT, 3*FRACUNIT/2, extraHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
	end
	
	if bossnames[boss.type] then
		local bossname = bossnames[boss.type]
		if (isMobjTypeValid("MT_BOSSRIDE"))
			if (_G["MT_BOSSRIDE"] == boss.type)
			and ((boss.rider and boss.rider.valid)
			and (boss.rider.player and boss.rider.player.valid))
				name = boss.rider.player.name
			end
		end
		
		if (boss.health <= 0) or (pinch and ((leveltime % 12) < 6)) then
			v.drawString(319, y+12, "\x85"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "right")
		elseif (boss.flags2 & MF2_FRET) and ((leveltime % 12) > 5) then
			v.drawString(319, y+12, "\x82"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "right")
		else
			v.drawString(319, y+12, "\x80"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "right")
		end
	end
end

local function drawbossHPBar(v)
	if not (boss and boss.valid) return end
	if (bossnames[boss.type] == dontshow) return end
	
	local maxhealth = boss.info.spawnhealth
	local healthbarlen = max(15, boss.info.spawnhealth + 1)
	local x = 321 - (4*healthbarlen)
	local y = 2
	local midHPatch = v.cachePatch("WL_BHP")
	local endingHPatch = v.cachePatch("WL_BHPE")
	local extraHPatch = v.cachePatch("WL_BHPR")
	local color
	local pinch = false
	local stageSecond = false
	
	if (boss.info.damage > 1) and (boss.info.damage <= boss.info.spawnhealth) then
		if boss.health <= boss.info.damage then pinch = true end
	else
		if (boss.health <= maxhealth / 4) or (boss.health == 1) then pinch = true end
	end
	
	if isMobjTypeValid("MT_ROBOHOOD_MINIBOSS") then
		if boss.type == MT_ROBOHOOD_MINIBOSS then pinch = false end
	end
	
	if isMobjTypeValid("MT_STRAYBOLTS_BOSS") then
		if (boss.type == MT_STRAYBOLTS_BOSS) then
			if (boss.health <= 3) then pinch = true
			elseif (boss.health <= 6) then stageSecond = true end
		end
	end
	
	if pinch then
		color = v.getColormap("sonic", SKINCOLOR_NEON)
	elseif (boss.health <= (2*maxhealth) / 3) or stageSecond then
		color = v.getColormap("sonic", SKINCOLOR_YELLOW)
	else
		color = v.getColormap("sonic", SKINCOLOR_EMERALD)
	end
	
	if boss.health <= 0 then
		v.draw(x, y, v.cachePatch("WL_BHPB"), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.draw(x+1, y, endingHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.drawStretched((x+3)*FRACUNIT, y*FRACUNIT, (317-x)*FRACUNIT, FRACUNIT, extraHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
	else
		v.draw(x, y, v.cachePatch("WL_BHPS"), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, color)
		if boss.health > 1 then
			for i = 2, (boss.health) do
				v.draw((x-5)+(i*4), y, midHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, color)
			end
		end
		v.draw((x-1)+(boss.health*4), y, endingHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
		v.drawStretched(((x+1)+(boss.health*4))*FRACUNIT, y*FRACUNIT, (319-(x+(boss.health*4)))*FRACUNIT, FRACUNIT, extraHPatch, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS)
	end
	
	if bossnames[boss.type] then
		local bossname = bossnames[boss.type]
		if (isMobjTypeValid("MT_BOSSRIDE"))
			if (_G["MT_BOSSRIDE"] == boss.type)
			and ((boss.rider and boss.rider.valid)
			and (boss.rider.player and boss.rider.player.valid))
				name = boss.rider.player.name
			end
		end
		
		if (boss.health <= 0) or (pinch and ((leveltime % 12) < 6)) then
			v.drawString(x+1, y+9, "\x85"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "small")
		elseif (boss.flags2 & MF2_FRET) and ((leveltime % 12) > 5) then
			v.drawString(x+1, y+9, "\x82"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "small")
		else
			v.drawString(x+1, y+9, "\x80"..bossname,  V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, "small")
		end
	end
end

addHook("BossThinker", setBoss)
if isMobjTypeValid("MT_ROBOHOOD_MINIBOSS") then
	addHook("MobjThinker", setBoss, MT_ROBOHOOD_MINIBOSS)
end
addHook("MapChange", mapSet)
--addHook("MapLoad", mapSet)

hud.add(function(v, p)
	if boss then
		drawbossHPBarScaled(v)
	end
	
	if (mapheaderinfo[gamemap].bonustype == 1) or (mapheaderinfo[gamemap].bonustype == 2)
		and (not splitscreen) then
		drawPlayerDamage(v, p)
	end
end)