/*

	Soap's combo bar, the same one kids wouldn't stop asking me for
	download links.
	Not exactly the same, but the original code is messy and I'd rather
	reference Takis' code.
	
	-luigi budd
	
*/

//I CANT LIVE WITHOUT MY TR
local TR = TICRATE
local pnk = "\x8E"
local wht = "\x80"
local ranks = {
	"Lame...",
	"\x83Soapy",
	"\x88".."Alright...",
	"\x8B".."Going Places!",
	"\x82Nice!",
	"\x84".."Gamer!",
	"\x8D".."Destructive!",
	"\x87".."Demolition Expert!",
	"\x85Menacing!",
	"\x86WICKED!!",
	"\x85".."Adobe Flash!",
	"\x86Robo!",
	"\x88".."BLAST!!",
	"F"..pnk.."u"..wht.."n"..pnk.."n"..wht.."y"..pnk.."!",
	"\x86Unfunny."
}
local maxtime = 7*TR
local parttime = 2*TR
local comboup = 10
//spike stuff according tro source
// https://github.com/STJr/SRB2/blob/a4a3b5b0944720a536a94c9d471b64c822cdac61/src/p_map.c#L838
local SPIKE_LIST = {
	[MT_SPIKE] = true,
	[MT_WALLSPIKE] = true,
	[MT_SPIKEBALL] = true,
	[MT_BOMBSPHERE] = true,
}

//from chrispy chars!!! by Lach!!!!
local function SafeFreeslot(...)
	for _, item in ipairs({...})
		if rawget(_G, item) == nil
			freeslot(item)
		end
	end
end

SafeFreeslot("sfx_shudcl")
sfxinfo[sfx_shudcl].caption = "Menu Close"
SafeFreeslot("sfx_shudop")
sfxinfo[sfx_shudop].caption = "Menu Open"
for i = 0, 2
	SafeFreeslot("sfx_comup"..i)
	sfxinfo[sfx_comup0 + i].caption = "\x83".."Combo Up!\x80"
end

rawset(_G, "GivePlayerCombo",function(p,add,max,remove)
	if p.alreadyhascombometer
		return
	end
	if (p.powers[pw_carry] == CR_NIGHTSMODE)
	or not (gametyperules & GTR_FRIENDLY)
		return
	end
	if add == nil
		add = false
	end
	if max == nil
		max = false
	end
	if remove == nil
		remove = false
	end
	
	local c = p.combo
	
	if add == true
		c.count = $+1
		
		if c.count == 1
			S_StartSound(nil,sfx_shudop,p)
		end
		
		if not (c.count % comboup)
			c.rank = $+1
			c.showrank.tics = 2*TR
			c.showrank.num = c.rank
			c.showrank.score = c.score
			S_StartSound(nil,P_RandomRange(sfx_comup0,sfx_comup2),p)
		end
		
		c.time = maxtime
	else
		if not c.count
			return
		end
		
		if (remove)
			if c.time >= parttime
				c.time = $-parttime
			else
				c.time = 0
			end
		else
			if max == true
				c.time = maxtime
			else
				c.time = $+parttime
			end
		end
	end
end)

