freeslot("MT_FREEZER_HSPAWNER", "MT_FREEZER_VSPAWNER", "MT_FREEZER_CSPAWNER", "MT_COLDFREEZER", "MT_ICEBALL", "SPR_ICEC", "S_ICECUBE_OVERLAY", "S_ICEBALL_ATTACK1")

states[S_ICECUBE_OVERLAY] = {SPR_ICEC, A|FF_PAPERSPRITE, 2, nil, 0, 0, S_NULL}

local spawner_table = {
MT_FREEZER_HSPAWNER,
MT_FREEZER_VSPAWNER,
MT_FREEZER_CSPAWNER
}

addHook("MobjSpawn", function(wind)
wind.spritexscale = $1 + FRACUNIT/4
wind.spriteyscale = $1 + FRACUNIT/4
end, MT_COLDFREEZER)

local function SpawnFreezeWind(mo, type)
	if (leveltime % 4) == 0
		if type == 1 //Horizontal Type
		local wind = P_SPMAngle(mo, MT_COLDFREEZER, mo.angle+P_RandomRange(-10, 10)*ANG1)
			/*
			if wind
			and wind.valid
			wind.color = SKINCOLOR_SKY
			wind.colorized = true
			A_SetScale(wind, FRACUNIT+FRACUNIT/2, 1)
			//P_SetObjectMomZ(wind, P_RandomRange(-2, 2)*FRACUNIT)
			end
			*/
		elseif type == 2 //Vertical Type
		local wind = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_COLDFREEZER)
			if wind
			and wind.valid
			S_StartSound(wind, wind.info.seesound)
			/*
			wind.color = SKINCOLOR_SKY
			wind.colorized = true
			A_SetScale(wind, FRACUNIT+FRACUNIT/2, 1)
			*/
			P_SetObjectMomZ(wind, wind.info.speed)
			P_InstaThrust(wind, P_RandomRange(0, 360)*ANG1, P_RandomRange(-2, 2)*FRACUNIT)
			end
		elseif type == 3 //Circle Type
		local wind = P_SPMAngle(mo, MT_COLDFREEZER, mo.angle)
			/*
			if wind
			and wind.valid
			wind.color = SKINCOLOR_SKY
			wind.colorized = true
			A_SetScale(wind, FRACUNIT+FRACUNIT/2, 1)
			//P_SetObjectMomZ(wind, P_RandomRange(-2, 2)*FRACUNIT)
			end
			*/
		end
	end
end

for k, v in ipairs(spawner_table)
	addHook("MobjThinker", function(mo)
		if mo
		and mo.valid
		and mo.health
			if mo.spawnpoint
			and mo.spawnpoint.valid
				if mo.spawnpoint.options & MTF_AMBUSH
				mo.reactiontime = 1983
				end
			end
			if mo.state == S_FREEZER_SPAWNER_SHOOT
				if mo.type != MT_FREEZER_CSPAWNER
					if mo.reactiontime > 0
					mo.reactiontime = $1 - 1
					SpawnFreezeWind(mo, k)
					else
					mo.reactiontime = mo.info.reactiontime
					mo.state = mo.info.spawnstate
					end
				else
				local factor = 1
					if mo.spawnpoint
					and mo.spawnpoint.valid
						if mo.spawnpoint.options & MTF_AMBUSH
						factor = -1
						end
					end
				SpawnFreezeWind(mo, 3)
				mo.angle = $1 + ANG2*factor
				end
			end
		end
	end, v)
end

addHook("MobjThinker", function(mo)
	if mo
	and mo.valid
		if not mo.calmdown then mo.calmdown = 0 end
		if mo.calmdown != 0
			mo.calmdown = $ - 1
		else
			if mo.target
			and mo.target.valid
			and mo.health != 0
				local distance_xy = R_PointToDist2(mo.x, mo.y, mo.target.x, mo.target.y) 
				local distance_z = P_AproxDistance(0, mo.target.z-mo.z)
				if distance_xy <= 320*FRACUNIT
				and distance_z <= 128*FRACUNIT
					mo.state = S_ICEBALL_ATTACK1
					mo.calmdown = TICRATE*2
				end
			end
		end
	end
end, MT_ICEBALL)
addHook("MobjThinker", function(mo)
	if mo
	and mo.valid
		mo.color = SKINCOLOR_SKY
		mo.colorized = true
		A_SetScale(mo, FRACUNIT+FRACUNIT/2, 1)
	end
end, MT_COLDFREEZER)

