freeslot("MT_TAILSSWEAT","SPR_SWET","S_TAILS_SWEAT1","S_TAILS_SWEAT2")

//custom1 sfx

rawset(_G, "TC_isTails", function(player)
	if player == nil then return false end
	if player.mo == nil then return false end
	if (player.mo.skin == "ffssffredftails")
	or (player.mo.skin == "ntails")
		return true
	else
		return false
	end
end)
addHook('JumpSpecial', function(player)
	    if player.mo and player.mo.valid
			if player.mo.skin == "ntails"
               if (player.powers[pw_tailsfly] > 0) and (player.cmd.buttons & BT_JUMP)
                player.fly1 = 1
				end
			end
		end
end)

rawset(_G, "TC_isHyper", function(player)
	if player == nil then return false end
	if player.mo == nil then return false end
	if not player.powers[pw_super] then return false end
	if (mrce_hyperunlocked == true and player.powers[pw_super])
	or (player.isxmomentum and player.hyper.capable)
	or (player.mo.skin == "supersogrrfnic" and player.hyper.transformed)
	or (player.powers[pw_super] and player.mysticsuper != nil and player.mysticsuper == 1)
		return true
	else
		return false
	end
end)

rawset(_G, "ChrispySonic_SpawnDustRing", function(mo, speed, thrust, alwaysabove)
	local momz = mo.momz
	if alwaysabove
		momz = -P_MobjFlip(mo)*abs($)
	end
	if abs(momz) < mo.scale
		momz = $ < 0 and -mo.scale or mo.scale
	end
		
	local forwardangle = R_PointToAngle2(0, 0, mo.momx, mo.momy)
	local sideangle = forwardangle + ANGLE_90
	local vangle = R_PointToAngle2(0, 0, FixedHypot(mo.momx, mo.momy), momz)
	
	local cosine = cos(vangle)
	local sine = sin(vangle)
	
	local radius = FixedDiv(mo.height, mo.scale) >> 1
	local xspawn = -FixedMul(FixedMul(cos(forwardangle), cosine), radius)
	local yspawn = -FixedMul(FixedMul(sin(forwardangle), cosine), radius)
	local zspawn = -FixedMul(sine, radius)
	
	local hthrust = 0
	local vthrust = 0
	if thrust
		hthrust = FixedMul(thrust, cosine)
		vthrust = FixedMul(thrust, sine)
	end
	
	cosine = FixedMul($, speed)
	sine = FixedMul($, speed)
	
	for i = 1, 16
		local dust = P_SpawnMobjFromMobj(mo, xspawn, yspawn, radius, mo.eflags & (MFE_UNDERWATER | MFE_TOUCHWATER) and MT_MEDIUMBUBBLE or MT_DUST)
		
		local a = i*ANGLE_22h + forwardangle
		
		local forwardthrust = FixedMul(cos(a), sine)
		local sidethrust = FixedMul(sin(a), speed)
		local zthrust = FixedMul(cosine, cos(a))
		
		dust.z = $ + zspawn
		
		P_Thrust(dust, forwardangle, forwardthrust - hthrust)
		P_Thrust(dust, sideangle, sidethrust)
		dust.momz = -zthrust - vthrust
		
		dust.fuse = TICRATE/4
		dust.destscale = mo.scale/8
	end
end)

addHook("ThinkFrame", do
    for player in players.iterate
	   if (player.mo and player.valid and TC_isTails(player))

	   if not (player.mo.usedown) then
	   player.mo.usedown = 0
	   end
	   
	   if not (player.mo.flydrop) then
	   player.mo.flydrop = 0
	   end
	  
	   if (player.cmd.buttons & BT_CUSTOM1) and player.panim == PA_ABILITY
	   and (player.mo.usedown == 0)
	   and not P_IsObjectOnGround(player.mo)
	   S_StartSound(player.mo, sfx_trcul)
	   player.mo.usedown = 1
	   player.mo.flydrop = 1
	   player.mo.state = S_PLAY_JUMP
	   player.pflags = $1| PF_JUMPED
	   end
	   
	   if not (player.cmd.buttons & BT_CUSTOM1)
	   and (player.mo.usedown == 1)
	   player.mo.usedown = 0
	   end
	   
	   end
	end
end)