addHook("PlayerThink",function(p)
	if not p
	or not p.valid
		return
	end
	
	//set this to 2 every frame to prevent this running for your skin
	//otherwise, it will run for everyon!!!
	if p.alreadyhascombometer
		p.alreadyhascombometer = $-1
		return
	end
	
	if not p.combo
		p.combo = {
			count = 0,
			time = 0,
			
			rank = 0,
			score = 0,
			verys = 0,
			
			showrank = {num = 0,score = 0,tics = 0},
			waslost = false,
			
			lastskin = 0,
		}
		return
	end
	
	local c = p.combo
	local me = p.realmo
	
	if me.skin ~= c.lastskin
		c.time = 0
	end
	
	if c.time
		if (p.powers[pw_carry] ~= CR_NONE)
			return
		end
		
		if c.time > maxtime
			c.time = maxtime
		end
		
		local cc = c.count
		c.score = ((cc*cc)/2)+(10*cc)
		
		c.verys = cc/(#ranks*comboup)
		
//		c.rank = ranks[ ((cc-1) % 15)+1]
		
		c.time = $-1
	else
		if c.count
			S_StartSound(nil,sfx_shudcl,p)
			P_AddPlayerScore(p,c.score)
			c.showrank.num = c.rank
			c.showrank.score = c.score
			c.showrank.tics = 2*TR
			c.waslost = true
			c.count = 0
		end
		
	end
	
	if c.showrank.tics
		c.showrank.tics = $-1
	else
		if c.waslost
			c.waslost = false
		end
		if c.showrank.num
			c.showrank.num = 0
		end
		if c.showrank.score
			c.showrank.score = 0
		end
	end
	
	c.lastskin = me.skin
end)

local drawcombotimebar = function(v, p, combdisp,comby)
	local me = p.mo
	local c = p.combo
	local maxammo = maxtime/5
	local curammo = c.time/5
	local x = hudinfo[HUD_RINGS].x+18+combdisp
	local y = hudinfo[HUD_RINGS].y+30-2+comby
	local barx = x //- maxammo/2
	local bary = y
	local patch1 = v.cachePatch("CANSEG1") //blue
	local patch3 = v.cachePatch("CANSEG2") //black
	
		--Ammo bar
		local pos = 0
		while (pos < maxammo)
			local patch = patch3
			pos = $ + 1
			
			
				if pos <= curammo
					v.draw(barx + pos - 1, bary, patch3, V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS|V_PERPLAYER)
					if pos > curammo - 1
						if (curammo <= 1)
							//first
							patch = patch1
						else
							//fill
							patch = patch1
						end
					else
						patch = patch1
					end
				end
			//todo: skincolors
			v.draw(barx + pos - 1, bary, patch, V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS|V_PERPLAYER,v.getColormap(nil,SKINCOLOR_SUPERSILVER5))
		end
		
end

addHook("HUD",function(v,p)
	if not p
	or not p.valid
		return
	end
	
	if p.alreadyhascombometer
		return
	end
	
	local c = p.combo
	local combdisp = 8
	local comby = 0
	local endmovedown = 0
	if p.pflags & PF_FINISHED
		comby = 5+5+15
	end
	
	if c.time
		v.draw(hudinfo[HUD_RINGS].x-combdisp+5,
			hudinfo[HUD_RINGS].y+14+comby,
			v.cachePatch("COMBBACK"),
			V_SNAPTOLEFT|V_SNAPTOTOP|V_30TRANS|V_PERPLAYER,
			v.getColormap(nil, SKINCOLOR_BLACK)
		)
		v.drawNum(hudinfo[HUD_RINGS].x+16+combdisp,
			hudinfo[HUD_RINGS].y+20+comby,
			c.count,
			V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER
		)
		v.drawString(hudinfo[HUD_RINGS].x+18+combdisp,
			hudinfo[HUD_RINGS].y+20+comby,
			"Combo!",
			V_HUDTRANS|V_ALLOWLOWERCASE|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER,
			"thin"
		)
		drawcombotimebar(v,p,combdisp,comby)
		endmovedown = 25
		
	end
	
	if c.showrank.tics
		local isvery = c.showrank.num/(#ranks*comboup)
		if c.waslost
			v.drawString(hudinfo[HUD_RINGS].x+4,
				hudinfo[HUD_RINGS].y+20+endmovedown+comby,
				"That combo was",
				V_HUDTRANS|V_ALLOWLOWERCASE|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER,
				"thin"
			)
			
			local length = #ranks
			
			v.drawString(hudinfo[HUD_RINGS].x+34,
				hudinfo[HUD_RINGS].y+20+17+endmovedown+comby,
				ranks[ ((c.showrank.num) % length)+1 ],
				V_HUDTRANS|V_ALLOWLOWERCASE|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER,
				"thin-center"
			)
			
			if isvery
				v.drawScaled((hudinfo[HUD_RINGS].x-combdisp+5+7)*FU,
					(hudinfo[HUD_RINGS].y+14+15+endmovedown+comby)*FU,
					FU/3,
					v.cachePatch("COMBVERY"),
					V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS|V_PERPLAYER
				)
			end
			
			v.drawString(hudinfo[HUD_RINGS].x+35,
				hudinfo[HUD_RINGS].y+20+34+endmovedown+comby,
				c.showrank.score,
				V_HUDTRANS|V_ALLOWLOWERCASE|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER,
				"small-center"
			)
		else
			local xdisp = 10
			local ydisp = 15
			local length = #ranks
			v.drawString(hudinfo[HUD_RINGS].x+34+xdisp,
				hudinfo[HUD_RINGS].y+20+17+ydisp,
				ranks[ ((c.showrank.num) % length)+1 ],
				V_HUDTRANS|V_ALLOWLOWERCASE|V_SNAPTOLEFT|V_SNAPTOTOP|V_PERPLAYER,
				"thin-center"
			)
			if isvery
				v.drawScaled((hudinfo[HUD_RINGS].x-combdisp+5+7+xdisp)*FRACUNIT,(hudinfo[HUD_RINGS].y+14+15+ydisp)*FRACUNIT,FRACUNIT/3,v.cachePatch("COMBVERY"),V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS|V_PERPLAYER, v.getColormap(nil, nil))	
			end
		end
	end
	
end)

addHook("MobjDeath",function(mo,inf,sor)
	if not sor
	or not sor.valid
		return
	end
	
	if not sor.player
	or not sor.player.valid
		return
	end
	
	if sor.player.alreadyhascombometer
		return
	end
	
	local p = sor.player

	if mo.flags & MF_MONITOR
		if mo.type ~= MT_EGGMAN_BOX
			GivePlayerCombo(p,true)
		end
	end
	
	if ((mo.type == MT_RING)
	or (mo.type == MT_COIN))
		GivePlayerCombo(p,false)		
	end
	
	if p
	and p.combo
		local c = p.combo

		if ((mo.flags & MF_ENEMY) or (mo.flags & MF_BOSS))
		or (SPIKE_LIST[mo.type] == true)
		or (mo.type == MT_PLAYER)
		and (not mo.ragdoll)
			GivePlayerCombo(p,true)
		end

	end
end)