local hook_table = {
"MobjCollide",
"MobjMoveCollide"
}

for k, v in ipairs(hook_table)
	addHook(v, function(mo, wind)
		if mo
		and mo.valid
		and mo.health
			if wind
			and wind.valid
			and wind.health
			and wind.type == MT_COLDFREEZER
				if not (mo.z > wind.z+wind.height)
				and not (wind.z > mo.z+mo.height)
					if mo.iceball == false
					mo.icedensity = $1 + 1
					end
				end
			end
		end
	end, MT_ROLLOUTROCK)
end

local trans_table = {
[1] = FF_TRANS90,
[2] = FF_TRANS80,
[3] = FF_TRANS70,
[4] = FF_TRANS60,
[5] = FF_TRANS50,
[6] = FF_TRANS40,
[7] = FF_TRANS30,
[8] = FF_TRANS20,
[9] = FF_TRANS10,
[10] = 0
}

addHook("MobjThinker", function(mo)
	if mo
	and mo.valid
	and mo.health
		if mo.iceball == nil
		mo.iceball = false
		end
		if mo.icedensity == nil
		mo.icedensity = 0
		end
		if mo.iceball == false
			/*if (leveltime % 8) == 0
				if mo.icedensity > 0
				mo.icedensity = $1 - 1
				end
			end*/
			if mo.icedensity <= 0
				if mo.overlay
				and mo.overlay.valid
				P_RemoveMobj(mo.overlay)
				mo.overlay = nil
				end
			end
			if mo.icedensity > 0
				if mo.overlay == nil
				mo.overlay = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_OVERLAY)
				mo.overlay.color = SKINCOLOR_SKY
				mo.overlay.colorized = true
				mo.overlay.state = S_THOK
				mo.overlay.target = mo
				else
					if mo.overlay
					and mo.overlay.valid
					mo.overlay.tics = -1
					mo.overlay.angle = mo.angle
					mo.overlay.sprite = mo.sprite
					mo.overlay.frame = mo.frame|trans_table[max(1, min(10, mo.icedensity/17))]
					else
					mo.overlay = nil
					end
				end
				if mo.flags2 & MF2_DONTDRAW
				mo.flags2 = $1 & ~MF2_DONTDRAW
				end
			mo.fuse = mo.info.painchance
				//if mo.icedensity >= 5*TICRATE
				if mo.icedensity >= 1
				S_StartSound(mo, sfx_s3k80)
				mo.fuse = mo.info.painchance
				mo.color = SKINCOLOR_SKY
				mo.colorized = true
					if mo.overlay
					and mo.overlay.valid
					P_RemoveMobj(mo.overlay)
					mo.overlay = nil
					end
				mo.iceball = true
				end
			end
		elseif mo.iceball == true
		mo.color = SKINCOLOR_SKY
		mo.colorized = true
			if mo.add_effect == nil
			mo.add_effect = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_OVERLAY)
			mo.add_effect.target = mo
			mo.add_effect.color = SKINCOLOR_SKY
			mo.add_effect.colorized = true
			mo.add_effect.state = S_THOK
			else
				if mo.add_effect
				and mo.add_effect.valid
				mo.add_effect.blendmode = AST_ADD
				mo.add_effect.tics = -1
				mo.add_effect.angle = mo.angle
				mo.add_effect.sprite = mo.sprite
				mo.add_effect.frame = mo.frame
				else
				mo.add_effect = nil
				end
			end
			//if mo.flags2 & MF2_DONTDRAW
			//mo.flags2 = $1 & ~MF2_DONTDRAW
			//end
		mo.flags2 = $1|MF2_AMBUSH
		//mo.fuse = mo.info.painchance
			if mo.eflags & MFE_TOUCHWATER
			or mo.eflags & MFE_UNDERWATER
			local sector = mo.subsector.sector
				for rover in sector.ffloors()
					if rover
					and rover.valid
					and rover.flags & FF_EXISTS
					and rover.flags & FF_SWIMMABLE
						//if mo.z <= rover.topheight
						//and mo.z+mo.height >= rover.bottomheight
						if P_InsideANonSolidFFloor(mo, rover)
							if GetSecSpecial(rover.sector.special, 1) == 3 //Lava Detected
							P_SetObjectMomZ(mo, -FRACUNIT/2)
								if (leveltime % 4) == 0
								S_StartSound(mo, sfx_s3k4f)
								end
							local radius = FixedInt(mo.radius)
							local smoke = P_SpawnMobjFromMobj(mo, P_RandomRange(-radius, radius)*FRACUNIT, P_RandomRange(-radius, radius)*FRACUNIT, P_RandomRange(0, FixedInt(mo.height/4))*FRACUNIT, MT_SMOKE)
								if smoke
								and smoke.valid
								P_SetObjectMomZ(smoke, P_RandomRange(1, 4)*FRACUNIT)
								P_InstaThrust(smoke, P_RandomRange(0, 360)*ANG1, P_RandomRange(0, 4)*FRACUNIT)
								end
								if rover.t_slope
									if mo.z+mo.height <= P_GetZAt(rover.t_slope, mo.x, mo.y)
									and mo.z+mo.height >= rover.bottomheight
										if mo.fuse > 1
										mo.fuse = 1
										end
									end
								else
									if mo.z+mo.height <= rover.topheight
									and mo.z+mo.height >= rover.bottomheight
										if mo.fuse > 1
										mo.fuse = 1
										end
									end
								end
							else //No Lava, Just Water
							mo.flags2 = $1 & ~MF2_AMBUSH
							end
						end
					end
				end
			end
		end
	end