addHook("PlayerThink",function(p)
	if not (p.mo and p.mo.valid and TC_isTails(p))
		return end
	local mo = p.mo
	
	if p.tailsthrusterjumptimer == nil
		p.tailsthrusterjumptimer = 0
	end
	
	if p.tailsthrusterjumptimercap == nil
		p.tailsthrusterjumptimercap = 35
	end
	
	local tailsthrusterjumpthrust = FRACUNIT*36
	
	if p.tailsthrusterjumpthrustmultiplier == nil
		p.tailsthrusterjumpthrustmultiplier = 1
	end
	
	if p.tailsusedthrusterjump == nil
		p.tailsusedthrusterjump = false
	end
	
	if p.tailsthrusterjumptrailtimer == nil
		p.tailsthrusterjumptrailtimer = 0
	end
	
	if p.tailsspawnaura == nil
		p.tailsspawnaura = false
	end
	
	local FixedLerp = function (a, b, w)
		return FixedMul((FRACUNIT - w), a) + FixedMul(w, b)
	end
	
	if (mo.previousx == nil) or (mo.previousy == nil) or (mo.previousz == nil)
		mo.previousx = mo.x
		mo.previousy = mo.y
		mo.previousz = mo.z
	end
	
	if (p.cmd.buttons & BT_CUSTOM1) and p.tailsthrusterjumptimer < p.tailsthrusterjumptimercap and p.tailsusedthrusterjump == false and mo.state == S_PLAY_JUMP and not P_IsObjectOnGround(mo) and not (mo.eflags & MFE_UNDERWATER) and not p.exiting then
		p.tailsthrusterjumptimer = $ + 1
		if p.tailsthrusterjumptimer == p.tailsthrusterjumptimercap and p.tailsspawnaura == false then
			S_StartSound(mo, sfx_cdfm40, p)
			p.tailsspawnaura = true
		end
	end
	
	if P_IsObjectOnGround(mo) then
		p.tailsusedthrusterjump = false
	end
	
	if p.tailsthrusterjumptrailtimer > 0
		p.tailsthrusterjumptrailtimer = $ - 1
		if p.tailsusedthrusterjump == true
			mo.previousx = mo.x
			mo.previousy = mo.y
			mo.previousz = mo.z
			for i = 0, 9
				local percent = FRACUNIT * (i * 10) / 100
				local trail = P_SpawnGhostMobj(mo)
				local tx = FixedLerp(mo.x,mo.previousx,percent)
				local ty = FixedLerp(mo.y,mo.previousy,percent)
				local tz = FixedLerp(mo.z + 3*FRACUNIT,mo.previousz + 4*FRACUNIT,percent)
				P_TeleportMove(trail, tx, ty, tz - 7 * FRACUNIT)
				trail.fuse = 13
				//trail.scalespeed = FRACUNIT/12
				//trail.scale = (FRACUNIT * 4/5) - (i * FRACUNIT/120)
				//trail.destscale = 0
				trail.frame = TR_TRANS70
			end
		end
	end
	
	if (P_IsObjectOnGround(mo) or not (p.cmd.buttons & BT_CUSTOM1)) or mo.eflags & MFE_UNDERWATER then
		if p.tailsthrusterjumptimer >= p.tailsthrusterjumptimercap and p.tailsusedthrusterjump == false and not P_IsObjectOnGround(mo) and not (mo.eflags & MFE_UNDERWATER) then
		
			if p.powers[pw_super]
				p.tailsthrusterjumpthrustmultiplier = 2
			else
				p.tailsthrusterjumpthrustmultiplier = 1
			end	
		
			if TC_isHyper(p)
				if mo.eflags & MFE_UNDERWATER
					P_SetObjectMomZ(mo, (tailsthrusterjumpthrust*p.tailsthrusterjumpthrustmultiplier)/2, false) // 2/3 * 3/2 = 1
				else
					P_SetObjectMomZ(mo, (tailsthrusterjumpthrust*p.tailsthrusterjumpthrustmultiplier)*3/4, false)
				end
			else
				if mo.eflags & MFE_UNDERWATER
					P_SetObjectMomZ(mo, (tailsthrusterjumpthrust*p.tailsthrusterjumpthrustmultiplier)/3, false)
				else
					P_SetObjectMomZ(mo, (tailsthrusterjumpthrust*p.tailsthrusterjumpthrustmultiplier)/2, false) // 1/ (15/6)
				end
			end
			
			p.tailsusedthrusterjump = true
			ChrispySonic_SpawnDustRing(mo, 6*mo.scale, 2*mo.scale)
			S_StartSound(mo, sfx_kc5b, p)
			mo.state = S_PLAY_FLY_TIRED
			p.tailsthrusterjumptrailtimer = 5
			p.pflags = $1| (PF_JUMPED|PF_THOKKED)
		end
	p.tailsthrusterjumptimer = 0
	p.tailsspawnaura = false
	end
end)

