// --------------------------------------
// Lua_Ice
// Ice ability!
// --------------------------------------
rawset(_G, "K_Ice", function(checkflags, destroy, late, player)
	if(checkflags)
		if(player.kvars.ablstate)
			return AF_NOFLOAT|AF_NODUCK|AF_NOJUMP|AF_NOSWIM|AF_NODROP
		end
		return 0
	end
	if(destroy)
		return
	end
	if(late)
		return
	end
	
	if(player.cmd.buttons & BT_USE)
		and not(player.kvars.prevcmd & BT_USE)
		and not(player.kvars.ablstate)
		and not(player.kvars.ducking)
		and not(player.kvars.floating)
		and not(player.pflags & PF_SLIDING)
		and not(player.powers[pw_carry] or player.kvars.prevcarry)
		and not(player.exiting)
		and not(player.pflags & PF_STASIS)
		and not(player.kvars.industdevil)
		player.kvars.ablstate = 1
	end
	
	if(player.kvars.ablstate)
		if not(player.cmd.buttons & BT_USE)
			or(player.pflags & PF_SLIDING)
			or(player.powers[pw_carry] or player.kvars.prevcarry)
			or(player.exiting)
			or(player.pflags & PF_STASIS)
			player.kvars.ablstate = 0
			if(player.mo.state == S_KIRBY_ICE1 or player.mo.state == S_KIRBY_ICE2)
				player.mo.state = S_PLAY_WALK
			end
		else
			if(player.powers[pw_nocontrol] <= 2)
				player.powers[pw_nocontrol] = 2
			end
			if(P_IsObjectOnGround(player.mo) and R_PointToDist2(player.cmomx, player.cmomy, player.mo.momx, player.mo.momy) < player.mo.scale)
				player.drawangle = player.mo.angle
				player.mo.state = S_KIRBY_ICE1
			else
				player.drawangle = $1 + ANGLE_22h
				player.mo.state = S_KIRBY_ICE2
			end
			player.mo.friction = FRACUNIT*89/90	// Icy!
			if(player.kvars.ablstate == 1)
				S_StartSound(player.mo, sfx_ice)
			end
			if(player.kvars.ablstate&1)
				local i = P_SPMAngle(player.mo, MT_ICEBREATH, player.drawangle, 0)
				if(i and i.valid)
					i.momx = ($1 + player.mo.momx)+FixedMul((P_RandomFixed()*4)-(2*FRACUNIT), player.mo.scale)
					i.momy = ($1 + player.mo.momy)+FixedMul((P_RandomFixed()*4)-(2*FRACUNIT), player.mo.scale)
					
					if(P_RandomByte()&1)
						i.state = $1 + 1
					end
				end
			end
			player.kvars.ablstate = ($1%10)+1	// :sweat_drops:
		end
	end
end)

local function friendlyPlayer(playermo1, playermo2)
	if not(playermo1.player and playermo1.player.valid)
		or not(playermo2.player and playermo2.player.valid)
		return false
	end
	
	local player1 = playermo1.player
	local player2 = playermo2.player
	
	if(gametyperules & GTR_FRIENDLY)
		or((gametyperules & GTR_TEAMS) and(player2.ctfteam == 0 or player2.ctfteam == player1.ctfteam))
		return true
	end
	
	return false
end
local function playerInvincible(mobj)
	if not(mobj.player and mobj.player.valid)
		return false
	end
	
	local player = mobj.player
	if(player.powers[pw_flashing])
		or(player.powers[pw_invulnerability])
		or(player.powers[pw_super])
		return true
	end
	
	return false
end

addHook("MobjMoveCollide", function(ice, mobj)
	if not((mobj.player and mobj.player.valid) or (mobj.flags & MF_ENEMY))
		or(mobj == ice.target)
		or(friendlyPlayer(ice.target, mobj))
		or not(mobj.flags & MF_SHOOTABLE)
		or(mobj.flags2 & MF2_FRET)
		or(playerInvincible(mobj))
		return false
	end
	
	if(mobj.flags & MF_BOSS)	// Just damage bosses normally
		return
	end
	
	if(mobj.health <= 1)
		or(mobj.player and mobj.player.valid)
		if(mobj.z <= ice.z+ice.height)
			and(mobj.z+mobj.height >= ice.z)
			local iceblock = P_SpawnMobj(mobj.x, mobj.y, mobj.z, MT_KIRBYICEBLOCK)
			S_StartSound(iceblock, sfx_ice)
			iceblock.scale = mobj.scale
			/*local scalemul = FixedDiv(mobj.height, iceblock.height)
			local radmul = FixedDiv(mobj.radius, iceblock.radius)
			if(radmul > scalemul)
				scalemul = radmul
			end
			iceblock.scale = FixedMul(mobj.scale, scalemul)*/
			iceblock.colorized = true
			iceblock.color = SKINCOLOR_ICY
			if(mobj.skin)
				iceblock.skin = mobj.skin
			end
			iceblock.sprite = mobj.sprite
			iceblock.sprite2 = mobj.sprite2
			iceblock.frame = mobj.frame
			iceblock.origdeathstate = mobjinfo[mobj.type].deathstate
			iceblock.origcolor = mobj.color
			iceblock.origdeathsound = mobjinfo[mobj.type].deathsound
			
			iceblock.angle = mobj.angle
			if(mobj.player and mobj.player.valid)
				iceblock.angle = mobj.player.drawangle
			end
			if(mobj.eflags & MFE_VERTICALFLIP)
				iceblock.eflags = $1|MFE_VERTICALFLIP
			end
			
			// Remove the objects
			if(mobj.player and mobj.player.valid)
				iceblock.trapped = mobj
				mobj.state = S_INKIRBYICE
			else
				server.kirbyremovemonitor = true
				P_KillMobj(mobj)
				P_RemoveMobj(mobj)
				server.kirbyremovemonitor = false
			end
			P_RemoveMobj(ice)
		end
		return false
	end
end, MT_ICEBREATH)

