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 == nil 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_YGUNLOOK then
			mo.momz = zdiff/5
		end
	
		if mo.state == S_YGUNACTIVE and mo.fuel == true then
			S_StartSound(mo, 440)
			mo.state = S_YGUNZOOM0 // dash once
			mo.fuel = false
			mo.attackmode = false
			mo.flags = 4196869// MF2_DONTDRAW
		end
		
		if mo.fuel == false and mo.state == S_YGUNLOOK then
			mo.potshot = true // shoot quick next time a target is found
		end
		
		if mo.potshot == true and mo.state == S_YGUNACTIVE then
			mo.state = S_YGUNSHOOT1
		end
		if mo.state >= S_YGUNSHOOT3 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_YGUNLOOK
			mo.aim = 0 
			mo.truetarget = 0
		end //--//
		
		if mo.chasedistance > 425*FRACUNIT and mo.attackmode == false and mo.state != S_YGUNZOOM0 and mo.state != S_YGUNZOOM1 then
			mo.attackmode = true
			mo.state = S_YGUNSHOOT1 //
		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 == nil 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_YGUNBBULLET3 and mo.homintime > TICRATE*2 then
			mo.state = S_YGUNBBULLET4
			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_YGUNBBULLET3 or state == S_YGUNBBULLET2 then
			P_InstaThrust(mo, mo.angle, FixedMul(36*FRACUNIT, mo.scale))
		end
		
		if mo.homeingdistance < 51*FRACUNIT then
			mo.tracer = nil
		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 = nil
		end
		
		if mo.valid and mo.state == S_YGUNTAR1 then
			if mo.creator.valid and mo.creator and mo.creator.seeabule == true then
			mo.state = S_YGUNTAR1 // stay alive
			end
		else
			tar = nil
		end
	end
end, MT_TURBOTARGET)

addHook("MobjThinker", function(mo)
	local tar = mo.target
	
	if mo.roostx == nil
		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)