rawset(_G, "gxChar", {}) --Global namespace so other scripts can see some stuff

//Credit: Montblanc

--CHANGE ME
--Write in all of your sounds here
--ex your sound file in the pack is DSLAST1, write "sfx_last1" here
freeslot("sfx_fplay","sfx_ftail","sfx_fknux","sfx_fkegg","sfx_fmetr","sfx_fkflk","sfx_fmoto","sfx_fkamy","sfx_fkgty","sfx_fkray","sfx_fespo","sfx_fvect","sfx_fchao","sfx_fe102","sfx_fchsz","sfx_fshdw","sfx_froug","sfx_fhcha","sfx_fdcha","sfx_fcrem","sfx_fe123","sfx_fblaz","sfx_fsilv","sfx_flzrd","sfx_farle","sfx_fngts","sfx_fskgk","sfx_fulal","sfx_fbeat","sfx_fvyse","sfx_faiai","sfx_fkiry","sfx_faegs","sfx_fmiku","sfx_fdoom","sfx_feuno","sfx_fhksh","sfx_fismp","sfx_fchgs","sfx_fnljb","sfx_fpwsm","sfx_fpwta","sfx_fscsa","sfx_fcrwk","sfx_fedgr","sfx_fdnhs","sfx_fhmsp","sfx_ftftw","sfx_fgrgd","sfx_fdenk","sfx_fcspj","sfx_fknkm","sfx_frdff","sfx_fzngf","sfx_fkomg","sfx_ftrok","sfx_fbwlf","sfx_fjfnr","sfx_frslr","sfx_fmhgr","sfx_ftgml","sfx_fflea","sfx_fbkrt","sfx_frkhm","sfx_fdzrc","sfx_fandr","sfx_forgc","sfx_fyhko","sfx_frmrn","sfx_fbsam","sfx_ftnam","sfx_frawk","sfx_fbkwd","sfx_fakof","sfx_fbane","sfx_frmon","sfx_falex","sfx_fdvto","sfx_fincr","sfx_frmka","sfx_fshaq")
	
--CHANGE ME
--Remember, use the internal skin name here! Not the display name. Find it in a skin's S_SKIN file in their respective package. You want the stuff after "name = "
--Format: name = soundID
gxChar.announceList = {sonic = sfx_fplay, tails = sfx_ftail, knuckles = sfx_fknux, eggman = sfx_fkegg, metalsonic = sfx_fmetr, flicky = sfx_fkflk, motobug = sfx_fmoto, amy = sfx_fkamy, mighty = sfx_fkgty, ray = sfx_fkray, espio = sfx_fespo, vector = sfx_fvect, chao = sfx_fchao, gamma = sfx_fe102, chaos = sfx_fchsz, shadow = sfx_fshdw, rouge = sfx_froug, herochao = sfx_fhcha, darkchao = sfx_fdcha, cream = sfx_fcrem, omega = sfx_fe123, blaze = sfx_fblaz, silver = sfx_fsilv, wonderboy = sfx_flzrd, arle = sfx_farle, nights = sfx_fngts, sakura = sfx_fskgk, ulala = sfx_fulal, beat = sfx_fbeat, vyse = sfx_fvyse, aiai = sfx_faiai, kiryu = sfx_fkiry, aigis = sfx_faegs, miku = sfx_fmiku, doom = sfx_fdoom, eviluno = sfx_feuno, hikarushida = sfx_fhksh, makiitoh = sfx_fismp, chugs = sfx_fchgs, jawnny = sfx_fnljb, starman = sfx_fpwsm, amazon = sfx_fpwta, stonecold = sfx_fscsa, crasherwake = sfx_fcrwk, eddyguerrero = sfx_fedgr, danhausen = sfx_fdnhs, tobeymaguire = sfx_fhmsp, taz = sfx_ftftw, grangordo = sfx_fgrgd, denkops = sfx_fdenk, chaosproject = sfx_fcspj, kinnikuman = sfx_fknkm, raidenff = sfx_frdff, zangief = sfx_fzngf, kennyomega = sfx_fkomg, therock = sfx_ftrok, beowulf = sfx_fbwlf, jimross = sfx_fjfnr, rasslor = sfx_frslr, mikehaggar = sfx_fmhgr, tmillionaire = sfx_ftgml, theflea = sfx_fflea, bookert = sfx_fbkrt, reikohinomoto = sfx_frkhm, danazane = sfx_fdzrc, andrethegiant = sfx_fandr, orangecassidy = sfx_forgc, yoshihiko = sfx_fyhko, romanreigns = sfx_frmrn, bassarmstrong = sfx_fbsam, tinaarmstrong = sfx_ftnam, rawkhawk = sfx_frawk, blackwidow = sfx_fbkwd, angelkof = sfx_fakof, bane = sfx_fbane, ramon = sfx_frmon, alex = sfx_falex, danny = sfx_fdvto, incineroar = sfx_fincr, rainbowmika = sfx_frmka, shaq = sfx_fshaq }

