local spawnx = 0
local spawny = 0
local spawnz = 0
local spawnangle = 0
local spawndrawangle = 0

freeslot("sfx_ringtk",
"MT_SUPERWARP",
"S_SUPERWARP",
"SPR_WARP",
"MT_SUPERBOLT")
sfxinfo[sfx_ringtk].caption = "Got Token"
states[S_SUPERWARP] = {SPR_WARP, A|FF_ANIMATE|FF_FULLBRIGHT, 7, nil, 7, 1, S_NULL}

mobjinfo[MT_SUPERWARP] = {
	spawnstate = S_SUPERWARP,
	spawnhealth = 1,
    deathstate = S_NULL,
    speed = FRACUNIT,
    radius = FRACUNIT,
    height = FRACUNIT,
	flags = MF_SCENERY|MF_NOGRAVITY|MF_NOCLIPTHING
}

addHook("NetVars", function(network)
	spawnx = network($)
	spawny = network($)
	spawnz = network($)
	spawnangle = network($)
	spawndrawangle = network($)
end)

addHook("MapLoad", function()
	for player in players.iterate
		spawnx = player.mo.x
		spawny = player.mo.y
		spawnz = player.mo.z
		spawnangle = player.mo.angle
		spawndrawangle = player.drawangle
	end
end)

