freeslot("mt_cacoboss",
"s_cacobosscharge",
"s_cacobosslaser",
"s_cacobossspin",
"s_cacobossspin2",
"s_cacobosspinch",
"s_cacobosspinch2",
"s_cacobosspain",
"s_cacobosspain2",
"s_cacobossdie",
"s_cacobossdie2",
"s_cacobossdie3",
"mt_cacolaser",
"mt_laser_crackle",
"sfx_cacols")

function A_CacoEscape(actor, var1)
	if actor and actor.valid
		P_InstaThrust(actor, actor.angle, -50*FRACUNIT)
		P_SetObjectMomZ(actor, 10*FRACUNIT)
		P_SupermanLook4Players(actor)
		if actor.target 
			actor.angle = R_PointToAngle2(actor.x, actor.y, actor.target.x, actor.target.y)
		end
	end
end

function A_CacoLookForTarget(actor)
	if actor and actor.valid
		P_SupermanLook4Players(actor)
		if actor.target
			actor.angle = R_PointToAngle2(actor.x, actor.y, actor.target.x, actor.target.y) 
		end
	end
end

// Boss Thinker
addHook("MobjThinker", function(mo)
	mo.scale = 2*FRACUNIT
	mo.color = SKINCOLOR_ORANGE
	mo.hitground = $ or false
	
	// Charging Up...
	if mo.state == S_CACOBOSSCHARGE
	or mo.state == S_CACOBOSSPINCH
		local charge = P_SpawnMobj(mo.x + P_RandomRange(-50, 50)*FRACUNIT,
		mo.y + P_RandomRange(50, 50)*FRACUNIT,
		mo.z + P_RandomRange(0, 50)*FRACUNIT,
		MT_LASER_CRACKLE)
		local ang = R_PointToAngle2(charge.x, charge.y, mo.x, mo.y)
		charge.momx = $ - cos(ang) / 4
		charge.momy = $ - sin(ang) / 4
		charge.momz = $ - tan(ang) / 4
		charge.destscale = 1
		charge.fuse = TICRATE
		P_SupermanLook4Players(mo)
	end

	// Fire the caco boss laser!
	if mo.state == S_CACOBOSSLASER
		P_StartQuake(5*FRACUNIT, 5, {mo.x, mo.y, mo.z})
		if mo.target
			P_SpawnMissile(mo, mo.target, MT_CACOLASER)
			mo.angle = R_PointToAngle2(mo.x, mo.y, mo.target.x, mo.target.y)
		else
			P_SPMAngle(mo, MT_CACOLASER, mo.angle)
		end
		if (leveltime%5==0)
			local crackle = P_SpawnMobj(mo.x,mo.y,mo.z,MT_LASER_CRACKLE)
			crackle.momx = P_RandomRange(-20, 20)*FRACUNIT
			crackle.momy = P_RandomRange(-20, 20)*FRACUNIT
			crackle.momz = P_RandomRange(-20, 20)*FRACUNIT
			crackle.fuse = TICRATE
		end
		mo.momz = -FRACUNIT
	end
	
	//So many lasers!
	if mo.state == S_CACOBOSSPINCH2
		mo.hitground = false
		P_StartQuake(5*FRACUNIT, 5, {mo.x, mo.y, mo.z})
		P_SPMAngle(mo, MT_CACOLASER, mo.angle)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_45)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_90)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_90 + ANGLE_45)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_180)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_180 + ANGLE_45)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle + ANGLE_270)
		P_SPMAngle(mo, MT_CACOLASER, mo.angle - ANGLE_45)
		if (leveltime%5==0)
			local crackle = P_SpawnMobj(mo.x,mo.y,mo.z,MT_LASER_CRACKLE)
			crackle.momx = P_RandomRange(-20, 20)*FRACUNIT
			crackle.momy = P_RandomRange(-20, 20)*FRACUNIT
			crackle.momz = P_RandomRange(-20, 20)*FRACUNIT
			crackle.fuse = TICRATE
		end
		mo.angle = $ + ANG1
