freeslot("MT_TURBOBUZZ","MT_TURBBULLET","MT_TURBOWAYPOINT","MT_TURBOTARGET","MT_ANTITAILSUNIT")

function A_FaceAim(actor, var1, var2)
	local aim = actor.aim
	local tar = actor.target
		if actor.truetargetset == false and aim and aim.valid then
		actor.angle = R_PointToAngle2(actor.x, actor.y, aim.x, aim.y)
		actor.target = aim
		elseif tar and tar.valid  then
		actor.angle = R_PointToAngle2(actor.x, actor.y, tar.x, tar.y)
		end
end

addHook("MobjThinker", function(mo)
if mo.health > 0 then //--//
	local tar = mo.target
 if mo.fuel == nill then
	mo.fuel = true
	mo.aim = 0
	mo.potshot = false
	mo.chasedistance = 0
	mo.otherchasedistance = 0
	mo.truetarget = 0
	mo.truetargetset = false
	mo.seeabule = 0
	mo.startangle = mo.angle
 end
	// should always be 56 fracunits above the floor
	mo.floorbelow = 56*FRACUNIT+P_FloorzAtPos(mo.x, mo.y, mo.z, mo.height)
	local zdiff = mo.floorbelow-mo.z
	if mo.flags2&MF2_AMBUSH and mo.z != mo.floorbelow and mo.state != S_TBUZLOOK then
	mo.momz = zdiff/5
	end

	if mo.state == S_TBUZACTIVE and mo.fuel == true then
	S_StartSound(mo, 440)
	mo.state = S_TBUZZOOM0 // dash once
	mo.fuel = false
	mo.attackmode = false
	mo.flags = 4196869// MF2_DONTDRAW
	end
	
	if mo.fuel == false and mo.state == S_TBUZLOOK then
	mo.potshot = true // shoot quick next time a target is found
	end
	
	if mo.potshot == true and mo.state == S_TBUZACTIVE then
		mo.state = S_TBUZSHOOT1
	end
	if mo.state >= S_TBUZSHOOT3 then
		mo.potshot = false
	end
	
	if tar and tar.valid then //--//

		if tar.type != MT_TURBOTARGET then
		mo.truetarget = mo.target
		//print("work!")
		end
		mo.seeabule = P_CheckSight(mo, tar)
		
		mo.chasedistance = (P_AproxDistance(tar.x - mo.x, tar.y - mo.y))
			// place aim target on player
			if mo.aim == 0 and mo.seeabule == true and tar.type != MT_TURBOTARGET then
			mo.aim = P_SpawnMobj(mo.x+FixedMul(1*FRACUNIT, cos(mo.angle)),  
			mo.y+FixedMul(1*FRACUNIT, sin(mo.angle)), mo.z+(1*FRACUNIT), MT_TURBOTARGET)
			mo.aim.creator = mo
			mo.aim.target = tar
			end
			if mo.truetarget != 0 and mo.truetarget.valid then
				mo.otherchasedistance = (P_AproxDistance(mo.truetarget.x - mo.x, mo.truetarget.y - mo.y))
				if mo.chasedistance < 150*FRACUNIT then // avoid strange behavure when player is up close
				mo.target = mo.truetarget
				mo.truetargetset = true
				else
				mo.truetargetset = false
				end
			end
	else
	mo.state = S_TBUZLOOK
	mo.aim = 0 
	mo.truetarget = 0
	end //--//
	
	if mo.chasedistance > 425*FRACUNIT and mo.attackmode == false and mo.state != S_TBUZZOOM0 and mo.state != S_TBUZZOOM1 then
		mo.attackmode = true
		mo.state = S_TBUZSHOOT1 //
	elseif mo.attackmode == true and mo.fuel == false then
	// slow down over time
			if mo.momx > 32*FRACUNIT then
				mo.momx = $-2*FRACUNIT 
			end
			
			if mo.momy > 32*FRACUNIT then
				mo.momy = $-2*FRACUNIT 
			end
			
			if mo.momx < -32*FRACUNIT then
				mo.momx = $+2*FRACUNIT 
			end
			
			if mo.momy < -32*FRACUNIT then
				mo.momy = $+2*FRACUNIT 
			end
			// if you too slow damage your self
			//if mo.momy > -10*FRACUNIT and mo.momy < 10*FRACUNIT and mo.momx > -10*FRACUNIT and mo.momx < 10*FRACUNIT then
			//P_DamageMobj(mo)
			//end
			if mo.chasedistance > 1900*FRACUNIT then // if target is really far away move very slowly back
				local actionspd = 2*FRACUNIT 
					if mo.eflags&MFE_UNDERWATER
					actionspd = $*2/3
					end
				P_InstaThrust(mo, mo.startangle, FixedMul(-actionspd, mo.scale))
			elseif mo.momx < 32*FRACUNIT and mo.momx > -32*FRACUNIT and mo.momy < 32*FRACUNIT and mo.momy > -32*FRACUNIT then
				local actionspd = 25*FRACUNIT 
					if mo.eflags&MFE_UNDERWATER
					actionspd = $*2/3
					end
				if mo.potshot == true then
					P_InstaThrust(mo, mo.startangle, FixedMul(-actionspd, mo.scale))
				else
					P_InstaThrust(mo, mo.startangle, FixedMul(actionspd, mo.scale))
				end
			end
	end

end--//
end, MT_TURBOBUZZ)