end, MT_ROLLOUTROCK)

addHook("TouchSpecial", function(special, mo)
	if special
	and special.valid
	and special.health
		if mo
		and mo.valid
		and mo.player
		and mo.player.playerstate == PST_LIVE
			if not mo.player.powers[pw_carry]
			and not P_PlayerInPain(mo.player)
			and not mo.player.powers[pw_flashing]
			and mo.player.powers[pw_shield] != SH_BUBBLEWRAP
			and mo.player.powers[pw_shield] != SH_ELEMENTAL
			and mo.iceinside == false
				if mo.player.powers[pw_shield] == SH_FLAMEAURA
				P_DamageMobj(mo)
				return true
				end
			//mo.icetime = $1 + 1
			//mo.icetime = 3*TICRATE
			P_ResetPlayer(mo.player)
			S_StartSound(mo, sfx_s3k80)
			mo.iceinside = true
			mo.momx = 0
			mo.momy = 0
			end
		end
	end
return true
end, MT_COLDFREEZER)

addHook("PlayerCmd", function(player, cmd)
	if player.mo
	and player.mo.valid
	and player.playerstate == PST_LIVE
		if player.mo.iceinside == true
		cmd.forwardmove = 0
		cmd.sidemove = 0
		end
	end
end)

addHook("JumpSpecial", function(player)
	if player.mo
	and player.mo.valid
	and player.playerstate == PST_LIVE
		if player.mo.iceinside == true
			if not (player.pflags & PF_JUMPDOWN)
			player.mo.icebreak = $1 - 1
			S_StartSound(player.mo, sfx_s3k94)
			player.mo.momx = P_RandomRange(-4, 4)*FRACUNIT
			player.mo.momy = P_RandomRange(-4, 4)*FRACUNIT
				for i = 0, 3
				local debris = P_SpawnMobjFromMobj(player.mo, 0, 0, FRACUNIT, MT_BROKENROBOT)
					if debris
					and debris.valid
					debris.state = S_ROCKCRUMBLEI
					P_SetObjectMomZ(debris, P_RandomRange(1, 8)*FRACUNIT)
					P_InstaThrust(debris, P_RandomRange(0, 360)*ANG1, P_RandomRange(1, 8)*FRACUNIT)
					end
				end
			end
		return true
		end
	end
end)

addHook("SpinSpecial", function(player)
	if player.mo
	and player.mo.valid
	and player.playerstate == PST_LIVE
		if player.mo.iceinside == true
		return true
		end
	end
end)

local icecube_frame = {
	[8] = A,
	[7] = B,
	[6] = B,
	[5] = C,
	[4] = C,
	[3] = D,
	[2] = D,
	[1] = E,
	[0] = E
}

