local smscolors = {
    ['crisis'] = {SKINCOLOR_CRIMSON, SKINCOLOR_RED, SKINCOLOR_FLAME, SKINCOLOR_KETCHUP, SKINCOLOR_SUPERORANGE5},
    ['antimatter'] = {SKINCOLOR_CARBON, SKINCOLOR_BLACK, SKINCOLOR_JET, SKINCOLOR_SILVER, SKINCOLOR_GREY},
    ['priest'] = {SKINCOLOR_GREY, SKINCOLOR_SILVER, SKINCOLOR_SUPERSILVER5, SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERSILVER1},
    ['bluewave'] = {SKINCOLOR_COBALT, SKINCOLOR_BLUE, SKINCOLOR_CORNFLOWER, SKINCOLOR_BLUEBELL, SKINCOLOR_AZURE},
    ['arcticchi'] = {SKINCOLOR_ICY, SKINCOLOR_AETHER, SKINCOLOR_BONE, SKINCOLOR_WHITE, SKINCOLOR_SUPERSILVER5},
    ['ranger'] = {SKINCOLOR_FOREST, SKINCOLOR_GREEN, SKINCOLOR_PERIDOT, SKINCOLOR_SUPERPERIDOT5, SKINCOLOR_SUPERPERIDOT2},
    ['pinkmenace'] = {SKINCOLOR_VIOLET, SKINCOLOR_LILAC, SKINCOLOR_ROSY, SKINCOLOR_PINK, SKINCOLOR_BUBBLEGUM},
    ['metallic'] = {SKINCOLOR_SUPERRUST5, SKINCOLOR_SUPERRUST4, SKINCOLOR_COPPER, SKINCOLOR_SUNSET, SKINCOLOR_GOLD},
    ['hazelglow'] = {SKINCOLOR_BLACK, SKINCOLOR_CARBON, SKINCOLOR_BRONZE, SKINCOLOR_BROWN, SKINCOLOR_BEIGE},
    ['ultradrive'] = {SKINCOLOR_BONE, SKINCOLOR_WHITE, SKINCOLOR_SUPERSILVER3, SKINCOLOR_SUPERSILVER2, SKINCOLOR_SUPERSILVER1},
    ['lapisvapor'] = {SKINCOLOR_DUSK, SKINCOLOR_CERULEAN, SKINCOLOR_BLUE, SKINCOLOR_SAPPHIRE, SKINCOLOR_BLUEBELL},
    ['azurebreaker'] = {SKINCOLOR_WAVE, SKINCOLOR_AZURE, SKINCOLOR_TEAL, SKINCOLOR_AQUA, SKINCOLOR_MOSS}
}
	
