/*
Kart Secondcolor
	by Lach
	
v1.4
*/

--	NOTE: This tutorial assumes basic knowledge of WAD/PK3 editing. You will
--	need to know how to create markers for new spritesets (WAD) or create
--	directories for sprites and scripts (PK3) and similar functions. If you need
--	assistance with such tasks, refer to these articles on the SRB2 Wiki:
--		- https://wiki.srb2.org/wiki/WAD_file
--		- https://wiki.srb2.org/wiki/PK3
--	...or join the Kart Krew Discord server and ask for help in an appropriate
--	channel:
--		- https://discordapp.com/invite/WJmqDtN
--	...or DM @Lach#9444 on Discord. SLADE is generally agreed upon to be the
--	best WAD/PK3 editor available, for those who are new to this:
--		- http://slade.mancubus.net
--	Jimita's WAD2PK3 conversion tool may be helpful for those who are familiar
--	with WADs but would like their addon in PK3 format:
--		- https://mb.srb2.org/showthread.php?t=44181

--------------------------------------------------------------------------------

--	Instructions!

--	1.	Import this script into your addon as a new lump.

--	2.	Import your secondcolor sprites. These sprites should be a green-mapped
--		cutout of the sprite parts you want to change as the secondary color.
--		(Every character with a secondcolor has this, so look at one of those
--		WADs if you need an example!)
--		These sprites are separate from your S_SKIN sprites! They should be
--		between S_START and S_END markers (WAD) or in their subdirectory in the
--		sprites directory (PK3).

--	3.	Name all these sprites exactly as they would be named if they were
--		your default sprites, but with a custom 4-letter prefix. For instance,
--		if your character uses the prefix PLAY and you pick the prefix BODY,
--		then the secondcolor sprite that matches with PLAYM2O8 should be
--		BODYM2O8. Try to make this prefix as unique as you can to avoid
--		conflicts with other addons!
--		(Again, don't be afraid to use others' addons as examples!)
--		Then, replace "BODY" below with the prefix you chose. (Keep the quotes!)
--		(For those familiar with SOC/Lua - do NOT freeslot this spriteset on
--		your own; this script will do it for you, out of both convenience and
--		necessity.)

local SPRITESET = "SCYO"

--	4. 	Replace "sonic" below with your character's skin name.
--		(This is the name paramater in S_SKIN, but in quotes.)

local SKIN = "scoopy"

--	5.	Fill out secondcolors for each color you want a secondcolor for. Any
--		color you do not fill out a secondcolor for will use the color set in
--		secondcolors.default (see example below). There are also a few special
--		terms you can use, for further customization:
--			•	"opposite": sets the color's secondcolor to SRB2 Kart's built-in
--				opposite color for that color (the color used for the background
--				of the signpost that appears when the first-place player crosses
--				the finish line!)
--
--			•	"none": a secondcolor overlay will not display at all
--
--			•	"self": sets the color's secondcolor to itself
--
--		Any of these may be helpful to use as a default. I have filled in some
--		examples below! Replace them and add new ones as you see fit.
--		NOTE: colors with spaces or punctuation markings should be concatenated.

local secondcolors = {}		-- (this line sets up our table, do not delete it!)

secondcolors.default = "opposite"
secondcolors.dawn = "none"
secondcolors.lemonade = "dawn" --swap
secondcolors.salmon = "self" --all pink, just like beffica wanted
secondcolors.scarlet = "ultraviolet" --pokemon scarlet/violet
secondcolors.ultraviolet = "scarlet"

secondcolors.pistachio = "tangerine" --sherbert, i know it says pistachio but this is sherbert i swear
secondcolors.tangerine = "pistachio"
secondcolors.flame = "mint" --sherbert but prettier
secondcolors.mint = "flame"
secondcolors.caribbean = "periwinkle" --spaceboy because ofc
secondcolors.periwinkle = "caribbean"
secondcolors.cyan = "none" --trans flag
secondcolors.plague = "byzantium" --plague knight
secondcolors.super1 = "handheld"	-- just a note: supercolors are supported,
									-- but they don't have opposite colors, so
									-- any supercolor that is set to "opposite"
									-- will be set to "self" instead