addHook("MobjDamage", function(target, inflictor, source, damage, damagetype)
	if inflictor and inflictor.valid and inflictor.type == MT_PLAYER
		if target and target.valid and ((target.flags & MF_ENEMY) or (target.flags & MF_BOSS))
			if TC_isTails(inflictor.player)
				if (inflictor.player.pflags & PF_THOKKED)
					inflictor.player.pflags = $1 & ~(PF_THOKKED)
				end
			end
		end
	end
end)

addHook("MobjDeath", function(target, inflictor)
if inflictor and inflictor.valid and inflictor.type == MT_PLAYER
		if target and target.valid and (target.flags & MF_MONITOR)
			if TC_isTails(inflictor.player)
				if (inflictor.player.pflags & PF_THOKKED)
					inflictor.player.pflags = $1 & ~(PF_THOKKED)
				end
			end
		end
	end
end)

//Lifted from MRCE_Styles-v6

addHook("ThinkFrame", function(p)
	for p in players.iterate
		if p.mo and p.mo.valid
			if p.tailsspawnaura == false continue end
			if TC_isTails(p)
				if (p.mo.state == S_PLAY_JUMP)
					local fakethok = P_SpawnMobjFromMobj(p.mo, 0*FRACUNIT, 0*FRACUNIT, -3*FRACUNIT, MT_FADETHOK)
					fakethok.color = p.mo.color
					fakethok.destscale = 1*FRACUNIT/10
					if (p.mo.flags2 & MF2_OBJECTFLIP) and (p.mo.eflags & MFE_VERTICALFLIP)
						fakethok.flags2 = $ | MF2_OBJECTFLIP
						fakethok.eflags = $ | MFE_VERTICALFLIP
					end
				end
			end
		end
	end
end)