COM_AddCommand("supercolor", function(p, str)
    if not (p and p.mo and p.mo.valid) then
        CONS_Printf(p, "You must be in a level to use this.")
        return
    end
	if not str then
		if p.scolorstring == nil
			CONS_Printf(p,"supercolor [argument] - This command will change your super color. Use 'list' as an argument to see what colors you can use!")
		else
			CONS_Printf(p,"supercolor [argument] - This command will change your super color. Use 'list' as an argument to see what colors you can use!")
		end
	return end

	str = $:lower()
	
	if str == "list"
		CONS_Printf(p,
		"\n" ..
		"List of valid Super Colors are:\n" ..
		"\n" ..
		"Base Game Super Colors\n" ..
		"----------------\n" ..
		"\x85"+"Red," ..
		"\x87"+"Orange," ..
		"\x82"+"Gold," ..
		"\x8B"+"Peridot," ..
		"\x88"+"Sky,\n" ..
		"\x89"+"Purple," ..
		"\x87"+"Rust," ..
		"\x8D"+"Tan," ..
		"\x86"+"Silver\n" ..
		"\n" ..
		"\x80"+"Extra Super Colors\n" ..
		"------------\n" ..
		"\x83"+"Mint," ..
		"\x81"+"Bubblegum," ..
		"\x84"+"Sapphire," ..
		"\x88"+"Wave," ..
		"\x87"+"Copper,\n" ..
		"\x85"+"Ruby," ..
		"\x80"+"Aether," ..
		"\x85"+"Burning," ..
		"\x83"+"Emerald," ..
		"\x89"+"Lavender,\n" ..
		"\x8E"+"Rosy," ..
		"\x81"+"Raspberry," ..
		"\x84"+"Dark," ..
		"\x8D"+"Brown," ..
		"\x81"+"Magenta,\n" ..
		"\x89"+"PurpleRust," ..
		"\x85"+"Red"+"\x82"+"Gold," ..
		"\x8E"+"RoseGold," ..
		"\x84"+"Cobalt," ..
		"\x87"+"Sunset,\n" ..
		"\x80"+"Slate," ..
		"\x86"+"Jet," ..
		"\x8B"+"Lime," ..
		"\x8A"+"Wind," ..
		"\x87"+"Pseudo,\n" ..
		"\x82"+"Topaz," ..
		"\x88"+"Aquatic," ..
		"\x82"+"Yellow," ..
		"\x89"+"Grape," ..
		"\x82"+"Lemon,\n" ..
		"\x89"+"Amethyst," ..
		"\x8A"+"Prismarine," ..
		"\x86"+"Chrome," ..
		"\x88"+"Ve"+"\x8C"+"rgl"+"\x88"+"as," ..
		"\x81"+"Wine,\n" ..
		"\x89"+"Abyssal," ..
		"\x83"+"To"+"\x86"+"x"+"\x83"+"in," ..
		"\x87"+"Volcanic," ..
		"\x85"+"Radish," ..
		"\x89"+"Singer,\n" ..
		"\x85"+"Divine," ..
		"\x8B"+"Pear," ..
		"\x8E"+"Ph"+"\x86"+"ant"+"\x8E"+"om," ..
		"\x82"+"T"+"\x8B"+"e"+"\x83"+"r"+"\x8A"+"r"+"\x88"+"a"+"\x8C"+"r"+"\x84"+"i"+"\x89"+"a," ..
		"\x8C"+"Shimmering,\n" ..
		"\x85"+"Ce"+"\x8E"+"les"+"\x88"+"te," ..
		"\x8C"+"Ku"+"\x86"+"r"+"\x8C"+"ai," ..
		"\x8E"+"Beta"+"\x87"+"carotene," ..
		"\x89"+"Hallowed," ..
		"\x8E"+"Unlimited,\n" ..
		"\x83"+"Slayer," ..
		"\x82"+"Radiance," ..
		"\x87"+"Discovery," ..
		"\x85"+"Redemption," ..
		"\x8E"+"Lovestruck,\n" ..
		"\x83"+"Vortex," ..
		"\x88"+"Virtua," ..
		"\x82"+"Lightning," ..
		"\x8C"+"Spec"+"\x85"+"trum," ..
		"\x82"+"Lemon"+"\x83"+"Lime,\n" ..
		"\x83"+"Festive," ..
		"\x89"+"Void"+"\x86"+"Reborn," ..
		"\x86"+"Brim"+"\x85"+"stone," ..
		"\x83"+"Xeno"+"\x86"+"mite," ..
		"\x88"+"Prime"+"\x8C"+"Soul,\n" ..
		"\x87"+"Burning"+"\x85"+"Heart," ..
		"\x8E"+"Aurora," ..
		"\x81"+"MistyRuby," ..
		"\x88"+"C"+"\x85"+"y"+"\x88"+"b"+"\x85"+"e"+"\x88"+"r"+"\x85"+"s"+"\x88"+"p"+"\x85"+"a"+"\x88"+"c"+"\x85"+"e," ..
		"\x8F"+"Paradox,\n" ..
		"\x82"+"GoldenShine," ..
		"\x85"+"Crisis," ..
		"\x86"+"Antimatter," ..
		"\x80"+"Priest," ..
		"\x8C"+"BlueWave,\n" ..
		"\x88"+"Arctic"+"\x80"+"Chi," ..
		"\x8B"+"Ranger," ..
		"\x8E"+"PinkMenace," ..
		"\x87"+"Metallic," ..
		"\x8D"+"HazelGlow,\n" ..
		"\x80"+"UltraDrive," ..
		"\x88"+"LapisVapor," ..
		"\x8A"+"AzureBreaker," ..
		"\x85"+"Emperor," ..
		"\x84"+"Blue,\n" ..
		"\x82"+"Mystical," ..
		"\x88"+"Trans"+"\x8E"+"form"+"\x80"+"ation," ..
		"\x87"+"Flamebreaker," ..
		"\x89"+"InfinitysEnd," ..
		"\x82"+"Advance\n" ..
		"\n" ..
		"\x80"+"None\n" ..
		"\n" ..
		"Use the Page Up/Page Down keys to scroll the list.\n"..
		"If you want to use a regular skin color, put 'n_' at the start of your color name!\n"..
		"If you happen to know the internal name of a super color not part of this list, you can use that too!" ..
		"\n")
	//Yeah so let's just say a friend by the name of Bloops helped this script not suck -Icezer
	//above comment x2 -Icy
	elseif str == "default"
		p.scolor = str
		p.scolorstring = "Default"
		CONS_Printf(p,"Super Color set to Default!")
	elseif str == "none"
		p.scolor = str
		p.scolorstring = "None"
		CONS_Printf(p,"Super Color set to None!")
	elseif str == "advance"
		p.scolor = str
		p.scolorstring = "Advance"
		CONS_Printf(p,"Super Color set!")
	elseif str:find('n_') != nil
	and R_GetColorByName(str:sub(str:find('n_')+2))
		p.scolor = R_GetColorByName(str:sub(str:find('n_')+2))
		p.scolorstring = "N_ Colour"
		CONS_Printf(p,"Super Color set!")
	elseif R_GetSuperColorByName(str)
		p.scolor = R_GetSuperColorByName(str)
		CONS_Printf(p,"Super Color set!")
		p.scolorstring = "Super Color"
	elseif smscolors[str] then
		p.scolor = str
		p.scolorstring = 'SMS'
		CONS_Printf(p, 'Super Colour set!')
	else
		CONS_Printf(p,"Please enter a valid Super Color.")
	end
end)

