//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 = player.superghost
	if ghost and ghost.valid
		P_RemoveMobj(ghost)
	end
	ghost = P_SpawnGhostMobj(mo)
	ghost.dispoffset = mo.dispoffset + 1
	
	player.superghost = ghost
	return ghost
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 skins[player.skin].flags & SF_IRONMAN 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
}

//Make sure Super Sonic gets his correct signpost visuals
addHook("MobjThinker", function(mobj)
	local mo = mobj.target
	local player = mo and mo.valid and mo.player
	if not (player and (mo.skin == SUPER_SKIN or mo.skin == BASE_SKIN)) then return end
	
	local part = mobj.hnext
	while part and part.valid
		if (part.state == S_KART_SIGN or part.state == S_KART_SIGL)
		and part.skin == SUPER_SKIN
			//Use base form on the sign when detransformed!
			if not IsSuper(player)
				part.skin = BASE_SKIN
				part.color = GetBaseFormColor(player.skincolor)
				
			//Properly animate hyper color
			elseif player.skincolor == HYPER_COLOR
				part.color = SKINCOLOR_SKUNK + ((part.frame >> 1) % 5)
			end
			break
		end
		part = $.hnext
	end
end, MT_SIGN)

//Main Thinker
addHook("PostThinkFrame", do for player in players.iterate
	local mo = player.mo
	if not (mo and mo.valid) then continue end
	
	//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
			mo.frame = ($ &~ FF_FRAMEMASK) | (mo.superframe % numframes)
		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
		DoTransformAnimation(player)
		
	//Detransformed into Sonic
	elseif mo.skin == BASE_SKIN
	and (skins[player.skin].name == SUPER_SKIN
	or (player.fakeskin <= #skins and skins[player.skin].flags & SF_IRONMAN
	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
		DoTransformAnimation(player)
		
		//Replace Sonic's voice clips with the correct ones
		local skin = skins[player.skin]
		if skin.name == SUPER_SKIN
			local moskin = skins[mo.skin]
			for i, voice in ipairs(SUPER_SKINVOICES)
				local sound = skin.soundsid[voice]
				if S_SoundPlaying(mo, sound)
					S_StopSoundByID(mo, sound)
					S_StartSound(mo, moskin.soundsid[voice])
				end
			end
		end
	
	//Not Super or Sonic
	else
		//Give certain CPUs a super glow
		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
			
			//Gotta be alive and have rings to be super!
			if color and IsSuper(player)
				if not player.cpuwassuper
					SpawnSuperGhost(player, true)
					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
			
		//Not Super!
		elseif player.cpuwassuper
			player.cpuwassuper = false
		end
	end
	
	//Handle super ghost
	local ghost = player.superghost
	if ghost and ghost.valid
		local oldhealth = mo.health
		mo.health = 1
		A_CapeChase(ghost)
		mo.health = oldhealth
	end
end end)