--	6.	By default, this script lets players pick a custom secondcolor for
--		characters that support it, using the console command "secondcolor"
--		(and splitscreen variants). I give you, as the creator of your addon,
--		the option to disable this functionality for your character, if you
--		would prefer that players only use the secondcolors you assigned.
--		Change the below variable to false if you would like to opt your
--		character out of player-selected secondcolors.

local ALLOW_CUSTOMIZABLE_SECONDCOLORS = true

--	7.	Test out your addon! Once you are satisfied with your color choices,
--		you are done. Everything below this paragraph is code, so don't edit it!
--		(No, really, please don't. I can't believe I actually had to clarify
--		that after I released this. The code is designed to not be executed a
--		second time if another addon has already initialized it. Please don't
--		ruin other people's setups by shoehorning your own tidbits in.)

--	Please do not remove these comments, they will be helpful for creators who
--	find this script by looking in your addon.
--	If you have any questions, do not hesitate to DM @Lach#9444 on Discord!
--	I'm looking forward to seeing your character. <3 -Lach

--------------------------------------------------------------------------------

if not kart_secondcolors
	rawset(_G, "kart_secondcolors", {}) // This is our global table - it contains every secondcolor list for every supported character added to your game!
	freeslot("MT_KART_SECONDCOLOR") // This is our custom overlay object - it follows your character and displays your secondcolor sprites over them!
	
	mobjinfo[MT_KART_SECONDCOLOR] = {
		radius = mobjinfo[MT_PLAYER].radius,
		height = mobjinfo[MT_PLAYER].height,
		flags = MF_NOBLOCKMAP | MF_NOCLIPTHING | MF_DONTENCOREMAP,
		spawnstate = S_INVISIBLE,
		dispoffset = 2
	}
	
	local function setSecondColor(player, arg, num)
		if not arg
			CONS_Printf(player, 'Sets a custom secondcolor for supported characters that allow it.\nAccepted arguments:\n\t- Name of a skincolor (such as red)\n\t- Index of a skincolor (such as 15)\n\t- \"none\"/\"off\"/\"clear\" to return to skin-defined secondcolors')
			return
		end
		
		if netgame
			if num > 0
				CONS_Printf(player, 'You can only change secondcolor for splitscreen players in an offline game.')
				return
			end
		else
			if num > 0
				if players[num]
					player = players[num]
				else
					CONS_Printf(player, 'You can only change secondcolor for splitscreen players that are active.')
					return
				end
			end
		end
		
		if arg == "off" or arg == "clear"
			player.ksc_secondcolor = 0
			return
		end
		
		local n = tonumber(arg)
		
		if n ~= nil and n >= 0 and n < MAXTRANSLATIONS
			player.ksc_secondcolor = n
			return
		else
			n = _G["SKINCOLOR_"..arg:upper()]
			
			if n ~= nil
				player.ksc_secondcolor = n
				return
			end
		end
		
		CONS_Printf(player, '\"'..arg..'\" is not a possible value for \"secondcolor.\"')
	end
	
	for i = 4, 1, -1
		local s = i - 1 and i or ""
		COM_AddCommand("secondcolor"..s, function(player, arg)
			setSecondColor(player, arg, i - 1)
		end)
	end
	
	addHook("ThinkFrame", do
		for player in players.iterate
			if not player.mo then continue end
			
			local mo = player.mo
			
			if mo.skin ~= player.ksc_skin
				player.ksc_skin = mo.skin
				player.ksc_colors = kart_secondcolors[mo.skin]
			end
			
			if player.ksc_colors
				if not (mo.ksc_overlay and mo.ksc_overlay.valid)
					mo.ksc_overlay = P_SpawnMobj(mo.x, mo.y, mo.z, MT_KART_SECONDCOLOR)
					mo.ksc_overlay.target = mo
				end
				
				local overlay = mo.ksc_overlay
				
				overlay.scale = mo.scale
				overlay.angle = player.frameangle
				overlay.height = mo.height
				overlay.eflags = mo.eflags & MFE_VERTICALFLIP
				overlay.state = mo.state
				overlay.skin = mo.skin
				overlay.tics = mo.tics
				overlay.sprite = player.ksc_colors.sprite
				overlay.frame = mo.frame
				overlay.colorized = mo.colorized
				
				if not (player.ksc_colors.customizable and player.ksc_secondcolor or player.ksc_colors[player.skincolor] ~= 0)
					overlay.color = 0
				elseif mo.colorized
					overlay.color = mo.color
				elseif player.ksc_colors.customizable and player.ksc_secondcolor
					overlay.color = player.ksc_secondcolor
				else
					mo.ksc_overlay.color = player.ksc_colors[player.skincolor] or ColorOpposite(player.skincolor)
				end
				
				overlay.flags2 = mo.flags2 & (MF2_DONTDRAW|MF2_SHADOW) | ((overlay.color == 0 or mo.sprite ~= SPR_PLAY) and MF2_DONTDRAW or 0)
				
				overlay.momx = 0
				overlay.momy = 0
				overlay.momz = 0
				P_TeleportMove(overlay, mo.x, mo.y, mo.z)
				
				if overlay.color
					if player.kartstuff[k_invincibilitytimer]
						P_SpawnGhostMobj(overlay).fuse = 4
					elseif (player.kartstuff[k_driftboost]
					or player.kartstuff[k_sneakertimer]
					or player.kartstuff[k_startboost])
						P_SpawnGhostMobj(overlay).fuse = 2
					end
				end
			end
		end
	end)
	
	addHook("MobjThinker", function(ghost)
		if ghost.ksc_checked then return end
		
		local sign = ghost.target
		
		if ghost.state == S_PLAY_SIGN
		and sign and sign.valid and sign.target
		and sign.target.ksc_overlay and sign.target.ksc_overlay.color
			local mo = sign.target
			local player = mo.player
			
			local overlay = P_SpawnMobj(ghost.x, ghost.y, ghost.z, MT_OVERLAY)
			overlay.target = ghost
			overlay.state = S_INVISIBLE
			overlay.sprite = player.ksc_colors.sprite
			overlay.frame = S
			
			if player.ksc_colors.customizable and player.ksc_secondcolor
				overlay.color = player.ksc_secondcolor
			else
				overlay.color = player.ksc_colors[player.skincolor] or ColorOpposite(player.skincolor)
			end
		end
		ghost.ksc_checked = true
	end, MT_OVERLAY)

	addHook("MobjThinker", function(mo)
		local target = mo.target
		if not (target and target.valid and kart_secondcolors[target.skin])
			P_RemoveMobj(mo)
			return
		end
		mo.momx = target.x - mo.x
		mo.momy = target.y - mo.y
		if P_IsObjectOnGround(target)
			mo.momz = 2*P_GetMobjGravity(mo)
		else
			mo.momz = target.z - mo.z
		end
	end, MT_KART_SECONDCOLOR)
end

SKIN = $:lower()		// You thought I was using these as constants? hah!
kart_secondcolors[SKIN] = {}

if secondcolors.default
and secondcolors.default:lower() ~= "opposite"
and secondcolors.default:lower() ~= "self"
	if not _G["SKINCOLOR_"..secondcolors.default:upper()]
		error("Invalid secondcolor set for \'default\'")
	else
		local color = _G["SKINCOLOR_"..secondcolors.default:upper()]
		for i = 0, MAXTRANSLATIONS - 1
			kart_secondcolors[SKIN][i] = color
		end
	end
end

secondcolors.default = nil

for k, v in pairs(secondcolors)
	local i = "SKINCOLOR_"..k:upper()
	if _G[i] ~= nil
		v = $:lower()
		
		if v == "opposite"
			kart_secondcolors[SKIN][_G[i]] = nil
			continue
		end
		
		if v == "self"
			kart_secondcolors[SKIN][_G[i]] = _G[i]
			continue
		end
		
		v = "SKINCOLOR_"..$:upper()
		if _G[v] ~= nil
			kart_secondcolors[SKIN][_G[i]] = _G[v]
		else
			error("Invalid secondcolor set for \'"..k.."\'")
		end
	else
		error("Invalid skincolor \'"..k.."\'")
	end
end

for i = SKINCOLOR_SUPER1, MAXTRANSLATIONS - 1
	if kart_secondcolors[SKIN][i] == nil
		kart_secondcolors[SKIN][i] = i
	end
end

SPRITESET = "SPR_"..$
freeslot(SPRITESET)
SPRITESET = _G[$]

kart_secondcolors[SKIN].sprite = SPRITESET
kart_secondcolors[SKIN].customizable = ALLOW_CUSTOMIZABLE_SECONDCOLORS