addHook("ThinkFrame", do
	for player in players.iterate
		if player.mo and player.mo.valid
			if not player.mo.storedrings
				player.mo.storedrings = 0
			end
			if not player.mo.signpost
				player.mo.signpost = 0
			end
			if not player.mo.storedmusicpos
				player.mo.storedmusicpos = 0
			end
			if not player.mo.got1up
				player.mo.got1up = 0
			end
			if not player.mo.issuper
				player.mo.issuper = false
			end
			if not player.mo.switchtimer
				player.mo.switchtimer = 0
			end
			if not player.mo.shoespower
				player.mo.shoespower = false
			end
			if not player.mo.shoestats
				player.mo.shoestats = false
			end
			if not player.mo.sparklespower
				player.mo.sparklespower = false
			end
			if player.mo and player.mo.valid
			and player.powers[pw_extralife]
				player.mo.got1up = true
			else
				if player.mo.got1up == true
					S_SetMusicPosition(player.mo.storedmusicpos)
					S_SetInternalMusicVolume(0, player)
					S_FadeMusic(100, MUSICRATE, player)
					player.mo.got1up = false
				end
				player.mo.storedmusicpos = S_GetMusicPosition()
			end
			if player.mo.skin == "supersonic"
				if player.mo.switchtimer < 2
					player.mo.switchtimer = $ + 1
				end
				if player.mo.issuper == false
					player.mo.issuper = true
				end
				player.shieldscale = 0
			end
			if player.mo and player.mo.valid
			and player.mo.skin ~= "supersonic"
			and player.mo.issuper == true
				player.powers[pw_super] = 0
				player.mo.color = player.skincolor
				player.mo.state = $
				player.shieldscale = skins[player.mo.skin].shieldscale
				P_SpawnShieldOrb(player)
				player.mo.issuper = false
				player.mo.switchtimer = 0
			end
			if S_MusicName() == "_super"
			and player.mo.issuper == false
				P_RestoreMusic(player)
			end
			if player.mo and player.mo.valid and player.mo.skin == "supersonic"
				player.mo.frame = $|FF_FULLBRIGHT
				if player.rings < 1
				and not netgame
					P_DamageMobj(player.mo, nil, nil, 0, DMG_INSTAKILL)
				end
				if netgame
					if player.rings < 1
					and player.mo.switchtimer >= 2
					and player.playerstate == PST_LIVE
						player.powers[pw_carry] = CR_NONE
						player.pflags = player.pflags & ~(PF_JUMPED | PF_SPINNING | PF_STARTDASH | PF_THOKKED | PF_SHIELDABILITY | PF_GLIDING | PF_BOUNCING | PF_SLIDING)
						player.mo.momx = 0
						player.mo.momy = 0
						player.mo.momz = 0
						if not player.starpostnum
							player.mo.angle = spawnangle
							player.drawangle = spawndrawangle
						else
							player.mo.angle = player.starpostangle
							player.drawangle = player.starpostangle
						end
						player.mo.state = S_PLAY_STND
						player.mo.flags2 = player.mo.flags2 & ~MF2_TWOD
						player.mo.flags2 = player.mo.flags2 & ~MF2_OBJECTFLIP
						if not player.starpostnum
							P_TeleportMove(player.mo, spawnx, spawny, spawnz)
						else
							P_TeleportMove(player.mo, player.starpostx*FRACUNIT, player.starposty*FRACUNIT, player.starpostz*FRACUNIT)
						end
						S_StartSound(player.mo, sfx_s3kb3)
						P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_SUPERWARP)
						player.rings = 25
					end
					if not All7Emeralds(emeralds)
						R_SetPlayerSkin(player, "sonic")
						S_StartSound(player.mo, sfx_lose)
						if P_RandomChance(FRACUNIT/100*50)
							CONS_Printf(player, "\x85"+"You need all 7 Chaos Emeralds before using Super Sonic!")
						elseif P_RandomChance(FRACUNIT/100*30)
							CONS_Printf(player, "\x85"+"You must first collect all 7 gems of the chaotic variety.")
						elseif P_RandomChance(FRACUNIT/100*50)
							CONS_Printf(player, "\x85"+"Maybe collect all of those emeralds first!")
						elseif P_RandomChance(FRACUNIT/100*40)
							CONS_Printf(player, "\x85"+"He's named SUPER Sonic for a reason!")
						elseif P_RandomChance(FRACUNIT/100*30)
							CONS_Printf(player, "\x85"+"Did you get all of those Chaos Emeralds?")
						elseif P_RandomChance(FRACUNIT/100*30)
							CONS_Printf(player, "\x85"+"get all of them magic poprocks, my dude")
						elseif P_RandomChance(FRACUNIT/100*40)
							CONS_Printf(player, "\x85"+"I hope you didn't expect to go super without those Chaos Emeralds!")
						end
					end
				end
				if player.playerstate == PST_LIVE and player.lives > 0 and player.spectator == false and not netgame and All7Emeralds(emeralds) == false then
					emeralds = $ | EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7
				end
				if not player.powers[pw_super]
				and not player.exiting
					player.powers[pw_super] = 1
				end
				if player.powers[pw_sneakers] > 10*TICRATE
					player.powers[pw_sneakers] = 10*TICRATE
					player.mo.shoespower = true
					S_StartSound(player.mo, sfx_s3k9f)
				elseif not player.powers[pw_sneakers]
				and player.mo.shoespower == true
					player.mo.shoespower = false
					player.mo.shoestats = false
					S_StartSound(player.mo, sfx_kc65)
				end
				if player.powers[pw_invulnerability] > 10*TICRATE
					player.powers[pw_invulnerability] = 10*TICRATE
					player.mo.sparklespower = true
					S_StartSound(player.mo, sfx_s3k46)
				elseif not player.powers[pw_invulnerability]
				and player.mo.sparklespower == true
					player.mo.sparklespower = false
					S_StartSound(player.mo, sfx_kc65)
				end
				if player.mo.shoespower
					player.mo.shoestats = true
					if leveltime % 1 == 0
						local superbolt = P_SpawnMobjFromMobj(player.mo, FRACUNIT*P_RandomRange(-16,16), FRACUNIT*P_RandomRange(-16,16), FixedDiv(player.mo.height/2,player.mo.scale)+(P_RandomRange(-16,16)*FRACUNIT), MT_SUPERBOLT)
						//superbolt.momz = FixedMul(FRACUNIT*2, player.mo.scale)*P_MobjFlip(player.mo)
						superbolt.scale = player.mo.scale
						superbolt.colorized = true
						superbolt.color = SKINCOLOR_SKY
						superbolt.frame = $|FF_FULLBRIGHT
						superbolt.target = player.mo
						if superbolt.target.player == displayplayer
							local chasecam = CV_FindVar("chasecam")
							if (chasecam.value == 1)
								superbolt.flags2 = $ & ~MF2_DONTDRAW
							elseif (chasecam.value == 0)
								superbolt.flags2 = $ | MF2_DONTDRAW
							end
						end
					end
					local ghost1 = P_SpawnGhostMobj(player.mo)
					ghost1.color = player.mo.color
					if player.mo.colorized
						ghost1.colorized = true
					else
						ghost1.colorized = false
					end
					ghost1.rollangle = player.mo.rollangle
					ghost1.fuse = 4
					ghost1.eflags = player.mo.eflags & MFE_VERTICALFLIP
					ghost1.source = player.mo
					if ghost1.source.player == displayplayer
						local chasecam = CV_FindVar("chasecam")
						if (chasecam.value == 1)
							ghost1.flags2 = $ & ~MF2_DONTDRAW
						elseif (chasecam.value == 0)
							ghost1.flags2 = $ | MF2_DONTDRAW
						end
					end
					player.normalspeed = 54*FRACUNIT
					player.actionspd = 90*FRACUNIT
				end
				if not player.mo.shoestats
					player.normalspeed = 36*FRACUNIT
					player.actionspd = 60*FRACUNIT
				end
				if (netgame and (player.pflags & PF_FINISHED or player.powers[pw_carry] == CR_MINECART))
				or player.mo.sparklespower
					if not player.mo.storedrings
					or player.rings > player.mo.storedrings
						player.mo.storedrings = player.rings
					end
					if player.rings < player.mo.storedrings
						player.rings = player.mo.storedrings
					end
				else
					player.mo.storedrings = 0
				end
			end
		end
	end
