//Super skincolor for Shadow, used on his CPU while playing Super Sonic
for i = 1, 5
	freeslot("SKINCOLOR_SUPERSHADOW" + i)
end
skincolors[SKINCOLOR_SUPERSHADOW1] = {
    name = "Super Shadow 1",
    ramp = {32, 33, 35, 33, 32, 210, 209, 0, 0, 0, 80, 80, 81, 81, 82, 82},
    accessible = false
}
skincolors[SKINCOLOR_SUPERSHADOW2] = {
    name = "Super Shadow 2",
    ramp = {32, 33, 35, 37, 35, 33, 50, 82, 84, 84, 84, 84, 85, 86, 87, 245},
    accessible = false
}
skincolors[SKINCOLOR_SUPERSHADOW3] = {
    name = "Super Shadow 3",
    ramp = {32, 33, 35, 37, 39, 37, 55, 84, 84, 84, 85, 86, 87, 245, 247, 249},
    accessible = false
}
skincolors[SKINCOLOR_SUPERSHADOW4] = {
    name = "Super Shadow 4",
    ramp = {32, 33, 35, 37, 39, 39, 56, 84, 85, 86, 87, 245, 247, 249, 251, 237},
    accessible = false
}
skincolors[SKINCOLOR_SUPERSHADOW5] = {
    name = "Super Shadow 5",
    ramp = {32, 33, 35, 37, 39, 41, 214, 86, 87, 245, 247, 249, 251, 237, 239, 239},
    accessible = false
}

//Super colors for specific CPUs
/*
If you want to make support in your own mod, just take the first uncommented
line below, and define your own character's skincolor.

If you don't want to use Lua and your character uses a super color other than
gold, you can also define "supercolor = color" in your S_SKIN, which Ashura
does. Only custom super colors and super colors from SRB2 2.2 are valid.
https://wiki.srb2.org/wiki/List_of_skin_colors#Super_skin_colors
*/
if not SUPER_CPUS then rawset(_G, "SUPER_CPUS", {}) end

SUPER_CPUS["shadow"] = SKINCOLOR_SUPERSHADOW1
SUPER_CPUS["silver"] = SKINCOLOR_SUPERTAN1
SUPER_CPUS["knuckles"] = SKINCOLOR_SUPERRED1
SUPER_CPUS["tails"] = SKINCOLOR_SUPERORANGE1
SUPER_CPUS["amy"] = SKINCOLOR_SUPERRED1
SUPER_CPUS["mighty"] = SKINCOLOR_SUPERRED1
SUPER_CPUS["ray"] = SKINCOLOR_SUPERGOLD1
SUPER_CPUS["metalsonic"] = SKINCOLOR_SUPERRUST1
SUPER_CPUS["mechasonic"] = SKINCOLOR_SUPERRUST1

SUPER_CPUS["sonic"] = SKINCOLOR_SUPERSKY1 //Bro who is this guy

//Skins this code applies to
local SUPER_SKIN = "supersonic"
local BASE_SKIN = "sonic"

local HYPER_COLOR = SKINCOLOR_WHITE
local SPECIAL_COLORS = {
	[HYPER_COLOR] = SKINCOLOR_MIDNIGHT,
	[SKINCOLOR_YELLOW] = SKINCOLOR_BLUE,
	//[SKINCOLOR_MUSTARD] = SKINCOLOR_JET,
	//[SKINCOLOR_BANANA] = SKINCOLOR_NAVY,
	//[SKINCOLOR_KETCHUP] = SKINCOLOR_BLUEBERRY
}
local TRANS_TIME = TICRATE*3/2 + 1

//Get the color for Super Sonic's base form
//Special colors swap their opposites so each color has a unique opposite
local function GetBaseFormColor(color)
	//Prefcolor
	if color == skins[SUPER_SKIN].prefcolor
		return skins[BASE_SKIN].prefcolor
	elseif color == ColorOpposite(skins[BASE_SKIN].prefcolor)
		return ColorOpposite(skins[SUPER_SKIN].prefcolor)
		
	//All other colors
	else
		for pref, opposite in pairs(SPECIAL_COLORS)
			if color == pref
				return opposite
			elseif color == ColorOpposite(opposite)
				return ColorOpposite(pref)
			end
		end
		return ColorOpposite(color)
	end
end

//Spawn the ghost used to transition between super and base form
local function SpawnSuperGhost(player, dosound)
	if leveltime < 2 then return end
	local mo = player.mo
	
	if dosound and leveltime > TRANS_TIME + #player
		S_StartSound(mo, sfx_s3k9f)
	end
	
	local ghost = P_SpawnGhostMobj(mo)
	ghost.type = MT_OVERLAY
	ghost.fuse = $ >> 1
end

