//Edited to prevent conflicts, remove colorization, and also disallow instashield use while holding a diamond or being a jettysyn in battle, and holding a flag in CTF
//Thank you Katmint!

freeslot(
	"MT_FINSTASHIELD",
	"S_FINSTASHIELD",
	"S_FINSTASHIELD1A",
	"S_FINSTASHIELD1B",
	"S_FINSTASHIELD2A",
	"S_FINSTASHIELD2B",
	"S_FINSTASHIELD3A",
	"S_FINSTASHIELD3B",
	"S_FINSTASHIELD4A",
	"S_FINSTASHIELD4B",
	"S_FINSTASHIELD5A",
	"S_FINSTASHIELD5B",
	"S_FINSTASHIELD6A",
	"S_FINSTASHIELD6B",
	"SPR_FWSP"
)

mobjinfo[MT_FINSTASHIELD] = {
	doomednum = -1,
	spawnhealth = 1,
	spawnstate = S_FINSTASHIELD,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	flags = MF_NOGRAVITY|MF_NOCLIPHEIGHT
}

states[S_FINSTASHIELD] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD1A}
states[S_FINSTASHIELD1A] = {SPR_FWSP, 0|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD1B}
states[S_FINSTASHIELD1B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD2A}
states[S_FINSTASHIELD2A] = {SPR_FWSP, 1|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD2B}
states[S_FINSTASHIELD2B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD3A}
states[S_FINSTASHIELD3A] = {SPR_FWSP, 2|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD3B}
states[S_FINSTASHIELD3B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD4A}
states[S_FINSTASHIELD4A] = {SPR_FWSP, 3|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD4B}
states[S_FINSTASHIELD4B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD5A}
states[S_FINSTASHIELD5A] = {SPR_FWSP, 4|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD5B}
states[S_FINSTASHIELD5B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_FINSTASHIELD6A}
states[S_FINSTASHIELD6A] = {SPR_FWSP, 5|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_FINSTASHIELD6B}
states[S_FINSTASHIELD6B] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_NULL}

local function InstaShield(player)
	if (player.mo) and (player.mo.skin == "fsonic") //sonic, now fsonic
	and not (player.pflags & PF_SHIELDABILITY) and not (player.pflags & PF_THOKKED) and not (player.pflags & PF_USEDOWN) and not player.powers[pw_shield] and not player.powers[pw_invulnerability] and not player.powers[pw_carry] and not player.powers[pw_super] and not player.gotcrystal and not player.isjettysyn and not player.gotflag
		player.invisiframe = 1
		S_StartSound(player.mo, sfx_s3k42)
		local instashield = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_FINSTASHIELD)
		instashield.target = player.mo
		instashield.scale = player.mo.scale*3/2
		player.tracer = instashield
		player.pflags = $1|PF_SHIELDABILITY & ~PF_SPINNING
		if (player.mo.eflags & MFE_VERTICALFLIP)
			instashield.eflags = $|MFE_VERTICALFLIP
		end
		player.instashield = 1
		return true
	end
end
	

addHook("PlayerThink", function(player)
	if (player.instashield == 1) and (P_IsObjectOnGround(player.mo) or player.powers[pw_carry])
		player.instashield = 0
		if (player.tracer and player.tracer.valid) and player.tracer.type == MT_FINSTASHIELD
			P_KillMobj(player.tracer)
		end
	end
	if (player.instashield == 1) and (player.invisiframe == 1)
		player.mo.frame = ($1 & FF_FRAMEMASK)|FF_FULLBRIGHT
	end
	if ((player.invisiframe == 1) and not (player.tracer and player.tracer.valid and player.tracer.type == MT_FINSTASHIELD))
		player.invisiframe = nil
	end
end)

addHook("JumpSpinSpecial", InstaShield)

local function InstaCheck(sonic, inflictor, source, damage, element)
	if (sonic.player) and sonic.player.tracer and sonic.player.tracer.valid and sonic.player.tracer.health and sonic.player.tracer.type == MT_FINSTASHIELD
		if not (element == DMG_INSTAKILL) and not (element == DMG_DROWNED) and not (element == DMG_SPACEDROWN) and not (element == DMG_DEATHPIT) and not (element == DMG_CRUSHED) and not (element == DMG_SPECTATOR)
			return false  //do not damage player while instashield is active
		end
	end
end

addHook("ShouldDamage", InstaCheck)

local function InstaCollide(insta, mobj) //instashield attacks function as an expanded roll hitbox and can damage things normal spins can't
	if not (insta.z-FixedMul(24*FRACUNIT, insta.scale) > mobj.z+mobj.height) and not(mobj.z-FixedMul(24*FRACUNIT, insta.scale) > insta.z+insta.height)
		if (mobj.valid and mobj.health and (mobj.flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) or (mobj.flags & MF_PUSHABLE and mobj.flags & MF_SHOOTABLE)))
			P_DamageMobj(mobj, insta, insta.target)
			if ((insta.target.momz < 0) and not (insta.target.eflags & MFE_VERTICALFLIP))
				P_SetObjectMomZ(insta.target, -insta.target.momz)
			elseif ((insta.target.momz > 0) and (insta.target.eflags & MFE_VERTICALFLIP))
				P_SetObjectMomZ(insta.target, insta.target.momz)
			end
			if (mobj.info.spawnhealth > 1)
				P_InstaThrust(insta.target, insta.target.angle, -insta.target.player.speed)
			end
		end
	else
		return nil
	end
end

addHook("MobjMoveCollide", InstaCollide, MT_FINSTASHIELD)
addHook("MobjCollide", InstaCollide, MT_FINSTASHIELD)