end)

//Give the player 25 Rings if they pick up an Emerald Token, and kill them if they hit 0 rings.
addHook("PlayerThink", function(player)
	if player.mo and player.mo.valid and player.mo.skin == "supersonic"
		player.mo.color = player.skincolor
	end
	if player.mo and player.mo.valid
	and player.mo.ringtokengrabbed
		P_GivePlayerRings(player, 25)
		P_AddPlayerScore(player, 1000)
		S_StartSound(player.mo, sfx_ringtk)
		player.mo.ringtokengrabbed = false
	end
end)

addHook("TouchSpecial", function(emeraldtoken, mo)
	if All7Emeralds(emeralds)
	and mo.skin == "supersonic"
		if not emeraldtoken.grabbed then
			mo.ringtokengrabbed = true
			emeraldtoken.grabbed = true
			P_KillMobj(emeraldtoken)
			return true
		end
	elseif not All7Emeralds(emeralds)
		return false
	end
end, MT_TOKEN)

//Making it so you start with 25 rings and am super upon spawn.
addHook("PlayerSpawn", function(player)
	if player.mo and player.mo.valid and player.mo.skin == "supersonic"
		P_GivePlayerRings(player, 25)
		player.mo.state = $
	end
end)
		
addHook("MobjDamage", function(target, inflictor, source)
	if inflictor and inflictor.valid and inflictor.type == MT_PLAYER
		local issuper = false
		for player in players.iterate
			if player.mo and player.mo.valid
			and player.mo.skin == "supersonic"
				issuper = true
			end
		end
		if issuper
			if target.flags & MF_BOSS
				for player in players.iterate
					if target.type == MT_METALSONIC_BATTLE
						P_GivePlayerRings(player, 10)
					else
						P_GivePlayerRings(player, 5)
					end
				end
				S_StartSoundAtVolume(target.mo, sfx_kc5e, 105)
			end
			if target.flags & MF_ENEMY
			and issuper
			and inflictor.skin == "supersonic" --Double checking since the 'issuper' check isn't enough, apparently.
				P_GivePlayerRings(inflictor.player, 2)
				S_StartSoundAtVolume(inflictor, sfx_kc5d, 105)
			end
		end
	end
end)