//Gotta be alive and have rings to be super!
local function IsSuper(player, nodead)
	local mo = player.mo
	return ((mo.health and (player.rings > 0 or gametyperules & GTR_SPHERES))
	//or player.exiting
	or (not nodead and not mo.health and player.deadtimer <= TICRATE/4))
	and (leveltime >= TRANS_TIME + #player or player.bot)
end

//Do super effects
local function DoSuperEffects(player)
	local mo = player.mo
	if mo.eflags & RF_DONTDRAW or not mo.sprite or player.spectator then return end
	
	//Fullbright!
	mo.frame = $ | FF_FULLBRIGHT
	
	//Sparkle Trail
	if not player.invincibilitytimer
		K_SpawnSparkleTrail(mo)
	end
end

//Do super transformation animation
local function DoTransformAnimation(player)
	if leveltime > TRANS_TIME + #player or player.spectator
	or player.canbesupersonic != true then return end
	local mo = player.mo
	
	//Spawn emeralds
	if leveltime == #player + 1 and not mo.animationemeralds
		mo.animationemeralds = {}
		for i = 0, 6
			local angle = ANGLE_180/7*2*i
			local emerald = P_SpawnMobjFromMobj(mo,
			P_ReturnThrustX(mo, angle, mo.info.radius),
			P_ReturnThrustY(mo, angle, mo.info.radius),
			0, MT_EMERALD)
			emerald.target = mo
			
			emerald.extravalue1 = 0
			emerald.color = SKINCOLOR_CHAOSEMERALD1 + i
			
			if player.skincolor == HYPER_COLOR
				emerald.state = S_SUPEREMERALD1
			end
			
			mo.animationemeralds[i] = emerald
		end
		
	//Reset emerald table
	elseif leveltime == TRANS_TIME + #player
		mo.animationemeralds = nil
		
	//Start transformation sound
	elseif leveltime == TRANS_TIME*4/5 + #player
		S_StartSound(mo, sfx_s25f)
		
	//Speed up emerald animation
	elseif mo.animationemeralds and leveltime < TRANS_TIME*2/3 + #player
		for i = 0, 6
			local emerald = mo.animationemeralds[i]
			if emerald and emerald.valid
				local ratio = (emerald.fuse * FRACUNIT) / emerald.threshold
				emerald.threshold = $ - 1
				emerald.fuse = max(1, (emerald.threshold * ratio) / FRACUNIT)
			end
		end
	end
	
	local collectsound = mobjinfo[MT_EMERALD].deathsound
	if S_SoundPlaying(mo, collectsound) then S_StopSoundByID(mo, collectsound) end
end

//Swap between Sonic and Super Sonic, without changing player.skin or stats
local function SetSuperSkin(player)
	local mo = player.mo
	mo.skin = ($ == SUPER_SKIN) and BASE_SKIN or SUPER_SKIN
	mo.frame = $ &~ FF_FRAMEMASK
end

local SUPER_SKINVOICES = {
	SKSKWIN,
	SKSKLOSE,
	SKSKPAN1,
	SKSKPAN2,
	SKSKATK1,
	SKSKATK2,
	SKSKBST1,
	SKSKBST2,
	SKSKSLOW,
	SKSKHITM,
	SKSKPOWR,
	SKSKTALK
}

local SUPER_SKINSFX

//Make sure Super Sonic gets his correct signpost visuals

//Keep the old signpost action in reserves
local SuperOldSignAction = states[S_KART_SIGN].action or A_PlaySeeSound

//Make the signpost show base Sonic or Hyper Sonic where appropriate
function A_SuperSignpost(mobj, var1, var2)
	SuperOldSignAction(mobj, var1, var2) //Perform the old signpost action
	
	//We need to be a Super Sonic
	if mobj.skin != SUPER_SKIN then return end
	
	//Use base form on the sign when detransformed!
	local player = mobj.target
	player = $ and $.valid and $.target
	player = $ and $.valid and $.player
	
	if not IsSuper(player)
		mobj.frame = $ &~ FF_FRAMEMASK
		mobj.skin = BASE_SKIN
		mobj.color = GetBaseFormColor(player.skincolor)
		
	//Properly animate hyper color
	elseif player.skincolor == HYPER_COLOR and not player.mfdfinish
		mobj.color = SKINCOLOR_SKUNK + ((mobj.frame >> 1) % 5)
		
		//Loop the state so we can update the color still
		mobj.frame = $ &~ FF_ANIMATE
		mobj.tics = 1
	end
end

//Assign our new action to the signpost state
states[S_KART_SIGN].action = A_SuperSignpost
states[S_KART_SIGN].nextstate = $ or S_KART_SIGN //Allow looping the state

addHook("MapLoad", do for player in players.iterate
	//Can we be Super Sonic?
	player.canbesupersonic = skins[player.skin].name == SUPER_SKIN
	or skins[player.skin].flags & SF_IRONMAN
	
	//Can we be a Super bot?
	if not netgame and player.bot and consoleplayer
	and skins[consoleplayer.skin].name == SUPER_SKIN
		local color = SUPER_CPUS[skins[player.skin].name]
		if not color
			color = skins[player.skin].supercolor
			if color == SKINCOLOR_SUPERGOLD1 then color = nil end
		end
		player.canbesupercolor = color
	elseif player.canbesupercolor
		player.canbesupercolor = nil
	end
end end)

//Main Thinker
local SuperSonicThinker = function()
	for player in players.iterate
		local mo = player.mo
		if not (player.canbesupersonic and mo and mo.valid) then continue end
		
		//Do transformation animation
		DoTransformAnimation(player)
		
		//Super Sonic specific logic
		if mo.skin == SUPER_SKIN
			//Make sure the super glow stays consistent across animations
			if mo.superframe and mo.superspr2 != mo.sprite2
			and mo.sprite == SPR_PLAY
				local numframes = skins[mo.skin].sprites[mo.sprite2 or 1].numframes
				if (mo.frame & FF_FRAMEMASK) >= numframes
					mo.frame = ($ &~ FF_FRAMEMASK) | (mo.superframe % numframes)
				else
					mo.frame = ($ &~ FF_FRAMEMASK) | mo.superframe
				end
			end
			mo.superspr2 = mo.sprite2
			mo.superframe = mo.frame & FF_FRAMEMASK
			
			//Hyper color
			if player.skincolor == HYPER_COLOR
			and (mo.color == player.skincolor
			or (mo.color >= SKINCOLOR_SKUNK
			and mo.color < SKINCOLOR_SKUNK + 5))
				mo.color = SKINCOLOR_SKUNK + ((mo.frame >> 1) % 5)
			end
			
			//Gotta be alive and have rings to be super!
			if IsSuper(player)
				DoSuperEffects(player)
			
			//Detransform
			else
				SpawnSuperGhost(player)
				SetSuperSkin(player)
			end
			
		//Detransformed into Sonic
		elseif mo.skin == BASE_SKIN and (player.canbesupersonic != SF_IRONMAN
		or (player.fakeskin <= #skins and skins[player.fakeskin].name == SUPER_SKIN))
			//Retransform!
			if IsSuper(player, true)
				SpawnSuperGhost(player, true)
				
				SetSuperSkin(player)
				if mo.color == GetBaseFormColor(player.skincolor)
					mo.color = player.skincolor
				end
				
			//Base Sonic gets the player's opposite color
			elseif mo.color == player.skincolor
			or (player.skincolor == HYPER_COLOR
			and mo.color >= SKINCOLOR_SKUNK
			and mo.color < SKINCOLOR_SKUNK + 5)
				mo.color = GetBaseFormColor(player.skincolor)
			end
			
			//Replace Sonic's voice clips with the correct ones
			if player.canbesupersonic == SF_IRONMAN then continue end
			
			if SUPER_SKINSFX
				for sound, voice in pairs(SUPER_SKINSFX)
					if S_SoundPlaying(mo, sound)
						S_StopSoundByID(mo, sound)
						S_StartSound(mo, voice)
						break
					end
				end
			else
				local skin = skins[player.skin]
				local moskin = skins[mo.skin]
				SUPER_SKINSFX = {}
				
				for i, voice in ipairs(SUPER_SKINVOICES)
					local sound = skin.soundsid[voice]
					SUPER_SKINSFX[sound] = moskin.soundsid[voice]
				end
			end
		end
	end
end

//Thinker for bots!
local SuperBotThinker = function()
	for player in players.iterate
		local color = player.canbesupercolor
		local mo = player.mo
		if not (color and mo and mo.valid) then continue end
		
		//Gotta be alive and have rings to be super!
		if color and IsSuper(player)
			if not player.cpuwassuper
				if player.cpuwassuper != nil
					SpawnSuperGhost(player, true)
				end
				player.cpuwassuper = true
			end
			
			//Super color
			if mo.color == player.skincolor
			or (mo.color >= color
			and mo.color < color + 5)
				mo.color = color + abs( ( (leveltime >> 1) % 9) - 4)
			end
			DoSuperEffects(player)
			
		//Detransform
		elseif player.cpuwassuper
			player.cpuwassuper = false
			
			if color
				SpawnSuperGhost(player)
				mo.frame = $ &~ FF_FULLBRIGHT
				if mo.color >= color
				and mo.color < color + 5
					mo.color = player.skincolor
				end
			end
		end
	end
end
		
//Add the above functions into a hook!
addHook("PostThinkFrame", do
	SuperBotThinker()
	SuperSonicThinker()
end)