/*
icy here, lemme explain this business
this here serves as a method of allowing potential follow objects to be put on a blacklist for SCR recoloring.
put the name of the object, then literally just put a 1 next to it. follow the formatting you see below for support!

if not SCRnofollowmobjcoloring
    rawset(_G, "SCRnofollowmobjcoloring", {})
end
SCRnofollowmobjcoloring[MT_OBJECT] = 1
*/

if not SCRnofollowmobjcoloring
	rawset(_G, "SCRnofollowmobjcoloring", {})
end
SCRnofollowmobjcoloring[MT_METALJETFUME] = 1 --metal sonic's jet fume object. it shouldn't be colored by supercolor, so it's here.

addHook("PlayerThink", function(p)
	if not (p and p.mo and p.mo.valid) return end
	if (p.scolor == "default" or p.scolor == nil) return end
	if hyperyu return end
	if (p.scolor == "none")
		p.mo.color = p.skincolor
	elseif p.scolor
		for i = 0, 4
			if ((p.mo.color == skins[p.mo.skin].supercolor + i) and (p.powers[pw_super])) //For Super beings of Chaos...
				if (p.scolorstring == "Advance")
					p.mo.color = SKINCOLOR_SUPERADVANCEGOLD
				elseif p.scolorstring == "N_ Colour"
					p.mo.color = R_GetColorByName(p.scolor)
				elseif p.scolorstring == 'SMS' then
					p.mo.color = smscolors[p.scolor][abs( ( (leveltime >> 1) % 9) - 4) + 1]
				else
					p.mo.color = p.scolor + i
				end
			end
		end
		if p.followmobj and p.followmobj.valid
		and p.powers[pw_super] >= 1
			if ((SCRnofollowmobjcoloring) and (SCRnofollowmobjcoloring[p.followmobj.type]) and (SCRnofollowmobjcoloring[p.followmobj.type]) >= 1) return end -- if in blacklist, don't color it.
			p.followmobj.color = p.mo.color
		end
	end
end)

local hyperyu
local superyu

addHook("ThinkFrame", do
	for p in players.iterate
		if p.yusonictable -- time for exclusive sa-sonic thingies, you better feel spoiled shine -Icy
			if p.yusonictable.hypersonic --please let this work for the love of god
				hyperyu = true
			else
				hyperyu = false
			end
			if p.powers[pw_super] >=1
			and not hyperyu
				superyu = true
			else
				superyu = false
			end
			--there WAS gonna be special suuport for sa-sonic's aura here, but getting it to work 100% on it's own in here was... literally impossible. -Icy
			if not (p and p.mo and p.mo.valid) continue end
			if (p.scolor == "default" or p.scolor == nil) continue end
			if hyperyu
				if (p.scolor == "none")
					p.mo.color = p.skincolor
				elseif p.scolor
					for i = 0, 4
						if (p.scolorstring == "Advance")
							p.mo.color = SKINCOLOR_SUPERADVANCEGOLD
						elseif p.scolorstring == "N_ Colour"
							p.mo.color = R_GetColorByName(p.scolor)
						elseif p.scolorstring == 'SMS' then
							p.mo.color = smscolors[p.scolor][abs( ( (leveltime >> 1) % 9) - 4) + 1]
						else
							p.mo.color = p.scolor + abs( ( (leveltime >> 1) % 9) - 4)
						end
					end
				end
			end
		end
	end
end)

