--Huge Thanks to TripelTheFox for letting me use this from Kirby
// "Me" in this case being Mari0shi06, thanks for the help! - SMS Alfredo

// ------------------------------------------
// Lua_Feet
// Yoshi's feet!
// Backported... or, forwardported I guess?
// from kart!
// ------------------------------------------
local charskin = "yoshi"				// Set this to your character's skin (MUST BE ALL LOWWER CASE!)

// Array of colors!
// List cant be copied from kart oops
local yoshicolors = {}
yoshicolors[SKINCOLOR_GREEN] = SKINCOLOR_ORANGE -- Green Yoshi
yoshicolors[SKINCOLOR_EMERALD] = SKINCOLOR_RED -- Green Baby Yoshi TTYD
yoshicolors[SKINCOLOR_RUBY] = SKINCOLOR_EMERALD -- Red Baby Yoshi TTYD
yoshicolors[SKINCOLOR_SAPPHIRE] = SKINCOLOR_ROSY -- Blue Baby Yoshi TTYD
yoshicolors[SKINCOLOR_PINK] = SKINCOLOR_RASPBERRY -- Pink Baby Yoshi TTYD
yoshicolors[SKINCOLOR_EMERALD] = SKINCOLOR_RED -- Green Baby Yoshi TTYD
yoshicolors[SKINCOLOR_JET] = SKINCOLOR_YELLOW -- Black Baby Yoshi TTYD
yoshicolors[SKINCOLOR_AETHER] = SKINCOLOR_RASPBERRY -- White Baby Yoshi TTYD
yoshicolors[SKINCOLOR_FOREST] = SKINCOLOR_PURPLE
yoshicolors[SKINCOLOR_BONE] = SKINCOLOR_SKY	--White Yoshi
yoshicolors[SKINCOLOR_WHITE] = SKINCOLOR_ICY
yoshicolors[SKINCOLOR_BLACK] = SKINCOLOR_WHITE --Black Yoshi
yoshicolors[SKINCOLOR_ROSY] = SKINCOLOR_YELLOW --Pink Yoshi
yoshicolors[SKINCOLOR_BROWN] = SKINCOLOR_RED --Speculated Brown Yoshi (Beta Yoshi's Story)
yoshicolors[SKINCOLOR_BRONZE] = SKINCOLOR_CRIMSON
yoshicolors[SKINCOLOR_LAVENDER] = SKINCOLOR_ORANGE --Purple Yoshi
yoshicolors[SKINCOLOR_PURPLE] = SKINCOLOR_ORANGE --Purple Yoshi (Again)
yoshicolors[SKINCOLOR_RED] = SKINCOLOR_BLUE --Red Yoshi
yoshicolors[SKINCOLOR_COBALT] = SKINCOLOR_CRIMSON
yoshicolors[SKINCOLOR_SALMON] = SKINCOLOR_CORNFLOWER
yoshicolors[SKINCOLOR_BLUE] = SKINCOLOR_NEON --Blue Yoshi 
yoshicolors[SKINCOLOR_CORNFLOWER] = SKINCOLOR_PASTEL
yoshicolors[SKINCOLOR_COBALT] = SKINCOLOR_BLUE
yoshicolors[SKINCOLOR_YELLOW] = SKINCOLOR_GREEN --Yellow Yoshi
yoshicolors[SKINCOLOR_GOLD] = SKINCOLOR_FOREST
yoshicolors[SKINCOLOR_SKY] = SKINCOLOR_PURPLE --Light Blue Yoshi
yoshicolors[SKINCOLOR_APRICOT] = SKINCOLOR_CYAN
yoshicolors[SKINCOLOR_ORANGE] = SKINCOLOR_CYAN -- Orange Yoshi
yoshicolors[SKINCOLOR_RUST] = SKINCOLOR_CERULEAN
yoshicolors[SKINCOLOR_PLUM] = SKINCOLOR_SKY -- Burgundy Yoshi (SMW2)
--New Red Supercolor to match default supercolor
yoshicolors[SKINCOLOR_SUPER_YOSHI_1] = SKINCOLOR_SUPER_BOOT_1
yoshicolors[SKINCOLOR_SUPER_YOSHI_2] = SKINCOLOR_SUPER_BOOT_2
yoshicolors[SKINCOLOR_SUPER_YOSHI_3] = SKINCOLOR_SUPER_BOOT_3
yoshicolors[SKINCOLOR_SUPER_YOSHI_4] = SKINCOLOR_SUPER_BOOT_4
yoshicolors[SKINCOLOR_SUPER_YOSHI_5] = SKINCOLOR_SUPER_BOOT_5

if rawget(_G, "SPR2_FROZ") == nil
	freeslot("SPR2_FROZ")
end

//An array of sprite frames for the boots since we're already using super...
local YOSHIBOOT_SPRITES = {
	[SPR2_STND] = 0,
	[SPR2_WALK] = 1,
	[SPR2_RUN_] = 9,
	[SPR2_SPNG] = 17,
	[SPR2_FALL] = 18,
	[SPR2_FIRE] = 19,
	[SPR2_GASP] = 20,
	[SPR2_MLEE] = 21,
	[SPR2_FLY_] = 22,
	[SPR2_ROLL] = 23,
	[SPR2_RIDE] = 24,
	[SPR2_PAIN] = 25,
	[SPR2_DEAD] = 32,
	[SPR2_DRWN] = 33,
	[SPR2_FROZ] = 34,
	[SPR2_TRNS] = 36,
	[SPR2_NFLT] = 43,
	[SPR2_NFLY] = 44,
	[SPR2_NDRL] = 45,
	[SPR2_NPUL] = 49,
}

// -----------------------------------------------------------------------------
// Starting here, nothing else needs to be modified for your character to work
// -----------------------------------------------------------------------------
// Overlay object!
// Uses a global variable to store the object number, so there's only one object no matter how many sc characters you have.
// Different versions of second color will use different objects (and therefore globals)
// to ensure characters with different versions are still compatable with eachother.
if(overlayobj_v2 == nil)
	freeslot("MT_SECONDCOLOROVERLAY_V2")
	rawset(_G, "overlayobj_v2", MT_SECONDCOLOROVERLAY_V2)
	mobjinfo[overlayobj_v2].doomednum = -1
	mobjinfo[overlayobj_v2].spawnstate = S_PLAY_STND
	mobjinfo[overlayobj_v2].spawnhealth = 1
	mobjinfo[overlayobj_v2].seestate = S_PLAY_WALK
	mobjinfo[overlayobj_v2].seesound = sfx_none
	mobjinfo[overlayobj_v2].reactiontime = 0
	mobjinfo[overlayobj_v2].attacksound = sfx_thok
	mobjinfo[overlayobj_v2].painstate = S_PLAY_PAIN
	mobjinfo[overlayobj_v2].painchance = MT_THOK
	mobjinfo[overlayobj_v2].painsound = sfx_none
	mobjinfo[overlayobj_v2].meleestate = S_NULL
	mobjinfo[overlayobj_v2].missilestate = S_NULL
	mobjinfo[overlayobj_v2].deathstate = S_PLAY_PAIN
	mobjinfo[overlayobj_v2].xdeathstate = S_NULL
	mobjinfo[overlayobj_v2].deathsound = sfx_none
	mobjinfo[overlayobj_v2].speed = 1
	mobjinfo[overlayobj_v2].radius = 16*FRACUNIT
	mobjinfo[overlayobj_v2].height = 48*FRACUNIT
	mobjinfo[overlayobj_v2].dispoffset = 0
	mobjinfo[overlayobj_v2].mass = 1000
	mobjinfo[overlayobj_v2].damage = MT_THOK
	mobjinfo[overlayobj_v2].activesound = sfx_none
	mobjinfo[overlayobj_v2].flags = MF_NOGRAVITY|MF_NOCLIPTHING
	mobjinfo[overlayobj_v2].raisestate = MT_THOK
	
	// Remove the overlay when we no longer need it!
	addHook("MobjThinker", function(scoverlay)
		scoverlay.tics = $1 + 1
		if(scoverlay.timer)
			scoverlay.timer = $1 - 1
		else
			P_RemoveMobj(scoverlay)
		end
	end, overlayobj_v2)
end

// Garbage
local function setStateSafe(mobj, state)
	local defaultaction = states[state].action
	states[state].action = nil
	mobj.state = state
	states[state].action = defaultaction
end

// -------------------------------------------
// Overlay function
// -------------------------------------------
local function doOverlay(mobj, slopestick, addtotarget)
	// Create the overlay
	if not(mobj.scoverlay and mobj.scoverlay.valid)
		mobj.scoverlay = P_SpawnMobj(mobj.x, mobj.y, mobj.z, overlayobj_v2)
	end
	
	local matchmobj = mobj
	if(addtotarget)
		matchmobj = mobj.target
	elseif mobj.player and mobj.player.mouthobj and mobj.player.mouthobj.valid
	and mobj.player.followmobj and mobj.player.followmobj.valid
		matchmobj = mobj.player.followmobj
	end
	
	if not(matchmobj and matchmobj.valid)
		return
	end
	
	// Set the overlay's tracer
	mobj.scoverlay.tracer = matchmobj
//	mobj.scoverlay.flags2 = $1|MF2_LINKDRAW
	
	// Set the overlay's frame to the player's frame! (and tics)
	local height = 0
	if (addtotarget)
		if(states[mobj.state].var2)
			height = states[mobj.state].var2*FRACUNIT*P_MobjFlip(matchmobj)
		else
			height = states[mobjinfo[matchmobj.type].seestate].var2*FRACUNIT*P_MobjFlip(matchmobj)
		end
	end
	
	// Match the overlay to the player
	setStateSafe(mobj.scoverlay, mobj.state)
	
	local frame = YOSHIBOOT_SPRITES[(mobj.sprite2&~FF_SPR2SUPER&~FF_SPR2ENDSTATE&~FF_SPR2MIDSTART)]
	if frame == nil or matchmobj.flags2 & MF2_DONTDRAW or matchmobj.sprite == SPR_NULL
		mobj.scoverlay.state = S_INVISIBLE
	else
		mobj.scoverlay.skin = mobj.skin
		mobj.scoverlay.sprite = SPR_PLAY
		mobj.scoverlay.sprite2 = SPR2_TAL0
		mobj.scoverlay.frame = mobj.frame + frame
		mobj.scoverlay.tics = mobj.tics
		mobj.scoverlay.anim_duration = mobj.anim_duration
	end
	
	// Match the overlay to the player more
	P_TeleportMove(mobj.scoverlay, mobj.x, mobj.y, mobj.z)
	mobj.scoverlay.momx = matchmobj.momx
	mobj.scoverlay.momy = matchmobj.momy
	mobj.scoverlay.momz = matchmobj.momz
	if(matchmobj.player and matchmobj.player.valid)
		mobj.scoverlay.angle = matchmobj.player.drawangle
	else
		mobj.scoverlay.angle = matchmobj.angle
	end
	mobj.scoverlay.scale = matchmobj.scale
	mobj.scoverlay.radius = matchmobj.radius
	mobj.scoverlay.height = matchmobj.height
	
	// Match the colors!
	if(mobj.colorized)
		mobj.scoverlay.color = mobj.color
	elseif(mobj.player)
		and(mobj.player.scoverlaycol)
		mobj.scoverlay.color = mobj.player.overlaycol
	else
		if(yoshicolors[mobj.color] == nil)
			if(mobj.color <= 0 or mobj.color >= MAXSKINCOLORS)
				mobj.scoverlay.color = mobj.color
			else
				mobj.scoverlay.color = ColorOpposite(mobj.color)
			end
		else
			mobj.scoverlay.color = yoshicolors[mobj.color]
		end
	end
	mobj.scoverlay.colorized = mobj.colorized
	
	// Match sprite rotation
	mobj.scoverlay.rollangle = matchmobj.rollangle
	
	// REVERSE GRAVITY WOAAAAAH
	if(mobj.eflags & MFE_VERTICALFLIP)
		mobj.scoverlay.eflags = $1|MFE_VERTICALFLIP
	else
		mobj.scoverlay.eflags = $1 & !MFE_VERTICALFLIP
	end
	
	// MF2_DONTDRAW WOAAAAAH
	if not(addtotarget)
		if(mobj.flags2 & MF2_DONTDRAW)
			or(addtotarget and not mobj.sprite == SPR_PLAY)
			if mobj.player
				if mobj.player.mouthobj
					return
				end
			end
			mobj.scoverlay.flags2 = $1|MF2_DONTDRAW
		else
			mobj.scoverlay.flags2 = $1 & !MF2_DONTDRAW
		end
	else
		if(mobj.flags2 & MF2_DONTDRAW)
			if mobj.player
				if mobj.player.mouthobj
					return
				end
			end
			mobj.scoverlay.flags2 = $1|MF2_DONTDRAW
		else
			mobj.scoverlay.flags2 = $1 & !MF2_DONTDRAW
		end
	end
	
	// MF2_SHADOW WOAAAAAH
	if(mobj.flags2 & MF2_SHADOW)
		and(leveltime or mobj.type != MT_PLAYER)	// Weird bug?
		mobj.scoverlay.flags2 = $1|MF2_SHADOW
	else
		mobj.scoverlay.flags2 = $1 & !MF2_SHADOW
	end
	
	if not(slopestick)
		mobj.scoverlay.flags = $1|MF_NOCLIP|MF_NOCLIPHEIGHT
	end
	
	mobj.scoverlay.flags = ($1 & !FF_TRANSMASK)|(mobj.flags & FF_TRANSMASK)
	
	// Keep the overlay in the world!
	mobj.scoverlay.timer = 1
end

// -------------------------------------------
// Adding overlays to objects!
// -------------------------------------------
// Players
addHook("PreThinkFrame", function()
	for player in players.iterate
		if(player.mo and player.mo.valid and player.mo.prevspr2)
			player.mo.sprite2 = player.mo.prevspr2
			player.mo.prevspr2 = nil
		end
	end
end)
addHook("PostThinkFrame", function()
	for player in players.iterate
		if(player.mo and player.mo.valid and player.mo.skin == charskin)
			doOverlay(player.mo, true, false)
			player.mo.prevspr2 = player.mo.sprite2
			player.mo.sprite2 = $1 & !FF_SPR2SUPER	// Just in case
		end
	end
end)
addHook("PlayerSpawn", function(player)
	if(player.mo and player.mo.valid and player.mo.skin == charskin)
		doOverlay(player.mo, true, false)
		player.mo.prevspr2 = player.mo.sprite2
		player.mo.sprite2 = $1 & !FF_SPR2SUPER	// Just in case
	end
end)

// Ghosts
addHook("MobjThinker", function(ghost)
	if(ghost and ghost.valid and ghost.skin == "yoshi")
		doOverlay(ghost, false, false)
		ghost.sprite2 = $1 & !FF_SPR2SUPER	// Just in case
	end
end, MT_GHOST)
addHook("MobjFuse", function(ghost)
	if(ghost.skin == "yoshi")
		and(ghost.scoverlay and ghost.scoverlay.valid)
		P_RemoveMobj(ghost.scoverlay)	// Make sure to remove it properly so it doesn't linger 1 frame after
	end
end, MT_GHOST)

// Signposts (and 1-up monitors for normal SRB2)
local queuedforoverlay = {}
local numqueued = 0
addHook("MobjThinker", function(overlay)
	if(overlay.skin == "yoshi")
		and(overlay.target and overlay.target.valid)
		queuedforoverlay[numqueued] = overlay
		overlay.overlaydone = false
		numqueued = $1 + 1
	elseif(overlay.scoverlay)
		P_RemoveMobj(overlay.scoverlay)
		overlay.scoverlay = nil
	end
end, MT_OVERLAY)

addHook("PostThinkFrame", function()
	local onum = 0
	while(onum < numqueued)
		if(queuedforoverlay[onum] and queuedforoverlay[onum].valid)
			if not(queuedforoverlay[onum].overlaydone)
				doOverlay(queuedforoverlay[onum], false, true)
			end
			queuedforoverlay[onum].overlaydone = true
		end
		onum = $1 + 1
	end
	queuedforoverlay = nil
	queuedforoverlay = {}
	numqueued = 0
end)