addHook("ShouldDamage", function(target, inflictor, source, damage, damagetype)
    if target and target.valid and target.skin == "supersonic"
	and netgame
	and target.player.rings == 0
	and not (damagetype & DMG_DEATHMASK)
        return false
	end
end)

addHook("MobjThinker", function(sign)
	if sign.tracer.tracer  --tracers of tracers are dumb.
		if sign.tracer.tracer.skin == "supersonic"
			sign.tracer.tracer.tics = -1
			sign.tracer.tracer.frame = ((leveltime / 7) % 4) | (FF_FULLBRIGHT|FF_PAPERSPRITE)
		end
	end
end, MT_SIGN)

//Ring Attraction function based upon P_Attract from source.
local function SuperAttract(source, dest)
	local dist = 0
	local ndist = 0
	local speedmul = 0
	local tx = dest.x
	local ty = dest.y
	local tz = dest.z + (dest.height/2)
	local xydist = P_AproxDistance(tx - source.x, ty - source.y)
	if dest and dest.health and dest.valid and dest.type == MT_PLAYER
		source.angle = R_PointToAngle2(source.x, source.y, tx, ty)
		dist = P_AproxDistance(xydist, tz - source.z)
		if (dist < 1)
			dist = 1
		end
		speedmul = P_AproxDistance(dest.momx, dest.momy) + FixedMul(source.info.speed, source.scale)
		source.momx = FixedMul(FixedDiv(tx - source.x, dist), speedmul)
		source.momy = FixedMul(FixedDiv(ty - source.y, dist), speedmul)
		source.momz = FixedMul(FixedDiv(tz - source.z, dist), speedmul)
		ndist = P_AproxDistance(P_AproxDistance(tx - (source.x + source.momx), ty - (source.y+source.momy)), tz - (source.z+source.momz))
		if (ndist > dist)
			source.momx = 0
			source.momy = 0
			source.momz = 0
			P_TeleportMove(source, tx, ty, tz)
		end
	end
end

addHook("MobjThinker", function(ring)
    if ring and ring.valid and ring.health > 0
        local soup
        for p in players.iterate
            if p.mo and p.mo.valid and p.mo.skin == "supersonic" and R_PointToDist2(p.mo.x, p.mo.y, ring.x, ring.y) <= (RING_DIST/6) and abs(ring.z - p.mo.z) < (RING_DIST/6)
                soup = p.mo
            end
        end
        if soup
            local momRing = P_SpawnMobjFromMobj(ring, 0,0,0, MT_FLINGRING)
            momRing.followmo = soup
            P_RemoveMobj(ring)
        end
    end
end, MT_RING)

addHook("MobjThinker", function(ring)
    if ring and ring.valid and ring.health > 0 and ring.followmo and ring.followmo.valid
        if R_PointToDist2(ring.followmo.x, ring.followmo.y, ring.x, ring.y) <= RING_DIST/3 and abs(ring.z - ring.followmo.z) < RING_DIST/3
			SuperAttract(ring, ring.followmo)
        else
            ring.fuse = 5*TICRATE
        end
        if ring.fuse == 2
            P_SpawnMobjFromMobj(ring, 0,0,0, MT_RING)
            P_RemoveMobj(ring)
        end
    end
end, MT_FLINGRING)

addHook("MobjCollide", function(spike, plmo)
    if not (plmo and plmo.valid and plmo.skin == "supersonic") then return end
    if plmo.type ~= MT_PLAYER then return end
    if plmo.z + plmo.height < spike.z or spike.z + spike.height < plmo.z then return end
    local player = plmo.player
    if player.mo.shoespower
        P_KillMobj(spike, plmo, plmo)
    end
end, MT_SPIKE)

addHook("MobjCollide", function(spike, plmo)
    if not (plmo and plmo.valid and plmo.skin == "supersonic") then return end
    if plmo.type ~= MT_PLAYER then return end
    if (plmo.z > spike.z+spike.height*4) or (spike.z > plmo.z+plmo.height*2) then return end
    local player = plmo.player
	if player.mo.shoespower
        P_KillMobj(spike, plmo, plmo)
    end
end, MT_WALLSPIKE)