--Kudos!
rawset(_G, "kudos", {})
freeslot("sfx_kud1", "sfx_kud2", "sfx_kud3", "sfx_kud4", "sfx_kud5")
freeslot("MT_KUDOS")
freeslot("MT_KUDOFIRE")
freeslot("MT_KUDOPART")
sfxinfo[sfx_kud1].caption = "Kudos!"
sfxinfo[sfx_kud2].caption = "Double Kudos!"
sfxinfo[sfx_kud3].caption = "Triple Kudos!"
sfxinfo[sfx_kud4].caption = "Quadruple Kudos!"
sfxinfo[sfx_kud5].caption = "Ultra Kudos!"

kudos.GetPlayerFromString = function(src)
	if tonumber(src) ~= nil and tonumber(src) >= 0 and tonumber(src) <= 31 then
		return players[tonumber(src)]
	else
		src = src:lower()
		for player in players.iterate do
			if player.name:lower() == src then return player end
		end
	end
end



--Reset



addHook("MapLoad", function()
	for player in players.iterate do
		if player.thumbsup and player.thumbsup.valid then
			P_RemoveMobj(player.thumbsup)
		end
		if player.kudosfire and player.kudosfire.valid then
			P_RemoveMobj(player.kudosfire)
		end
		player.kudos = nil
		player.kudes = nil
		player.thumbsup = nil
		player.kudosfire = nil
	end
end)



--THE Player Thinker