addHook("MobjThinker", function(mo)

	if mo.once == nill then
	S_StartSound(mo, 475)
	mo.once = true
	mo.setfire = true
	mo.homintime = 1
		if mo.target.valid and mo.target.aim then
		mo.tracer = mo.target.aim
		mo.startangle = mo.target.angle
		end
	end
	
	if mo.homintime and mo.homintime > 0 then
		mo.homintime = $+1
		if mo.state == S_TBUZBBULLET3 and mo.homintime > TICRATE*2 then
			mo.state = S_TBUZBBULLET4
			mo.homintime = 0
		end
	end
	
	if mo.momz > 0 then // do not aim up
	mo.momz = 0
	end
	
	// set homing projectile
	if mo.tracer and mo.tracer.valid then
		mo.angle = R_PointToAngle2(mo.x, mo.y, mo.tracer.x, mo.tracer.y)
		mo.homeingdistance = (P_AproxDistance(mo.tracer.x - mo.x, mo.tracer.y - mo.y))
		
		if state == S_TBUZBBULLET3 or state == S_TBUZBBULLET2 then
		P_InstaThrust(mo, mo.angle, FixedMul(36*FRACUNIT, mo.scale))
		end
		
		if mo.homeingdistance < 51*FRACUNIT then
		mo.tracer = nill
		elseif  mo.homeingdistance < 150*FRACUNIT and mo.tracer.z <= mo.z then // fall faster if close
		P_SetObjectMomZ(mo, -1*FRACUNIT, true)
		end
	end
	
	if mo.state == S_SONIC3KBOSSEXPLOSION1 and mo.setfire == true then
		mo.setfire = false
		// creater alternative spawn postion?
		P_SpawnMobj(mo.x, mo.y, mo.z,  	MT_CYBRAKDEMON_FLAMEREST)
	end

end, MT_TURBBULLET)

addHook("MobjThinker", function(mo)
	local tar = mo.target
	if tar and tar.valid then
	
	P_TeleportMove(mo, (tar.x+(tar.momx*12)), (tar.y+(tar.momy*12)), tar.z)
		if tar.health < 1 then
		P_RemoveMobj(mo)
		tar = nill
		end
		
			if mo.valid and mo.state == S_TBUZTAR1 then
				if mo.creator.valid and mo.creator and mo.creator.seeabule == true then
				mo.state = S_TBUZTAR1 // stay alive
				end
			else
				tar = nill
			end
	end
	
end, MT_TURBOTARGET)

addHook("MobjThinker", function(mo)
	local tar = mo.target
	
	if mo.roostx == nill then
		mo.roostx = mo.x
		mo.roosty = mo.y
		mo.roostz = mo.z
		mo.attackstate = false
		mo.roostangle = 0
		mo.color = SKINCOLOR_GOLD
	end
	local xdiff = mo.roostx-mo.x
	local ydiff = mo.roosty-mo.y
	local zdiff = mo.roostz-mo.z
	mo.roostangle = R_PointToAngle2(mo.x, mo.y, mo.roostx, mo.roosty)
	if mo.health > 0 then
		if tar and tar.valid then // add hight limit
			if tar.z >= mo.z and P_CheckSight(mo, tar) == true and tar.z < (mo.z+1300*FRACUNIT) then
			mo.state = S_ATULOOKZOOM1
			mo.attackstate = true
			elseif mo.attackstate == true then
			mo.state = S_ATUWATCH1
			mo.attackstate = false
			end
		else
		mo.state = S_ATULOOK1
		end
		if mo.attackstate == false and mo.x != mo.roostx and mo.y != mo.roosty and mo.z != mo.roostz then
			if xdiff/16 > 38*FRACUNIT then
			mo.momx = 38*FRACUNIT
			elseif xdiff/16 < -38*FRACUNIT
			mo.momx = -38*FRACUNIT
			else
			mo.momx = xdiff/16
			end
			if ydiff/16 > 38*FRACUNIT then
			mo.momy = 38*FRACUNIT
			elseif ydiff/16 < -38*FRACUNIT
			mo.momy = -38*FRACUNIT
			else
			mo.momy = ydiff/16
			end
			if zdiff/16 > 38*FRACUNIT then
			mo.momz = 38*FRACUNIT
			elseif zdiff/16 < -38*FRACUNIT
			mo.momz = -38*FRACUNIT
			else
			mo.momz = zdiff/16
			end
		end
	end
	
end, MT_ANTITAILSUNIT)

//------------------------death states / removed tell parrent objects that there gone-------------//
addHook("MobjDeath", function(mo, inflictor, damagetype)

	if mo.aim and mo.aim.valid then
		P_RemoveMobj(mo.aim)
	end
end, MT_TURBOBUZZ)

addHook("MobjRemoved", function(mo)
	if mo.creator and mo.creator.valid then
		mo.aim = 0
		mo.creator = 0
	end
end, MT_TURBOTARGET)

addHook("ShouldDamage", function(mo, moinflictor, mosource, damage, damagetype) // no contact damage from touching turbo buzz
	if moinflictor != nil and moinflictor.valid and (moinflictor.type == MT_TURBOBUZZ) then
		return false
	end
end,  	MT_PLAYER )

addHook("ShouldDamage", function(mo, moinflictor, mosource, damage, damagetype) // no contact damage from touching turbo waypoint
	if moinflictor != nil and moinflictor.valid and (moinflictor.type == MT_TURBOWAYPOINT) then
		return false
	end
end,  	MT_PLAYER )

//----- turbo buzz does nothing to players---//
addHook("TouchSpecial", function(touchwaypoint, mo) 
	if mo.type != MT_TURBOBUZZ then // only stop turbobuz
	//print("playertouch")
		return true
	end

end, MT_TURBOWAYPOINT)