//Lua to choose a slug cat based on your skincolor

local SCUG_SKIN = "slugcat"
local SCUG_InvGrandPrix = false

//Define slug cat IDs
local SCUG_DEFAULT = 0
local SCUG_INV = 1
local SCUG_MONK = 2
local SCUG_SURVIVOR = 3
local SCUG_RIVULET = 4
local SCUG_MAX = 5 //Always needs to be one above the last slug cat

//Inv's own special skincolor
freeslot("SKINCOLOR_SOFANTHIEL")
skincolors[SKINCOLOR_SOFANTHIEL] = {
	name = "Sofanthiel",
	ramp = {44,46,199,254,254,175,175,137,137,136,136,142,141,141,140,140},
	invcolor = SKINCOLOR_SLATE,
	invshade = 8, 
	chatcolor = V_SKYMAP,
	accessible = false
}

//Assign slug cats to colors
//Positive numbers are chat colors, negative colors are skincolors
local SCUG_COLORS = {
	//Inv
	[-SKINCOLOR_VOMIT] = SCUG_INV,
	[-SKINCOLOR_SOFANTHIEL] = SCUG_INV,
	
	//Monk
	[V_YELLOWMAP] = SCUG_MONK,
	[V_GOLDMAP] = SCUG_MONK,
	//[-SKINCOLOR_BANANA] = SCUG_MONK,
	[-SKINCOLOR_GARDEN] = SCUG_MONK,
	
	//Survivor
	[0] = SCUG_SURVIVOR, //V_WHITEMAP (since it doesn't exist)
	//[-SKINCOLOR_SLATE] = SCUG_SURVIVOR,
	[-SKINCOLOR_GREY] = SCUG_SURVIVOR,
	[-SKINCOLOR_PLATINUM] = SCUG_SURVIVOR,
	[-SKINCOLOR_STEEL] = SCUG_SURVIVOR,
	
	//Rivulet
	[V_SKYMAP] = SCUG_RIVULET,
	[V_BLUEMAP] = SCUG_RIVULET,
	//[-SKINCOLOR_JAWZ] = SCUG_RIVULET,
}

local SCUG_BOTNUM = 2
local SCUG_BOTS = {
	[0] = "redz",
	[1] = "zipp",
	["redz"] = SKINCOLOR_BYZANTIUM,
	["zipp"] = SKINCOLOR_RED,
}

//Get a slug cat ID from a skin color
local SCUG_GetSlugcatFromColor = function(color)
	return SCUG_COLORS[-color] or SCUG_COLORS[skincolors[color].chatcolor] or SCUG_SURVIVOR
end