addHook("PlayerThink", function(player)
	if player and player.mo then
		if player.inthebeam == nil then
			CONS_Printf(player, "\x82Use command 'kudos <player>' in console to commend another player for skillful performance!")
			player.inthebeam = true
		end			
		if player.mo.eflags & MFE_VERTICALFLIP then
			player.kudograv = -1
			player.kudoflip = 1
		else
			player.kudograv = 1
			player.kudoflip = 0
		end
		if (player.kudos == nil) then
			player.kudos = 0
		end
		if (player.kudes == nil) then
			player.kudes = 0
		end
		
		if player.kudos != player.prekudos and player.kudos != 0 then
			if player.kudos == 1 then
				chatprint("\x82"..player.name.."\x86 now has "..player.kudos.." Kudos!\x80")
			else
				chatprint("\x82"..player.name.."\x86 now has "..player.kudos.." Kudos!'s!\x80")
			end
			if player.kudos == 7 then
				chatprint("\x82"..player.name.."\x81 is on a Kudos! rampage!\x80")
			elseif player.kudos == 5 then
				chatprint("\x82"..player.name.."\x87 is on a Kudos! spree!\x80")
			elseif player.kudos == 3 then
				chatprint("\x82"..player.name.."\x88 is on a Kudos! combo!\x80")
			end
		end
		player.prekudos = player.kudos
		
		if player.kudos > 0 and player.mo then
			if player.thumbsup == nil then
				player.thumbsup = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + player.kudograv*(4*(P_GetPlayerSpinHeight(player))/2) + player.kudoflip*player.mo.height, MT_KUDOS)
				player.thumbsup.scale = (player.mo.scale)*2
				player.thumbsup.parent = player
			end
			if (player.kudos > 2) and (player.kudosfire == nil) then
				player.kudosfire = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z + player.kudograv*(4*(P_GetPlayerSpinHeight(player))/2) + player.kudoflip*player.mo.height, MT_KUDOFIRE)
				player.kudosfire.scale = 3*(player.mo.scale)/2
			end
			player.xkudoshake = P_RandomRange(-1*(player.kudos - 1), player.kudos - 1)*FRACUNIT/3
			player.ykudoshake = P_RandomRange(-1*(player.kudos - 1), player.kudos - 1)*FRACUNIT/3
			player.zkudoshake = P_RandomRange(-1*(player.kudos - 1), player.kudos - 1)*FRACUNIT/3
			if player.thumbsup and player.thumbsup.valid and player.kudosfire and player.kudosfire.valid then
				if player.kudos > 6 then
					player.thumbsup.state = S_KUDOS4
					player.kudosfire.burn = 3
				elseif player.kudos > 4 then
					player.thumbsup.state = S_KUDOS3
					player.kudosfire.burn = 2
				elseif player.kudos > 2 then
					player.thumbsup.state = S_KUDOS2
					player.kudosfire.burn = 1
				end
				local plheight = P_GetPlayerSpinHeight(player)
				P_MoveOrigin(player.kudosfire, player.mo.x + player.xkudoshake, player.mo.y + player.ykudoshake, player.zkudoshake + player.mo.z + player.kudograv*(4*(plheight)/2) + player.kudoflip*player.mo.height)
				if player.kudograv == -1 then
					player.kudosfire.eflags = $|MFE_VERTICALFLIP
				else
					player.kudosfire.eflags = $ & ~MFE_VERTICALFLIP
				end
			end
			if player.thumbsup and player.thumbsup.valid then
				local plheight = P_GetPlayerSpinHeight(player)
				P_MoveOrigin(player.thumbsup, player.mo.x + player.xkudoshake, player.mo.y + player.ykudoshake, player.zkudoshake + player.mo.z + player.kudograv*(4*(plheight)/2) + player.kudoflip*player.mo.height)
				if player.kudograv == -1 then
					player.thumbsup.eflags = $|MFE_VERTICALFLIP
				else
					player.thumbsup.eflags = $ & ~MFE_VERTICALFLIP
				end
			end
		end
		
		if player.thumbsup and player.thumbsup.valid and player.mo then
			if player.kudtimer == nil then
				player.kudtimer = 0
			end
			if player.kudos > 1 then
				if player.kudtimer <= 0 then
					local xrand = P_RandomRange(-10, 10)*FRACUNIT
					local yrand = P_RandomRange(-10, 10)*FRACUNIT
					local zrand = player.kudograv*P_RandomRange(3, 8)*FRACUNIT
					local kpart = P_SpawnMobj(player.thumbsup.x + xrand, player.thumbsup.y + yrand, player.thumbsup.z + zrand, MT_KUDOPART)
					player.kudtimer = 40/player.kudos
					if player.kudograv == -1 and kpart and kpart.valid then
						kpart.eflags = $|MFE_VERTICALFLIP
					end
					if player.kudos > 6 and kpart and kpart.valid then
						kpart.state = S_KDPRT41
						P_SetObjectMomZ(kpart, 5*FRACUNIT)
					elseif player.kudos > 4 and kpart and kpart.valid then
						kpart.state = S_KDPRT31
						P_SetObjectMomZ(kpart, 4*FRACUNIT)
					elseif player.kudos > 2 and kpart and kpart.valid then
						kpart.state = S_KDPRT21
						P_SetObjectMomZ(kpart, 3*FRACUNIT)
					else
						P_SetObjectMomZ(kpart, 2*FRACUNIT)
					end
					if player.kudos > 3
						local xrand = P_RandomRange(-10, 10)*FRACUNIT
						local yrand = P_RandomRange(-10, 10)*FRACUNIT
						local zrand = player.kudograv*P_RandomRange(5, 10)*FRACUNIT
						local kember = P_SpawnMobj(player.thumbsup.x + xrand, player.thumbsup.y + yrand, player.thumbsup.z + zrand, MT_FLAMEPARTICLE)
						if player.kudograv == -1 and kember and kember.valid then
							kember.eflags = $|MFE_VERTICALFLIP
						end
						if player.kudos > 6 and kember and kember.valid then
							P_SetObjectMomZ(kember, 3*FRACUNIT)
							kember.colorized = true
							kember.color = SKINCOLOR_MAGENTA
						elseif player.kudos > 4 and kember and kember.valid then
							P_SetObjectMomZ(kember, 2*FRACUNIT)
							kember.colorized = false
						elseif player.kudos > 2 and kember and kember.valid then
							P_SetObjectMomZ(kember, 1*FRACUNIT)
							kember.colorized = true
							kember.color = SKINCOLOR_ARCTIC
						end
					end
					if player.kudos > 5
						for i = 1,6 do
							local zrand = player.kudograv*P_RandomRange(4, 5)*FRACUNIT
							local zspace = player.kudograv*i*10*FRACUNIT
							local kthunder = P_SpawnMobj(player.thumbsup.x, player.thumbsup.y, player.thumbsup.z + zspace, MT_WATERZAP)
							if player.kudograv == -1 and kthunder and kthunder.valid then
								kthunder.eflags = $|MFE_VERTICALFLIP
							end
							kthunder.colorized = true
							if i == 1 then
								kthunder.color = SKINCOLOR_CYAN
								kthunder.scale = 2*FRACUNIT
							elseif i == 2 then
								kthunder.color = SKINCOLOR_AQUA
								kthunder.scale = 7*FRACUNIT/4
							elseif i == 3 then
								kthunder.color = SKINCOLOR_SEAFOAM
								kthunder.scale = 6*FRACUNIT/4
							elseif i == 4 then
								kthunder.color = SKINCOLOR_LIME
								kthunder.scale = 5*FRACUNIT/4
							elseif i == 5 then
								kthunder.color = SKINCOLOR_YELLOW
								kthunder.scale = FRACUNIT
							else
								kthunder.colorized = false
								kthunder.scale = 3*FRACUNIT/4
							end
							local xrand = P_RandomRange(-25, 25)*FRACUNIT
							local yrand = P_RandomRange(-25, 25)*FRACUNIT
							local zrand = player.kudograv*P_RandomRange(2, 55)*FRACUNIT
							local klightning = P_SpawnMobj(player.thumbsup.x + xrand, player.thumbsup.y + yrand, player.thumbsup.z + zrand, MT_WATERZAP)
						end
					end
					if player.kudos > 7
						local xrand = P_RandomRange(-37, 37)*FRACUNIT
						local yrand = P_RandomRange(-37, 37)*FRACUNIT
						local zrand = player.kudograv*P_RandomRange(-7, 50)*FRACUNIT
						local kspark = P_SpawnMobj(player.thumbsup.x + xrand, player.thumbsup.y + yrand, player.thumbsup.z + zrand, MT_SUPERSPARK)
						kspark.scale = FRACUNIT/4
						player.thumbsup.grow = true
						player.thumbsup.stretch = player.kudos - 8
					end
				end
			end
			if player.kudtimer != nil then
				if player.kudtimer > 0 then
					player.kudtimer = player.kudtimer - 1
				end
			end
		end
	end
	if player and player.playerstate == PST_REBORN then
		if player.thumbsup and player.thumbsup.valid then
			P_RemoveMobj(player.thumbsup)
		end
		if player.kudosfire and player.kudosfire.valid then
			P_RemoveMobj(player.kudosfire)
		end
		player.thumbsup = nil
		player.kudosfire = nil
	end