addHook("TouchSpecial", function(iceblock, mobj)
	if(mobj.state == S_INKIRBYICE)
		or not(iceblock.state == S_KIRBYICEBLOCK)
		return true
	end
//	local angle = R_PointToAngle2(mobj.x, mobj.y, iceblock.x, iceblock.y)
	local angle = R_PointToAngle2(0, 0, mobj.momx, mobj.momy)
	P_InstaThrust(iceblock, angle, FixedMul(iceblock.scale, mobjinfo[iceblock.type].speed))
	iceblock.flags = ($1 & !MF_SPECIAL)|MF_MISSILE
	S_StartSound(iceblock, sfx_spit)
	iceblock.target = mobj
	if(iceblock.trapped and iceblock.trapped.valid)
		iceblock.angle = angle
	end
	return true
end, MT_KIRBYICEBLOCK)

local function RandomOff(num)
	return (P_RandomByte()%num)-(num/2)
end
local function SpawnSparkles(mobj, spriteheight)
	local stype = MT_BALLSPARKLE
	local zoff = 8*mobj.scale*P_MobjFlip(mobj)
	local sparkle = P_SpawnMobj(mobj.x+(RandomOff(30)*mobj.scale), mobj.y+(RandomOff(30)*mobj.scale), mobj.z+(mobj.height/2)+(RandomOff(spriteheight)*mobj.scale)+zoff, stype)
	sparkle.scale = mobj.scale
	if(mobj.eflags & MFE_VERTICALFLIP)
		sparkle.eflags = $1|MFE_VERTICALFLIP
	end
	sparkle.color = SKINCOLOR_ICY
end

local function freeTrapped(iceblock)
	iceblock.trapped.flags = $1 & !(MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY)
	iceblock.trapped.flags2 = $1 & !MF2_DONTDRAW
	iceblock.trapped.state = S_PLAY_PAIN
	P_TeleportMove(iceblock.trapped, iceblock.trapped.x, iceblock.trapped.y, iceblock.trapped.z+P_MobjFlip(iceblock.trapped))
	P_InstaThrust(iceblock.trapped, iceblock.angle, -5*iceblock.scale)
	iceblock.trapped.momz = 5*iceblock.scale*P_MobjFlip(iceblock)
	S_StartSound(iceblock.trapped, sfx_pop)
	if(iceblock.trapped.player and iceblock.trapped.player.valid)
		iceblock.trapped.player.powers[pw_flashing] = TICRATE*3
	end
	iceblock.trapped = nil
end

local function useOrigDeath(iceblock)
	if(iceblock.trapped and iceblock.trapped.valid)
		freeTrapped(iceblock)
		P_RemoveMobj(iceblock)
	elseif(iceblock.origdeathstate)
		iceblock.state = iceblock.origdeathstate
		S_StartSound(iceblock, iceblock.origdeathsound)
		iceblock.color = iceblock.origcolor
		iceblock.colorized = false
	end
end
addHook("MobjThinker", function(iceblock)
	if(iceblock.state == S_KIRBYICEBLOCKDIE)
		and not(iceblock.origdeathstate == S_KIRBYICEBLOCKDIE)	// A
		useOrigDeath(iceblock)
		if not(iceblock and iceblock.valid)
			return
		end
	end
	if not(leveltime&3)
		and(iceblock.colorized)
		SpawnSparkles(iceblock, iceblock.height/iceblock.scale)
	end
	if(iceblock.flags & MF_MISSILE)
		iceblock.tics = -1
	end
	if(iceblock.trapped)
		iceblock.trapped.state = S_INKIRBYICE
		iceblock.trapped.frame = 0
		P_TeleportMove(iceblock.trapped, iceblock.x, iceblock.y, iceblock.z)
		if(iceblock.trapped.player and iceblock.trapped.player.valid)
			if not(iceblock.trapped.player.powers[pw_nocontrol])
				iceblock.trapped.player.powers[pw_nocontrol] = 1
			end
		end
		iceblock.trapped.momx = iceblock.momx
		iceblock.trapped.momy = iceblock.momy
		iceblock.trapped.momz = iceblock.momz
		iceblock.trapped.flags = $1|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY
		iceblock.trapped.flags2 = $1|MF2_DONTDRAW
		iceblock.skin = iceblock.trapped.skin
		iceblock.sprite = iceblock.trapped.sprite
		iceblock.sprite2 = iceblock.trapped.sprite2
		iceblock.frame = iceblock.trapped.frame
	end
end, MT_KIRBYICEBLOCK)
addHook("MobjDeath", useOrigDeath, MT_KIRBYICEBLOCK)