addHook("PlayerThink", function(player)
//print(player.dashmode)
	if player.mo and player.mo.valid and (player.mo.skin == "ntails")
		if player.dashpreserve == nil
				player.dashpreserve = 0
			end
		if player.dashmode > 3*TICRATE //If you have dash mode, preserve it in the air.
			player.dashpreserve = true
		end
		if not P_IsObjectOnGround(player.mo) //If in the air, keep dash mode set so it doesn't count down.
			if player.dashpreserve == true
				player.dashmode = max(player.dashmode, 3*36)
			end
		end
		if not P_IsObjectOnGround(player.mo) //Build dash mode in the air the same way you would on the ground. Based on source code.
		and (player.dashmode >= 3*TICRATE)
		and player.speed > 28*FRACUNIT
			if (player.normalspeed < skins[player.mo.skin].normalspeed*2) // If the player normalspeed is not currently at normalspeed*2 in dash mode, add speed each tic.
				player.normalspeed = $ + FRACUNIT/5
			end
			if (player.jumpfactor < FixedMul(skins[player.mo.skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height.
				player.jumpfactor = $ + FRACUNIT/300
			end
		end
		if (player.dashmode) //If you have dash mode :v
            if not (player.mo.health) //If any of these conditionals are met, don't preserve dash mode.
            or (P_PlayerInPain(player))
            or (player.gotflag)
            or (player.exiting)
            or (player.pflags & (PF_STASIS|PF_JUMPSTASIS))
            or (player.powers[pw_carry])
            or (player.powers[pw_super] == 1)
			or (player.mo.chargefalling == true)
                player.dashpreserve = false
			end
		end
		if P_IsObjectOnGround(player.mo) //If on the ground and dash mode isn't active, don't preserve what doesn't exist.
            if player.dashmode <= 3*TICRATE
                player.dashpreserve = false
            end
        end
	end
end)





        //dropdown made by kirb the korb thanks ;)
		addHook("SpinSpecial", function(player)
		if player.mo.skin == "ntails"
		and not player.powers[pw_shield]
		and (player.mo.state == S_PLAY_JUMP)
		and not (player.mo.state >= S_PLAY_SUPER_TRANS1 and player.mo.state <= S_PLAY_SUPER_TRANS6)
		and not (player.pflags & PF_FULLSTASIS)
		and not (player.pflags & PF_THOKKED)
		and (player.pflags & PF_JUMPED)
		and not (player.mo.state == S_PLAY_PAIN)
		and (P_IsObjectOnGround(player.mo) == false) then
		S_StartSound(player.mo, sfx_spndsh)
		
		player.mo.state = S_PLAY_ROLL
		P_SpawnMobj(player.mo.x - 25*FRACUNIT, player.mo.y, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x + 25*FRACUNIT, player.mo.y, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x, player.mo.y + 25*FRACUNIT, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x - 20*FRACUNIT, player.mo.y - 20*FRACUNIT, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x + 20*FRACUNIT, player.mo.y - 20*FRACUNIT, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x - 20*FRACUNIT, player.mo.y + 20*FRACUNIT, player.mo.z, MT_DUST)
		P_SpawnMobj(player.mo.x + 20*FRACUNIT, player.mo.y + 20*FRACUNIT, player.mo.z, MT_DUST)
		player.charge = true
	 player.mo.momz = -30*FRACUNIT
	end
end)




	addHook("PlayerThink", function(player)
		if player.mo.skin == "ntails"
		and player.charge == true
		and (P_IsObjectOnGround(player.mo) == true) then
				S_StartSound(player.mo, sfx_zoom)
				player.mo.state = S_PLAY_ROLL
				player.charge = false
				player.pflags = $|PF_THOKKED
				P_SetObjectMomZ(player.mo, 10*FRACUNIT, true)
		end
	end)
//advance swim sound script made by neo
addHook("PlayerThink", function(player)
	if player.mo.skin == "ntails"	
		if not P_IsObjectOnGround(player.mo)
		local advanceswim = false
			if (player.mo.state == S_PLAY_SWIM)
				if (player.mo.frame == A or player.mo.frame == E)
					if not advanceswim
					and not player.powers[pw_extralife]
					and not S_SoundPlaying(player.mo, sfx_advswi)
					S_StartSound(player.mo, sfx_advswi)
					P_SpawnSkidDust(player, 1*FRACUNIT)
					end
				end
			end
		end
	end
end)
//tailswipe 
freeslot("S_TAILS_SWIPE")
states[S_TAILS_SWIPE] = {SPR_PLAY, SPR2_MLEE|FF_ANIMATE, 10, nil, 2, 1, S_PLAY_RUN}
addHook("ThinkFrame", function(player)
	for player in players.iterate
		if player.mo or player.mo.valid
		and(player.mo.skin == "ntails") -- charname here
			-- Button tapping detection script, taken and modified from the wiki sound
			if not (player.cmd.buttons & BT_CUSTOM1) then
				player.spintapready = true
				player.spintapping = false
			elseif player.spintapready then
				player.spintapping = true
				player.spintapready = false
			else
				player.spintapping = false
			end
			-- Hammer spin cooldown
			if player.hammerspincooldown == nil
				player.hammerspincooldown = 0
			end
			if player.mo.state == S_TAILS_SWIPE
			and player.hammerspincooldown == 0
				player.hammerspincooldown = 20
			end
			if player.hammerspincooldown > 0
				player.hammerspincooldown = $ - 1
			end
			-- Ghost trail thing
			if player.mo.state == S_TAILS_SWIPE
				local ghost = P_SpawnGhostMobj(player.mo)
				ghost.fuse = 4
				ghost.speed = player.speed
			end
		end
	end
end)
local function sbvars(m,pmo)
	if m and m.valid then
		m.momx = $ + pmo.momx
		m.momy = $ + pmo.momy
		S_StartSoundAtVolume(m,sfx_s3kb8,190)
	end
end
local sideangle = ANG30 + ANG10
local function Tailsdomissile(mo)
	//Projectile
	local m = P_SPMAngle(mo,MT_ROCKET,mo.angle+sideangle,0)
	sbvars(m,mo)
	//Do Side Projectiles
	local m = P_SPMAngle(mo,MT_ROCKET,mo.angle-sideangle,0)
	sbvars(m,mo)
	local m = P_SPMAngle(mo,MT_ROCKET,mo.angle,0)
	sbvars(m,mo)
end
addHook("PlayerThink", function(player)
    if player.mo and player.mo.skin == "ntails" -- charname here
		-- State swap for hammer spin
		if P_IsObjectOnGround(player.mo) -- If you're on the ground...
		and not (player.mo.state == S_PLAY_ROLL) -- ...and you're not spinning...
		and player.spintapping == true -- ...and you're tapping Custom 1...
		and player.speed > 0*FRACUNIT -- ...and your speed is higher than 4...
		and player.hammerspincooldown == 0
			player.mo.state = S_TAILS_SWIPE -- ...you'll enter spin state!A
			S_StartSound(player.mo, sfx_s3k42, player)
		end
	end
end)
/*
local function HammerSpinKill(touchedmobj, mobj)
	for player in players.iterate do //abuse that error.
	if (player.mo.skin == "ntails")
	and (touchedmobj.flags & (MF_ENEMY|MF_BOSS))
	and (player.mo.state == S_TAILS_SWIPE)
		P_DamageMobj(touchedmobj, mobj, mobj)
		S_StartSound(player.mo, sfx_none, player)
		return true
	elseif (player.mo.skin == "ntails")
	and (touchedmobj.flags & (MF_MONITOR))
	and (player.mo.state == S_TAILS_SWIPE)
		P_KillMobj(touchedmobj, mobj, mobj)
		S_StartSound(player.mo, sfx_none, player)
		return true
	end
	end
end
addHook("MobjCollide", HammerSpinKill)
*/
addHook("PlayerCanDamage", function(player)
	if player.mo.state == S_TAILS_SWIPE
		return true
	end
end)
-- Spike breaking hook
addHook("MobjCollide", function(thing, tmthing)
  if (tmthing.skin ~= "ntails" or not tmthing.player) then return end -- return end if you're not that skin or you aren't a skin
  if thing.z + thing.height < tmthing.z + tmthing.momz or thing.z > tmthing.z + tmthing.momz + tmthing.height then return nil end -- return nil end if that's true, i forgot what this checks
  local p = tmthing.player -- localing p as player
  if(p.mo.state == S_TAILS_SWIPE) then -- If you're spinning, you will have the following effects:
    P_KillMobj(thing, tmthing, tmthing, nil, nil) -- You'll "kill" the specified object.
  end
end, MT_SPIKE) -- The specified object is MT_SPIKE in this case.



//fly effects
addHook("MobjThinker", function(tails)
	if tails and tails.skin == "ntails"
		// Flying
		// Add a visual indication a bit before Tails becomes tired of flying.
		if ((tails.state == S_PLAY_FLY) or (tails.state == S_PLAY_FLY) or (tails.state == S_PLAY_SWIM))
			if tails.player.powers[pw_tailsfly] == 52
			or tails.player.powers[pw_tailsfly] == 35
			or tails.player.powers[pw_tailsfly] == 17
				P_SpawnMobj(tails.x, tails.y, tails.z + 50*FRACUNIT, MT_TAILSSWEAT)
				S_StartSound(tails, sfx_s3k6d)
		    end
		end	
	end
end, MT_PLAYER)

addHook("ThinkFrame", do
	for player in players.iterate
		if (player.mo.valid) and (player.mo.skin == "ntails")
			player.charflags = $ | SF_DASHMODE
			if player.dashmode >= 3*TICRATE
				player.nomoredashmodeflash = P_SpawnGhostMobj(player.mo)
				player.nomoredashmodeflash.fuse = 1
				if player.followitem
				player.nomoredashmodeflash.tracer.fuse = 1
				end
				player.nomoredashmodeflash.frame = player.mo.frame
			end
		end
	end
end)
addHook("FollowMobj", function(player, tails) --Having a custom tails overlay is cool
	if player.mo.skin == "ntails"
		tails.renderflags = $&~RF_VERTICALFLIP
		local smilesonground = P_IsObjectOnGround(player.mo)
		local horizangle = player.drawangle
		local zoffs = 0
		local backwards = -FRACUNIT
		local doswim = (player.panim == PA_ABILITY and (player.mo.eflags & MFE_UNDERWATER))
		local doroll = (player.panim == PA_ROLL or (player.panim == PA_JUMP and not (player.charflags & SF_NOJUMPSPIN)) or doswim)
		local rollangle
		local panimchange
		local ticnum = 0
		local chosenstate
		
		if not tails.skin
			tails.skin = player.mo.skin
			tails.state = S_TAILSOVERLAY_STAND
			tails.movecount = -1
		end
		
		panimchange = (tails.movecount != player.panim)
		
		if doroll
			local testval, zdist
			if player.speed < FRACUNIT
				testval = FRACUNIT
			else
				testval = (FixedMul(player.speed, cos((horizangle-R_PointToAngle2(0, 0, player.rmomx, player.rmomy)))))
				if testval < FRACUNIT
					testval = FRACUNIT
				end
			end
			if doswim
				zdist = player.mo.momz<<1
			elseif smilesonground and not player.mo.reactiontime
				zdist = (player.mo.z-tails.threshold)
			else
				zdist = player.mo.momz
			end
			rollangle = R_PointToAngle2(0, 0, testval, -P_MobjFlip(player.mo)*zdist)
			if not doswim
				zoffs = 3*FRACUNIT + 12*sin(rollangle)
				backwards = -12*cos(rollangle)
			end
			if ((not ((gametyperules & GTR_RACE) and leveltime < 4*TICRATE))
			and player.acceldash and player.doaccel)
			or player.chball or player.dotailspin
				backwards = -15*FRACUNIT
				zoffs = 0
			end
		elseif player.panim == PA_RUN
			backwards = -5*FRACUNIT
		elseif (player.panim == PA_SPRING or player.panim == PA_JUMP)
			if (player.springfall and player.cmd.buttons & BT_JUMP)
				zoffs = -10*FRACUNIT
				backwards = -5*FRACUNIT
			else
				zoffs = $+FRACUNIT*4
				backwards = $/2
			end
		elseif (player.panim == PA_FALL)
			if (player.springfall and player.cmd.buttons & BT_JUMP)
			or player.dotailspin
				zoffs = -10*FRACUNIT
				backwards = -5*FRACUNIT
				if player.dotailspin
					zoffs = -5*FRACUNIT
				end
			else
				zoffs = 0
				backwards = -FRACUNIT
			end
		elseif player.panim == PA_PAIN
			backwards = $/16
		elseif player.mo.state == S_PLAY_GASP
			backwards = $/16
			zoffs = 12*FRACUNIT
		elseif player.mo.state == S_PLAY_EDGE
			if player.prop and player.startascend
				zoffs = 0
				backwards = -5*FRACUNIT
			else
				backwards = $/16
				zoffs = 3*FRACUNIT
			end
		elseif player.panim == PA_ABILITY2
			local step = (player.maxdash - player.mindash)/6
			local speed = (player.dashspeed - player.mindash)
			if (speed > 6*step)
				zoffs = 0
				backwards = -5*FRACUNIT
			else
				zoffs = -7*FRACUNIT
				backwards = -9*FRACUNIT
			end
			if player.dotailspin
				zoffs = 0
				backwards = -5*FRACUNIT
			end
		elseif player.panim == PA_ABILITY
			backwards = -5*FRACUNIT
		end
		
		if doroll
			rollangle = $+ANG15
			if (rollangle > ANG60)
				chosenstate = S_TAILSOVERLAY_PLUS60DEGREES
			elseif (rollangle > ANG30)
				chosenstate = S_TAILSOVERLAY_PLUS30DEGREES
			elseif (rollangle < -ANG60)
				chosenstate = S_TAILSOVERLAY_MINUS60DEGREES
			elseif (rollangle < -ANG30)
				chosenstate = S_TAILSOVERLAY_MINUS30DEGREES
			else
				chosenstate = S_TAILSOVERLAY_0DEGREES
			end
			if ((not ((gametyperules & GTR_RACE) and leveltime < 4*TICRATE))
			and player.acceldash and player.doaccel)
			or player.chball or player.dotailspin
				chosenstate = S_TAILSOVERLAY_RUN
			end
		elseif (player.panim == PA_SPRING or player.panim == PA_JUMP)
			if (player.springfall and player.cmd.buttons & BT_JUMP)
				chosenstate = S_TAILSOVERLAY_FLY
				tails.renderflags = $|RF_VERTICALFLIP
			else
				chosenstate = S_TAILSOVERLAY_MINUS60DEGREES
				tails.renderflags = $&~RF_VERTICALFLIP
			end
		elseif (player.panim == PA_FALL or player.mo.state == S_PLAY_RIDE)
			if (player.springfall and player.cmd.buttons & BT_JUMP)
				chosenstate = S_TAILSOVERLAY_FLY
				tails.renderflags = $|RF_VERTICALFLIP
			else
				chosenstate = S_TAILSOVERLAY_PLUS60DEGREES
			end
			if player.dotailspin
				chosenstate = S_TAILSOVERLAY_RUN
			end
		elseif (player.panim == PA_PAIN)
			chosenstate = S_TAILSOVERLAY_PAIN
		elseif (player.mo.state == S_PLAY_GASP)
			chosenstate = S_TAILSOVERLAY_GASP
		elseif (player.mo.state == S_PLAY_EDGE)
			if player.prop and player.startascend
				chosenstate = S_TAILSOVERLAY_RUN
			else
				chosenstate = S_TAILSOVERLAY_EDGE
			end
		elseif (player.panim == PA_DASH) and not player.powers[pw_super]
			chosenstate = S_TAILSOVERLAY_DASH
		elseif (player.panim == PA_RUN) and not player.powers[pw_super]
			chosenstate = S_TAILSOVERLAY_RUN
		elseif (player.panim == PA_WALK)
			if (not smilesonground or player.mo.state == S_PLAY_SKID)
				chosenstate = S_TAILSOVERLAY_PLUS30DEGREES
			elseif (player.speed >= FixedMul(player.runspeed/2, player.mo.scale))
				chosenstate = S_TAILSOVERLAY_0DEGREES
			else
				chosenstate = S_TAILSOVERLAY_MINUS30DEGREES
			end
		elseif (player.mo.sprite2 == SPR2_FLY)
			chosenstate = S_TAILSOVERLAY_FLY
		elseif (player.mo.sprite2 == SPR2_SWIM)
			chosenstate = S_TAILSOVERLAY_FLY
			if player.prop and player.startascend
				chosenstate = S_TAILSOVERLAY_FLY
			end
		elseif (player.mo.sprite2 == SPR2_TIRE)
			chosenstate = S_TAILSOVERLAY_TIRE
		elseif (player.panim == PA_ABILITY2)
			local step = (player.maxdash - player.mindash)/6
			local speed = (player.dashspeed - player.mindash)
			if (speed > 6*step)
			or player.dotailspin
				chosenstate = S_TAILSOVERLAY_RUN
			else
				chosenstate = S_TAILSOVERLAY_PLUS30DEGREES
			end
			if player.dotailspin
				chosenstate = S_TAILSOVERLAY_RUN
			end
		elseif (player.panim == PA_IDLE)
			chosenstate = S_TAILSOVERLAY_STAND
		else
			chosenstate = S_TAILSOVERLAY_0DEGREES
		end
		
		if player.dotheflip
			if doroll
				backwards = -5*FRACUNIT
				zoffs = 0
			elseif player.panim == PA_RUN
				backwards = -5*FRACUNIT
			elseif (player.panim == PA_SPRING or player.panim == PA_JUMP)
				backwards = -5*FRACUNIT
				zoffs = 0
			elseif (player.panim == PA_FALL)
				backwards = -5*FRACUNIT
			elseif player.panim == PA_PAIN
				backwards = -5*FRACUNIT
			elseif player.mo.state == S_PLAY_GASP
				backwards = -5*FRACUNIT
			elseif player.mo.state == S_PLAY_EDGE
				zoffs = 0
				backwards = -5*FRACUNIT
			elseif player.panim == PA_ABILITY2
				backwards = -5*FRACUNIT
			elseif player.panim == PA_ABILITY
				backwards = -5*FRACUNIT
			elseif player.panim == PA_IDLE
				backwards = -6*FRACUNIT
				zoffs = -6*FRACUNIT
			elseif player.panim == PA_WALK
				backwards = -6*FRACUNIT
				zoffs = -6*FRACUNIT
			end
			
			if doroll
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_SPRING or player.panim == PA_JUMP)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_FALL or player.mo.state == S_PLAY_RIDE)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_PAIN)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.mo.state == S_PLAY_GASP)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.mo.state == S_PLAY_EDGE)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_DASH)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_RUN)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_WALK)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.mo.sprite2 == SPR2_FLY)
				chosenstate = S_TAILSOVERLAY_FLY
			elseif (player.mo.sprite2 == SPR2_SWIM)
				chosenstate = S_TAILSOVERLAY_FLY
			elseif (player.mo.sprite2 == SPR2_TIRE)
				chosenstate = S_TAILSOVERLAY_FLY
			elseif (player.panim == PA_ABILITY2)
				chosenstate = S_TAILSOVERLAY_RUN
			elseif (player.panim == PA_IDLE)
				chosenstate = S_TAILSOVERLAY_RUN
			else
				chosenstate = S_TAILSOVERLAY_RUN
			end
		end
		
		if panimchange
			tails.state = chosenstate
		else
			if tails.state != chosenstate
				tails.state = chosenstate
			end
		end
		
		if (player.panim == PA_SPRING or player.panim == PA_FALL or player.mo.state == S_PLAY_RIDE)
			if (FixedDiv(abs(player.mo.momz), player.mo.scale) < 20<<FRACBITS)
				ticnum = 2
			else
				ticnum = 1
			end
		elseif (player.panim == PA_PAIN)
			ticnum = 2
		elseif (player.mo.state == S_PLAY_GASP)
			tails.tics = -1
		elseif (player.mo.sprite2 == SPR2_TIRE)
			if doswim
				ticnum = 2
			else
				ticnum = 4
			end
		elseif (player.panim != PA_IDLE)
			ticnum = player.mo.tics
		end
		if player.mo.state == S_PLAY_EDGE
		and player.prop and player.startascend
			ticnum = 1
		end
		if player.dotheflip
		or player.startascend
			ticnum = 1
		end

		if (ticnum and tails.tics > ticnum)
			tails.tics = ticnum
		end
		
		tails.color = player.mo.color
		tails.threshold = player.mo.z
		tails.movecount = player.panim
		tails.angle = player.drawangle
		tails.scale = player.mo.scale
		tails.destscale = player.mo.destscale
		tails.radius = player.mo.radius
		tails.height = player.mo.height
		tails.rollangle = player.mo.rollangle
		
		if P_MobjFlip(player.mo) == -1
			tails.eflags = $|MFE_VERTICALFLIP
			tails.flags2 = $|MF2_OBJECTFLIP
			zoffs = player.mo.height - tails.height - zoffs
		else
			tails.eflags = $&~MFE_VERTICALFLIP
			tails.flags2 = $&~MF2_OBJECTFLIP
		end
		if (player.mo.state > S_PLAY_SUPER_TRANS1 and player.mo.state < S_PLAY_SUPER_TRANS6)
			if player.followmobj and player.followmobj.valid
				player.followmobj.flags2 = $&~MF2_DONTDRAW
			end
		end
		P_TeleportMove(tails, 
			player.mo.x+P_ReturnThrustX(tails, tails.angle, FixedMul(backwards, tails.scale)),
			player.mo.y+P_ReturnThrustY(tails, tails.angle, FixedMul(backwards, tails.scale)),
			player.mo.z+zoffs)
		return true
	end
end, MT_TAILSOVERLAY)
addHook("PlayerThink", function(player)
	if player.valid and player.playerstate == PST_LIVE and not player.spectator
	and player.powers[pw_carry] != CR_NIGHTSMODE and player.mo.skin == "ntails"
		if (player.mo.state >= S_PLAY_SUPER_TRANS1 and player.mo.state <= S_PLAY_SUPER_TRANS6 or player.mo.state == S_TAILS_SWIPE)
			player.followitem = MT_NULL
		else
			player.followitem = MT_TAILSOVERLAY
		end
	end
end)
addHook('JumpSpecial', function(player)
	    if player.mo and player.mo.valid
			if player.mo.skin == "ntails"
               if (player.powers[pw_tailsfly] > 0) and (player.cmd.buttons & BT_JUMP)
                player.fly1 = 1
				end
			end
		end
end)