end)



--Mobj Thinkers



addHook("MobjThinker", function(mo)
	if mo.burn == nil then
		mo.burn = 0
	end
	if mo.burn != mo.preburn then
		if mo.burn == 1 then
			mo.state = S_KDFIR1
		elseif mo.burn == 2 then
			mo.state = S_KDFIR2
		elseif mo.burn == 3 then
			mo.state = S_KDFIR3
		end
	end
	mo.preburn = mo.burn
end, MT_KUDOFIRE)

addHook("MobjThinker", function(mo)
	if mo and mo.valid
		if mo.livedtime == nil then
			mo.livedtime = 0
			mo.scale = FRACUNIT/2
		end
		mo.livedtime = mo.livedtime + 1
		if mo.livedtime < 16
			mo.destscale = 5*FRACUNIT/4
		elseif mo.livedtime >= 16
			mo.destscale = FRACUNIT/2
		end
	end		
end, MT_KUDOPART)

addHook("MobjThinker", function(mo)
	if mo and mo.valid
	and (mo.grow == true) then
		if mo.livedtime == nil then
			mo.livedtime = 0
			mo.destscale = (5*FRACUNIT/2) + mo.stretch*FRACUNIT
		end
		mo.livedtime = mo.livedtime + 1
		if mo.livedtime == 8
			mo.destscale = FRACUNIT*2
		elseif mo.livedtime >= 16
			mo.livedtime = 0
			mo.destscale = (5*FRACUNIT/2) + mo.stretch*FRACUNIT
		end
	end		
end, MT_KUDOS)



--Commands



COM_AddCommand("debugkudos", function(player)
    if not (player == server or IsPlayerAdmin(player)) return end
    if player.debugkudos != 1 then
        player.debugkudos = 1
    else
        player.debugkudos = 0
    end
    CONS_Printf(player, "Debugkudos = "..player.debugkudos)
end)