--Variables to make this do the thing
local announcedRaceWinner = false
local timeList = {}
local playerOrder = {}
local timeToAnnounce = nil

--CHANGE ME
--Play around with this to change when the win announcement happens!
local announceDelay = 2*TICRATE
	
--Sorts data in a table
local function spairs(t, order)
    -- collect the keys
    local keys = {}
    for k in pairs(t) do keys[#keys+1] = k end

    -- if order function given, sort by it by passing the table and keys a, b,
    -- otherwise just sort the keys 
    if order then
        table.sort(keys, function(a,b) return order(t, a, b) end)
    else
        table.sort(keys)
    end

    -- return the iterator function
    local i = 0
    return function()
        i = i + 1
        if keys[i] then
            return keys[i], t[keys[i]]
        end
    end
end

local function sortPlayers()
	local posPointer = 0
	local lastTime = 0
	playerOrder = {}
	for k,v in spairs(timeList, function(t,a,b) return tonumber(t[b]) > tonumber(t[a]) end) do
		--k = playername, v = realtime
		if lastTime == v and playerOrder[posPointer] ~= nil then
			--This is a tie
			table.insert(playerOrder[posPointer], k)
		else
			posPointer = $ + 1
			playerOrder[posPointer] = {k}	
		end		
		lastTime = v
		--print(tostring(posPointer).." - "..k)
	end
end

--Game thinker, executes once every mid race tick
local function think()
	--Assuming you only care about announcing the winner, this check stops this loop after it finds a winner to announce
	if announcedRaceWinner == false then
		for p in players.iterate do
			--Check for validity, ignore spectators
			if p.valid and p.mo ~= nil and p.mo.valid then		
				if p.exiting ~= 0 then
					--Someone stopped. Determine if winner and mark finished players.
					if timeList[p.name] == nil then
						timeList[p.name] = p.realtime
						--Sort player order
						sortPlayers()
						--Set delay
						timeToAnnounce = leveltime + announceDelay
					end		
				end
			end
		end
	end

	--If winner found, announce it
	if playerOrder[1] ~= nil and playerOrder[1][1] ~= nil and announcedRaceWinner == false and leveltime >= timeToAnnounce then
		--Set this immediately so in case of error it doesn't blow people's ears out
		announcedRaceWinner = true
		
		if G_BattleGametype() then
			--playerOrder[1] is not the player that actually won here, need to find the real winner.
			local winPlayer = nil
			local highScore = 0
			for p in players.iterate do
				if p.valid and p.mo ~= nil and p.mo.valid then
					if p.marescore > highScore then
						highScore = p.marescore --The actual in-round battle score
						winPlayer = p
					end
				end
			end
			
			if winPlayer and gxChar.announceList[winPlayer.mo.skin] then
				S_StartSound(nil, gxChar.announceList[winPlayer.mo.skin], winPlayer)
				S_StartSoundAtVolume(nil, gxChar.announceList[winPlayer.mo.skin], 200)
			end
		else
			--Have to loop through players again to find our winner
			for p in players.iterate do
				--Check if this is the player and also if there's a sound file for their skin
				if p.valid and p.mo ~= nil and p.mo.valid and playerOrder[1][1] == p.name and gxChar.announceList[p.mo.skin] ~= nil
					S_StartSound(nil, gxChar.announceList[p.mo.skin], p)
					S_StartSoundAtVolume(nil, gxChar.announceList[p.mo.skin], 200)
				end
			end
		end

	end
end
addHook("ThinkFrame", think)

--Triggers once during map change, reset variables
local function durMapChange()
	announcedRaceWinner = false
	timeList = {}
	playerOrder = {}
	timeToAnnounce = nil
end
addHook("MapChange", durMapChange)