addHook("PlayerThink", function(player)
	if player.mo
	and player.mo.valid
		if player.playerstate == PST_LIVE
			if player.mo.iceinside == nil
			player.mo.iceinside = false
			end
			if player.mo.icetime == nil
			player.mo.icetime = 0
			end
			if player.mo.icebreak == nil
			player.mo.icebreak = 0
			end
			if player.mo.iceinside == false
				if player.mo.iceblock
				//and player.mo.iceblock.valid
					for i = 0, 12
					local debris = P_SpawnMobjFromMobj(player.mo, 0, 0, FRACUNIT, MT_BROKENROBOT)
						if debris
						and debris.valid
						debris.state = S_ROCKCRUMBLEI
						P_SetObjectMomZ(debris, P_RandomRange(1, 8)*FRACUNIT)
						P_InstaThrust(debris, P_RandomRange(0, 360)*ANG1, P_RandomRange(1, 8)*FRACUNIT)
						end
					end
				S_StartSound(player.mo, sfx_shattr)
				//P_RemoveMobj(player.mo.iceblock)
				player.mo.iceblock = nil
				end
			player.mo.icetime = 3*TICRATE
			player.mo.icebreak = 8
				/*if player.mo.icetime > 0
				local radius = FixedInt(player.mo.radius)
					if (leveltime % 4) == 0
					local particle = P_SpawnMobjFromMobj(player.mo, P_RandomRange(-radius, radius)*FRACUNIT, P_RandomRange(-radius, radius)*FRACUNIT, P_RandomRange(0, FixedInt(player.mo.height))*FRACUNIT, MT_PARTICLE)
						if particle
						and particle.valid
						A_SetScale(particle, 1, 1)
						particle.sprite = SPR_SNO1
						particle.frame = P_RandomRange(0, 2)
						particle.tics = 15
						end
					player.mo.icetime = $1 - 1
					end
					if player.mo.icetime >= 3*TICRATE
					S_StartSound(player.mo, sfx_s3k80)
					player.mo.iceinside = true
					player.mo.momx = 0
					player.mo.momy = 0
					end
				end*/
			else
			player.mo.state = S_PLAY_PAIN
			player.mo.icetime = $1 - 1
				if player.mo.iceblock == nil
				player.mo.iceblock = {}
					for i = 1, 4
					player.mo.iceblock[i] = P_SpawnMobjFromMobj(player.mo, 0, 0, 0, MT_THOK)
					player.mo.iceblock[i].state = S_ICECUBE_OVERLAY
					end
				else
					for i = 1, 4
						if player.mo.iceblock[i]
						and player.mo.iceblock[i].valid
						player.mo.iceblock[i].state = S_ICECUBE_OVERLAY
						player.mo.iceblock[i].angle = ANGLE_90*i
						P_TeleportMove(player.mo.iceblock[i], player.mo.x+FixedMul(32*FRACUNIT, cos(player.mo.iceblock[i].angle-ANGLE_90)), player.mo.y+FixedMul(32*FRACUNIT, sin(player.mo.iceblock[i].angle-ANGLE_90)), player.mo.z)
						player.mo.iceblock[i].frame = icecube_frame[player.mo.icebreak]|FF_PAPERSPRITE
						end
					end
				end
				if player.mo.icetime <= 0
				P_DamageMobj(player.mo)
				player.mo.iceinside = false
				//S_StartSound(player.mo, sfx_shattr)
				end
				if player.mo.icebreak <= 0
				P_DoPlayerPain(player)
				player.mo.iceinside = false
				player.mo.icetime = 0
				//S_StartSound(player.mo, sfx_shattr)
				end
			end
		else
			if player.mo.iceblock
			//and player.mo.iceblock.valid
				for i = 0, 12
				local debris = P_SpawnMobjFromMobj(player.mo, 0, 0, FRACUNIT, MT_BROKENROBOT)
					if debris
					and debris.valid
					debris.state = S_ROCKCRUMBLEI
					P_SetObjectMomZ(debris, P_RandomRange(1, 8)*FRACUNIT)
					P_InstaThrust(debris, P_RandomRange(0, 360)*ANG1, P_RandomRange(1, 8)*FRACUNIT)
					end
				end
			S_StartSound(player.mo, sfx_shattr)
			//P_RemoveMobj(player.mo.iceblock)
			player.mo.iceblock = nil
			end
		end
	end
end)

addHook("MobjDamage", function(mo)
	if mo
	and mo.valid
	and mo.player
	and mo.player.playerstate == PST_LIVE
		if mo.iceinside == true
			if mo.icetime > 0
			S_StartSound(mo, sfx_shattr)
			mo.icetime = 0
			mo.iceinside = false
			end
		end
	end
end, MT_PLAYER)