--		if leveltime%3==0 then mo.colorized = true else mo.colorized = false end
	end
	
	// Thrust Down
	if mo.state == S_CACOBOSSSPIN
	or mo.state == S_CACOBOSSPINCH
		P_SetObjectMomZ(mo, -10*FRACUNIT, true)
		P_SpawnGhostMobj(mo)

		// Rock Effect
		if P_IsObjectOnGround(mo) and mo.hitground == false
			S_StartSound(mo, sfx_rocks2)
			P_StartQuake(12*FRACUNIT, 5, {mo.x, mo.y, mo.z})
			for i = 1, 10
				local rock = P_SpawnMobj(mo.x, mo.y, mo.z, MT_FALLINGROCK)
				rock.momz = 10*FRACUNIT
				rock.destscale = 1
				P_Thrust(rock, P_RandomRange(0, 360)*ANG1, 10*FRACUNIT)
				rock.fuse = TICRATE/3
			end
			mo.hitground = true
		end

		// Spin Indicator
		if mo.state == S_CACOBOSSSPIN and P_IsObjectOnGround(mo)
			if not S_SoundPlaying(mo, sfx_s3kd9s)
				S_StartSound(mo, sfx_s3kd9s)
			end
		elseif mo.state ~= S_CACOBOSSSPIN and S_SoundPlaying(mo, sfx_s3kd9s)
			S_StopSound(mo, sfx_s3kd9s)
		end
	end
	
	// Chase
	if mo.state == S_CACOBOSSSPIN2
		mo.flags = $|MF_BOUNCE
		mo.hitground = false
		if P_IsObjectOnGround(mo)
			local rock = P_SpawnMobj(mo.x, mo.y, mo.z, MT_FALLINGROCK)
			rock.momz = 10*FRACUNIT
			rock.destscale = 1
			P_Thrust(rock, P_RandomRange(0, 360)*ANG1, 10*FRACUNIT)
			rock.fuse = TICRATE/3
			if not S_SoundPlaying(mo, sfx_mindig) then S_StartSound(mo, sfx_mindig) end
		end
		if mo.target
			P_Thrust(mo, R_PointToAngle2(mo.x, mo.y, mo.target.x, mo.target.y), 3*FRACUNIT)
		else
			P_Thrust(mo, mo.angle, 3*FRACUNIT)
		end
		P_SpawnGhostMobj(mo)
		mo.angle = $+5*ANG1
	else
		mo.flags = $ & ~MF_BOUNCE
	end
	
	// fun
	if mo.state == S_CACOBOSSLASER
	or mo.state == S_CACOBOSSSPIN2
	or mo.state == S_CACOBOSSPINCH
	or mo.state == S_CACOBOSSPINCH2
		if leveltime%3==0 then mo.colorized = true else mo.colorized = false end
	else
		mo.colorized = false
	end
	
	// Death
	if mo.state == S_CACOBOSSDIE
		if (leveltime%12==0)
			local explosion = P_SpawnMobj(mo.x + P_RandomRange(-50, 50)*FRACUNIT,
			mo.y + P_RandomRange(-50, 50)*FRACUNIT,
			mo.z + P_RandomRange(0, 50)*FRACUNIT,
			MT_BOSSEXPLODE)
			S_StartSound(explosion, sfx_cybdth)
		end
	elseif mo.state == S_CACOBOSSDIE2
		if (leveltime%5==0)
			local explosion = P_SpawnMobj(mo.x + P_RandomRange(-50, 50)*FRACUNIT,
			mo.y + P_RandomRange(50, 50)*FRACUNIT,
			mo.z + P_RandomRange(0, 50)*FRACUNIT,
			MT_BOSSEXPLODE)
			S_StartSound(explosion, sfx_cybdth)
			P_StartQuake(5*FRACUNIT, 5, {mo.x, mo.y, mo.z})
		end
	elseif mo.state == S_CACOBOSSDIE3
		mo.flags = $ & ~MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP
		
		if P_IsObjectOnGround(mo) then P_SetObjectMomZ(mo, 0) end
	end
end, MT_CACOBOSS)

// Laser Thinker
addHook("MobjThinker", function(mo)
--	mo.momz = -7*FRACUNIT
	mo.scale = FRACUNIT/2	
	
	if (leveltime%15==0)
		local crackle = P_SpawnMobj(mo.x,mo.y,mo.z,MT_LASER_CRACKLE)
		crackle.momx = P_RandomRange(-20, 20)*FRACUNIT
		crackle.momy = P_RandomRange(-20, 20)*FRACUNIT
		crackle.momz = P_RandomRange(-20, 20)*FRACUNIT
		crackle.fuse = 20
	end
end, MT_CACOLASER)

// Make sure the player cant damage boss while they're in certain states.
addHook("ShouldDamage", function(t, i, s, d)
	if t.type == MT_CACOBOSS
		if t.state == S_CACOBOSSSPIN2
		or t.state == S_CACOBOSSPINCH
			S_StartSound(t, sfx_s3k7b)
			if t.state == S_CACOBOSSSPIN2
				P_DamageMobj(i, t)
			end
			return false
		end
	end
end)