addHook("MapLoad", do
	//Give everyone their slug cat ID at the beginning of the race
	//I would do this check more often, but there's no sense when the game
	//doesn't naturally let you change your skin midrace
	for player in players.iterate
		if skins[player.skin].name == SCUG_SKIN
			player.slugcat = SCUG_GetSlugcatFromColor(player.skincolor)
		elseif skins[player.skin].flags & SF_IRONMAN
			player.slugcat = -1 //Uh oh! Ironman special case
		else
			player.slugcat = nil
		end
	end
	
	//Inv's torture chamber!
	SCUG_InvGrandPrix = not netgame and grandprixinfo.gp and consoleplayer.slugcat == SCUG_INV
	if not SCUG_InvGrandPrix then return end
	
	//Go through all the players again...
	//Change all bots to max difficulty Redz, any real players get land mines
	local foundredz = true //Loop feedback variable
	while foundredz do
		foundredz = false //We haven't gotten a new Redz yet...
		for player in players.iterate
			//Not a bot? Have a land mine!
			if not player.bot
				if not player.itemtype
					player.itemtype = KITEM_LANDMINE
					player.itemamount = 1
				end
				continue
			end
			
			//Not a Redz? Delete this bot and make a new one!
			local botskin = SCUG_BOTS[(#player - 1) % SCUG_BOTNUM] or "redz"
			if skins[player.skin].name != botskin
				K_RemoveBot(player) //Remove this bot
				K_AddBot(botskin, 13, BOT_STYLE_NORMAL) //Add max level Redz
				
				//Restart loop to account for shuffling player IDs
				foundredz = true
				break
				
			//Already a Redz? Max out the difficulty!
			else
				player.botvars.difficulty = 13 //Max out Redz's level
				player.botvars.rival = true //Force rival mode!
			end
		end
	end
	
	//Go through all the sectors and clamp their brightness down
	for sector in sectors.iterate
		/*
		if not sector.floorlightabsolute
			sector.floorlightabsolute = true
			sector.ceilinglightabsolute = true
			sector.floorlightlevel = min(sector.lightlevel, 144)
			sector.ceilinglightlevel = min(sector.lightlevel, 144)
		end
		*/
		sector.lightlevel = min($, 128)
	end
	
	//Go through all objects and fullbright them at the start
	//Just so the darkness is a little more sane, plus it looks like the game!
	for mobj in mobjs.iterate()
		if (mobj.renderflags & RF_SEMIBRIGHT) == RF_SEMIBRIGHT
			mobj.renderflags = $ &~ RF_FULLDARK
		else
			mobj.renderflags = $ | RF_FULLBRIGHT
		end
	end
	
	//It's a Rain World, and we're living in it
	P_SetupLevelSky("~031")
	if not curWeather
		P_SwitchWeather(PRECIP_RAIN)
	end
end)

//Half of Inv's rings are spikes...
function A_AttractChase(mobj, var1, var2)
	if not SCUG_InvGrandPrix then super(mobj, var1, var2) return end
	
	mobj.renderflags = $ | RF_FULLBRIGHT //Use the rings as your guide for turns
    
	//Need a valid non-bot player
	local mo = mobj.target
	local player = mo and mo.valid and mo.player
	if not (player and not player.bot) then super(mobj, var1, var2) return end
	
	//Is this a ring being used with the item button?
	local isboostring = mobj.extravalue2
	
	//Only every other ring being used by the player is a spike!
	if mobj.scugringspike == nil
		if player.rings == 20 or isboostring
			mo.scugringspike = not $
			mobj.scugringspike = mo.scugringspike
		else
			mobj.scugringspike = false
		end
	end
	if not mobj.scugringspike then super(mobj, var1, var2) return end
	
	//Visual state
	if mobj.state >= S_RING and mobj.state <= S_FASTRING12
		mobj.state = S_DEBTSPIKE1
	end
	
	//Get our current variables before doing the ring logic
	local ringboost = player.ringboost
	local isfinalring = mobj.cvmem
	
	//Do the ring logic
	mobj.cvmem = (not isboostring) and 1 or $ //Hijack the cash register sound for our spike sfx
	super(mobj, var1, var2)
	
	//Revert cvmem variable
	if mobj and mobj.valid
		mobj.cvmem = isfinalring
		return
	end
	
	//You aren't getting anything out of these spikes!
	if player.ringboost != ringboost
		player.ringboost = ringboost
		
		//Play the appropriate sfx instead of the ring ones
		if isboostring
			if S_SoundPlaying(mo, sfx_s1b5)
				S_StopSoundByID(mo, sfx_s1b5)
				S_StartSoundAtVolume(mo, sfx_cdfm39, player.ringvolume)
			end
		elseif not isfinalring and S_SoundPlaying(mo, sfx_s1c5)
			S_StopSoundByID(mo, sfx_s1c5)
			S_StartSoundAtVolume(mo, sfx_s222, player.ringvolume)
		end
	end
end

//Inv Grand Prix! It's horrible
local SCUG_InvGrandPrixThinker = function()
	if not SCUG_InvGrandPrix then return end
	
	for player in players.iterate
		local mo = player.mo
		if not (mo and mo.valid) then continue end
		
		//Always be seeable, even in the dark rain
		if (mo.renderflags & RF_SEMIBRIGHT) == RF_SEMIBRIGHT
			mo.renderflags = $ &~ RF_FULLDARK
		else
			mo.renderflags = $ | RF_FULLBRIGHT
		end
		
		//Player behaviors
		if not player.bot
			//Get a land mine with every item
			if player.itemroulette and player.itemroulette.active
			and not player.backupitemtype
				//While we're at it, why not force the second item to be a sink
				if not player.itemroulette.ringbox
					if #player.itemroulette.itemlist > 1
						K_AddItemToReelByIndex(player, 2, KITEM_KITCHENSINK)
					else
						K_AddItemToReel(player, KITEM_KITCHENSINK)
					end
				end
				
				//Get the land mine!
				player.backupitemtype = KITEM_LANDMINE
				player.backupitemamount = 1
			end
		
		//Bot behaviors
		else
			//Bots get voltage for every checkpoint
			if mo.scugcheckpoint != player.checkpointid //We passed a new checkpoint
			and player.latestlap //We're actually in the game
				player.dotrickfx = true //Give voltage
				mo.scugcheckpoint = player.checkpointid //Update checkpoint
			end
			
			//Force specific colors
			local color = SCUG_BOTS[mo.skin] or SKINCOLOR_RED
			if player.skincolor != color
				if mo.color == player.skincolor
					mo.color = color
				end
				player.skincolor = color
			end
		end
	end
end

//Slug cat thinker
local SCUG_SlugcatThinker = function() for player in players.iterate
	local mo = player.mo
	if not (mo and mo.valid) then continue end
	
	local slugcat = player.slugcat //Grab what slug cat we are
	if slugcat == nil
		continue //We aren't a slug cat? Well that's a waste
	end
	
	//Not actually a slug cat, we're in Ironman mode
	if slugcat == -1
		if mo.skin != SCUG_SKIN then continue end //Not a slug cat... yet
		slugcat = 0
	end
	
	//Get the max number of frames for a specific animation (2 for idle)
	local skin = skins[SCUG_SKIN]
	local maxframes = 2
	if not mo.sprite2
		mo.sprite2 = SPR2_SIGL
		mo.tics = -1
		mo.frame = ($ &~ FF_FRAMEMASK) | FF_ANIMATE
	elseif mo.sprite2 == SPR2_SIGL
		mo.anim_duration = 1 
	end
	maxframes = skin.sprites[mo.sprite2].numframes / SCUG_MAX
	
	//Inv's special behavior in normal gameplay
	if slugcat == SCUG_INV
		//Force skincolor
		if player.skincolor != SKINCOLOR_SOFANTHIEL
			if mo.color == player.skincolor
				mo.color = SKINCOLOR_SOFANTHIEL
			end
			player.skincolor = SKINCOLOR_SOFANTHIEL
		end
		
		//Death voice clip
		if mo.state == S_KART_DEAD and mo.tics != -1
			mo.tics = -1
			S_StartSound(nil, skin.soundsid[SKSPLDET1 + (leveltime % 4)], player)
		end
	end
	
	//Truncate the frame to what slug cat we are
	local newframe = 0
	if maxframes
		local curframe = mo.frame & FF_FRAMEMASK //Our current frame
		newframe = (curframe % maxframes) + (slugcat * maxframes) //Mathz
	end
	
	//Apply the frame!
	mo.frame = ($ &~ FF_FRAMEMASK) | newframe
end end

//Add the above functions into a hook!
addHook("PostThinkFrame", do
	SCUG_InvGrandPrixThinker()
	SCUG_SlugcatThinker()
end)

//Sign post logic

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

//Make the signpost show the correct slug cat for each player and color
function A_ScugSignpost(mobj, var1, var2)
	SCUG_OldSignAction(mobj, var1, var2) //Perform the old signpost action
	
	//We need to be a slug cat and displaying a color first
	if mobj.skin != SCUG_SKIN or not mobj.color then return end
	
	local slugcat = SCUG_GetSlugcatFromColor(mobj.color) //Get the slug cat from our color
	mobj.frame = ($ &~ FF_FRAMEMASK &~ FF_ANIMATE) | slugcat //Apply the frame
end

//Assign our new action to the signpost state
states[S_KART_SIGN].action = A_ScugSignpost