addHook("ThinkFrame", do
	for p in players.iterate
		if not (p.scolorstring == "Advance") continue end
		if ((p.powers[pw_super])) //For Super beings of Chaos...
		or ((p.solchar) and (p.solchar.istransformed > 1)) //For those with a powerful Sol (this joke is dumb i'm sorry)...
			if (p.scolorstring == "Advance")
				if (leveltime % 2 == 0)
					local ghost = P_SpawnMobjFromMobj(p.mo,0,0,0,MT_OVERLAY)
					ghost.color = SKINCOLOR_SUPERSILVER1
					ghost.colorized = true
					ghost.angle = p.drawangle
					ghost.rollangle = p.mo.rollangle
					ghost.spritexscale = p.mo.spritexscale
					ghost.spriteyscale = p.mo.spriteyscale
					ghost.skin = p.mo.skin
					ghost.frame = (p.mo.frame & ~FF_TRANSMASK)|TR_TRANS80
					ghost.sprite = p.mo.sprite
					ghost.sprite2 = p.mo.sprite2
					ghost.tics = 1
					ghost.fuse = 1
					ghost.blendmode = AST_ADD
					if p.yusonictable
						ghost.spriteyoffset = p.yusonictable.superoffset -- i really get irked by how you do things sometimes, golden shine -Icy
					end
					if p.followmobj
						if ((SCRnofollowmobjcoloring) and (SCRnofollowmobjcoloring[p.followmobj.type]) and (SCRnofollowmobjcoloring[p.followmobj.type]) >= 1) return end -- same logic as the coloring. if in the blacklist, don't flicker.
						local ghost = P_SpawnMobjFromMobj(p.followmobj,0,0,0,MT_OVERLAY)
						ghost.color = SKINCOLOR_SUPERSILVER1
						ghost.colorized = true
						ghost.angle = p.followmobj.angle
						ghost.rollangle = p.followmobj.rollangle
						ghost.spritexscale = p.followmobj.spritexscale
						ghost.spriteyscale = p.followmobj.spriteyscale
						ghost.skin = p.mo.skin
						ghost.frame =  (p.followmobj.frame & ~FF_TRANSMASK)|TR_TRANS80
						ghost.sprite = p.followmobj.sprite
						ghost.sprite2 = p.followmobj.sprite2
						ghost.tics = 1
						ghost.fuse = 1
						ghost.blendmode = AST_ADD
					end
				end
			end
		end
	end
end) --ty phanto

addHook("PostThinkFrame", do --this hook is SPECIFICALLY for sol forms. created to eliminate load order issues.
	for p in players.iterate
		if not (p and p.mo and p.mo.valid) return end
		if (p.scolor == "default" or p.scolor == nil) return end
		if (p.scolor == "none")
			p.mo.color = p.skincolor
		elseif p.scolor
			for i = 0, 4
				if ((p.solchar) and (p.solchar.burningcolor) and (p.solchar.istransformed > 1)) //For those with a powerful Sol (this joke is dumb i'm sorry)...
					if (p.scolorstring == "Advance")
						p.mo.color = SKINCOLOR_SUPERADVANCEGOLD
					elseif p.scolorstring == "N_ Colour"
						p.mo.color = R_GetColorByName(p.scolor)
					elseif p.scolorstring == 'SMS' then
						p.mo.color = smscolors[p.scolor][abs( ( (leveltime >> 1) % 9) - 4) + 1]
					else
						p.mo.color = R_GetColorByName(p.scolor) + abs( ( (leveltime >> 1) % 9) - 4)
					end
				end
			end
			if p.followmobj and p.followmobj.valid
			and ((p.solchar) and (p.solchar.burningcolor) and (p.solchar.istransformed > 1))
				if ((SCRnofollowmobjcoloring) and (SCRnofollowmobjcoloring[p.followmobj.type]) and (SCRnofollowmobjcoloring[p.followmobj.type]) >= 1) return end -- if in object blacklist, do not color and abort.
				if p.followmobj.sprite2 == SPR2_FIRE return end -- dON'T COLOR BLAZE'S SPINNING FIRE FOR THE LOVE OF *F U C K*, would be in the table if it wasn't set up so specifically
				p.followmobj.color = p.mo.color
			end
		end
	end
end)

//2.2.10 will let this hook set the ghost's colors properly, too.
//Thanks to Mari0shi06 for tweaking this to work better.
addHook("MobjThinker", function(ghost)
    if ghost and ghost.valid
		if not ((ghost.target) and (ghost.target.valid)) return end
		if not ((ghost.target.player) and (ghost.target.player.valid)) return end
		if ((ghost.target.player.powers[pw_super] >= 2) or ((ghost.target.player.solchar) and (ghost.target.player.solchar.burningcolor) and (ghost.target.player.solchar.istransformed > 1)))
			if (ghost.color == skins[ghost.target.skin].supercolor) or (ghost.color == skins[ghost.target.skin].supercolor+1) or (ghost.color == skins[ghost.target.skin].supercolor+2) or (ghost.color == skins[ghost.target.skin].supercolor+3) or (ghost.color == skins[ghost.target.skin].supercolor+4)
				ghost.color = ghost.target.color
			end
		end
	end
end, MT_GHOST)