//instashield katsy version
//lua ported over to 2.2, new insta-shield sprites, and bug-fixes by DirkTheHusky

freeslot(
	"MT_INSTASHIELD",
	"MT_INSTAHIT",
	"S_INSTASHIELD",
	"S_INSTASHIELD1",
	"S_INSTASHIELD1B",
	"S_INSTASHIELD2",
	"S_INSTASHIELD2B",
	"S_INSTASHIELD3",
	"S_INSTASHIELD3B",
	"S_INSTASHIELD4",
	"S_INSTASHIELD4B",
	"S_INSTASHIELD5",
	"S_INSTASHIELD5B",
	"S_INSTASHIELD6",
	"S_INSTASHIELD6B",
	"S_INSTASHIELD7",
	"S_INSTASHIELD7B",
	"S_INSTAHIT",
	"S_INSTAHIT1",
	"S_INSTAHIT2",
	"SPR_TWSP"
)

assert(VERSION ~= nil, "script does not support game version")

//soc crap
mobjinfo[MT_INSTAHIT] = {
	doomednum = -1,
	spawnhealth = 1,
	spawnstate = S_INSTAHIT1,
	radius = 64*FRACUNIT,
	height = 64*FRACUNIT,
	flags = MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT
}

mobjinfo[MT_INSTASHIELD] = {
	doomednum = -1,
	spawnhealth = 1,
	spawnstate = S_INSTASHIELD1,
	radius = 32*FRACUNIT,
	height = 32*FRACUNIT,
	flags = MF_NOGRAVITY|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY|MF_NOCLIPHEIGHT
}

states[S_INSTAHIT1] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTAHIT2}
states[S_INSTAHIT2] = {SPR_NULL, 0, 1, A_CapeChase, 0, 0, S_INSTAHIT1}

states[S_INSTASHIELD1] = {SPR_TWSP, 0|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD2}
states[S_INSTASHIELD2] = {SPR_TWSP, 1|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD3}
states[S_INSTASHIELD3] = {SPR_TWSP, 2|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD4}
states[S_INSTASHIELD4] = {SPR_TWSP, 3|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD5}
states[S_INSTASHIELD5] = {SPR_TWSP, 4|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD6}
states[S_INSTASHIELD6] = {SPR_TWSP, 5|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD7}
states[S_INSTASHIELD7] = {SPR_TWSP, 6|FF_FULLBRIGHT, 1, A_CapeChase, 0, 0, S_INSTASHIELD1}

//the main fucntion that spawns the instashield
local function InstaShield(sonic)
	local player = sonic.player
	if not (player.mo and player.mo.skin == "s3sonic") return end
	if player.cmd.buttons & BT_USE
	and P_IsObjectOnGround(player.mo) 
		player.useground = 1
	end
	if not (player.cmd.buttons & BT_USE)
		player.useground = nil
	end
	if (player.cmd.buttons & BT_USE)
	and not (player.powers[pw_carry] == CR_NIGHTSMODE)
	and not (player.powers[pw_carry])
	and not (player.pflags & PF_SLIDING)
	and not (player.pflags & PF_THOKKED)
	and (player.pflags & PF_JUMPED)
	and not P_PlayerInPain(player)
	and not (player.exiting)
	and not P_IsObjectOnGround(sonic)
	and not player.useground
	and not (player.instashield == 1)
	and not player.powers[pw_shield]
		player.invisiframe = 1
		S_StartSound(player.mo, sfx_s3k42)
		local instahit = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_INSTAHIT)
		instahit.target = player.mo
		instahit.scale = player.mo.scale
		instahit.fuse = 7
		player.tracer = instahit
		local instashield = P_SpawnMobj(player.mo.x, player.mo.y, player.mo.z, MT_INSTASHIELD)
		instashield.target = player.mo
		instashield.scale = player.mo.scale * 3/4
		instashield.fuse = 7
		player.instashield = 1
		player.pflags = $ | PF_THOKKED
	end
	if (player.powers[pw_carry])
		player.useground = 1
		player.instashield = 0
	end
	if (player.instashield == 1)
	and P_IsObjectOnGround(sonic)
		player.instashield = 0
		if (player.tracer and player.tracer.valid)
		and player.tracer.type == MT_INSTAHIT
		P_KillMobj(player.tracer)
		end
	end
	
	if (player.instashield == 1) and (player.invisiframe == 1) and not (player.mo.state == S_PLAY_SPRING) and not (player.mo.state == S_PLAY_PAIN)
		player.mo.frame = ($1 & FF_FRAMEMASK)|TR_TRANS60
	end
	if (player.invisiframe == 1) and not (player.tracer and player.tracer.valid and player.tracer.type == MT_INSTAHIT)
		player.invisiframe = nil
	end
	if player.mo.state == S_PLAY_SPRING
		player.invisiframe = nil
	end
end

addHook("MobjThinker", InstaShield, MT_PLAYER)

//this makes stuff not damage sonic while the instashield is being used
local function InstaCheck(sonic, source)
	if ((sonic) and (sonic.player and sonic.skin == "s3sonic") and (sonic.player.tracer and sonic.player.tracer.valid) and ((sonic.player.tracer and sonic.player.tracer.health and sonic.player.tracer.valid) and sonic.player.tracer.type == MT_INSTAHIT)) 
		return false
	end
end

addHook("ShouldDamage", InstaCheck, MT_PLAYER)

local function InstaCollide(insta, mobj)
	if not (insta.z+(1*FRACUNIT) > mobj.z+mobj.height)
	and not(mobj.z+(1*FRACUNIT) > insta.z+insta.height)
		if (mobj.valid and mobj.health and mobj.flags & (MF_ENEMY|MF_BOSS))
			P_DamageMobj(mobj, insta, insta.target)
	//		P_SetObjectMomZ(insta.target, insta.target.momz-insta.target.momz*2)bt
		end
		if (mobj.valid and mobj.health and mobj.flags & MF_MONITOR)
			P_KillMobj(mobj, insta, insta.target)
	//		P_SetObjectMomZ(insta.target, insta.target.momz-insta.target.momz*2)
			end
	else
		return nil
	end
end

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

//flip instashield stuff if the player is flipped

local function InstaFlip(inst)
	if inst.target
		inst.eflags = ((inst.target.eflags & MFE_VERTICALFLIP) and ($1|MFE_VERTICALFLIP) or ($1 & ~MFE_VERTICALFLIP))
	end
end

addHook("MobjThinker", InstaFlip, MT_INSTASHIELD)
addHook("MobjThinker", InstaFlip, MT_INSTAHIT)