COM_AddCommand("kudos", function(player, arg1)
	if not player.valid then
		CONS_Printf(player, "You cannot use this right now!")
		return
	end
	if player.mo
		if not player.mo.valid then
			CONS_Printf(player, "This can only be used in a level!")
			return
		end
	else
		CONS_Printf(player, "You cannot use this right now!")
		return
	end
	if player.kudes > 0 and player.debugkudos != 1 then
		CONS_Printf(player, "You cannot Kudos! someone twice within the same level!")
		return
	end
	if arg1 then
		local target = kudos.GetPlayerFromString(arg1)
	if not target then
		CONS_Printf(player, "Player "..arg1.." does not exist!")
		return
	end
	if not target.valid then
		CONS_Printf(player, "Player "..arg1.." is not valid!")
		return
	end
		player.kudes = player.kudes + 1
		target.kudos = target.kudos + 1
		--chatprint(target.name.." has been Kudos!'d by "..player.name)
		if target.kudos == 1 then
			S_StartSound(nil, sfx_kud1)
		end
		if target.kudos == 2 then
			S_StartSound(nil, sfx_kud2)
		end
		if target.kudos == 3 then
			S_StartSound(nil, sfx_kud3)
		end
		if target.kudos == 4 then
			S_StartSound(nil, sfx_kud4)
		end
		if target.kudos >= 5 then
			S_StartSound(nil, sfx_kud5)
		end
	end
end)



--Leaderboard



local function GetTeam(v, tab)
	local cv_compactscoreboard = CV_FindVar("compactscoreboard")
	local redplayers = 0
	local blueplayers = 0

	for i = 1,#tab do
		if tab[i].ctfteam == 1 then
			redplayers = redplayers + 1
			--if redplayers > 9 then
				-- not enough room
			--	return
			--end
		elseif tab[i].ctfteam == 2 then
			blueplayers = blueplayers + 1
			--if blueplayers > 9 then
				-- not enough room
			--	return
			--end
		end
	end

	redplayers = 0
	blueplayers = 0
	if (cv_compactscoreboard and cv_compactscoreboard.value) or (#tab > 18) then
		for i = 1,#tab do
			if not tab[i].spectator then
				local x = 52
				local y
				if tab[i].ctfteam == 1 then
					redplayers = redplayers + 1
					x = x + 160
					y = (redplayers * 9) + 23
					
				elseif tab[i].ctfteam == 2 then
					blueplayers = blueplayers + 1
					y = (blueplayers * 9) + 23
				end
				if (tab[i].kudos) and (tab[i].kudos != 0) and not tab[i].quittime or (leveltime / (TICRATE/2) & 1) then
					local sonicj = V_GRAYMAP
					if tab[i].kudos > 6 then
						sonicj = V_MAGENTAMAP
					elseif tab[i].kudos > 4 then
						sonicj = V_ORANGEMAP
					elseif tab[i].kudos > 2 then
						sonicj = V_SKYMAP
					end
					local sideline = 54
					if tab[i].ctfteam == 1
						sideline = -120
					end
					local weird = 0
					if #tab <= 9 then
						weird = -7
					end
					if tab[i].kudos != 0 then
						--v.drawString(x+20, y+9, "(wario)", f, "small");
						v.drawScaled(FRACUNIT*(x - sideline + weird), FRACUNIT*(y - 4), 5*FRACUNIT/4, v.cachePatch("MINKDS"))
						v.drawString(x - sideline - 1 + weird, y - 3, ""..tab[i].kudos.."", sonicj, "thin-right");	
					end
				end
			end
		end
	else
		for i = 1,#tab do
			if not tab[i].spectator then
				local x = 52
				local y
				if tab[i].ctfteam == 1 then
					redplayers = redplayers + 1
					x = x + 160
					y = (redplayers * 16) + 16
				elseif tab[i].ctfteam == 2 then
					blueplayers = blueplayers + 1
					y = (blueplayers * 16) + 16
				end
				if (tab[i].kudos) and (tab[i].kudos != 0) and not tab[i].quittime or (leveltime / (TICRATE/2) & 1) then
					local sonicj = V_GRAYMAP
					if tab[i].kudos > 6 then
						sonicj = V_MAGENTAMAP
					elseif tab[i].kudos > 4 then
						sonicj = V_ORANGEMAP
					elseif tab[i].kudos > 2 then
						sonicj = V_SKYMAP
					end
					local sideline = 70
					if tab[i].ctfteam == 1
						sideline = -110
					end
					--v.drawString(x+20, y+9, "(wario)", f, "small");
					if tab[i].kudos != 0 then
						v.drawScaled(FRACUNIT*(x - sideline), FRACUNIT*(y - 8), 5*FRACUNIT/4, v.cachePatch("KUDOSS"))
						v.drawString(x - sideline, y + 4, ""..tab[i].kudos.."", sonicj, "thin-right")
						--v.drawString(x, y+9, "(" .. tab[i].kudos .. ")", f, "small");
					end	
				end
			end
		end
	end
end

hud.add(function (v)
	local cv_compactscoreboard = CV_FindVar("compactscoreboard")
	local tab = {}
	for player in players.iterate do
		if player and player.valid and (G_PlatformGametype() or not player.spectator) then
			local inserted = false
			for i = 1,#tab do
				if gametype == GT_RACE then
					if circuitmap then
						if player.laps >= tab[i].laps then
							table.insert(tab, i, player)
							inserted = true
							break
						end
					else
						if player.realtime <= tab[i].realtime then
							table.insert(tab, i, player)
							inserted = true
							break
						end
					end
				else
					if player.score >= tab[i].score then
						table.insert(tab, i, player)
						inserted = true
						break
					end
				end
			end
			if not inserted then
				table.insert(tab, player)
			end
		end
	end

	local x = 32
	local y = 32
	if G_GametypeHasTeams() then
		GetTeam(v, tab)
		return
	elseif #tab <= 9 then
		x = 40
		y = 32
	end
	if (cv_compactscoreboard and cv_compactscoreboard.value) or (#tab > 18) then
		for i, player in ipairs(tab) do
			if not player.quittime or (leveltime / (TICRATE/2) & 1) then
				if (player.kudos != nil) and (player.kudos != 0) then
					local sonicj = V_GRAYMAP
					if player.kudos > 6 then
						sonicj = V_MAGENTAMAP
					elseif player.kudos > 4 then
						sonicj = V_ORANGEMAP
					elseif player.kudos > 2 then
						sonicj = V_SKYMAP
					end
					local sideline = 40
					if x > 50
						sideline = -135
					end
					local weird = 0
					if #tab <= 9 then
						weird = -7
					end
					--v.drawString(x+20, y+9, "(wario)", f, "small");
					v.drawScaled(FRACUNIT*(x - sideline + weird), FRACUNIT*(y - 5), 5*FRACUNIT/4, v.cachePatch("MINKDS"))
					v.drawString(x - sideline - 1 + weird, y - 4, ""..player.kudos.."", sonicj, "thin-right")
				end
			end
			y = y + 9
			if y > 180 then
				y = 36
				x = x + 160
			end
		end
	else
		for i, player in ipairs(tab) do
			if not player.quittime or (leveltime / (TICRATE/2) & 1) then
				if (player.kudos != nil) and (player.kudos != 0) then
					local sonicj = V_GRAYMAP
					if player.kudos > 6 then
						sonicj = V_MAGENTAMAP
					elseif player.kudos > 4 then
						sonicj = V_ORANGEMAP
					elseif player.kudos > 2 then
						sonicj = V_SKYMAP
					end
					local sideline = 43
					if x > 50
						sideline = -130
					end
					--v.drawString(x+20, y+9, "(wario)", f, "small");
					v.drawScaled(FRACUNIT*(x - sideline), FRACUNIT*(y - 7), 5*FRACUNIT/4, v.cachePatch("KUDOSS"))
					v.drawString(x - sideline, y + 5, ""..player.kudos.."", sonicj, "thin-right")
				end
			end
			y = y + 16
			if y > 160 then
				y = 30
				x = x + 160
			end
		end
	end
end, "scores")



--Mod by SuperOfSrb2
--Leaderboard display template by Gouldron
print("\x82Use command 'kudos <player>' in console to commend another player for skillful performance!")