// This script contains functionality to allow bots to watch their own health and call for health when
// they are below a certain health value.

if(ScriptGoals.mount_vehicle == null)
{
	ScriptGoals.mount_vehicle = table();
	
	// The name for this goal
	ScriptGoals.mount_vehicle.Name = "mount_vehicle";
	
	////////////////////////////////////////////////////////////////////////////////
	// A debug flag for enabling/disabling printed messages. Useful for debugging this goal.
	ScriptGoals.mount_vehicle.Debug = false;
	
	////////////////////////////////////////////////////////////////////////////////
	// Script Goal Options
	// This script implements 2 aim modes while mounted.	
	ScriptGoals.mount_vehicle.aimModes =
	{
		// vehicleVelocity makes the bot aim in the direction the vehicle is moving
		vehicleVelocity = function()
		{
			vehicleVelocity = GetEntVelocity(this.scriptgoaldata.vehicleEntity);
			
			if(vehicleVelocity && !vehicleVelocity.IsZero())
			{
				vehicleVelocity.Normalize();
				this.scriptgoaldata.aimDirection = vehicleVelocity;
			}		
		},
		
		// random360 will allow the bot to aim in random directions in a 360 degree arc, changing direction at defined intervals. 
		// see ScriptGoals.mount_vehicle.aimAdjustDelay
		random360 = function()
		{
			// Is it time to adjust our aim?
			currentTime = GetTime();
			if(this.scriptgoaldata.aimAdjust <= currentTime)
			{
				this.scriptgoaldata.aimDirection.RotateAroundZ(RandRange(0.0, 360.0));

				// Schedule the next aim.
				this.scriptgoaldata.aimAdjust = currentTime + ScriptGoals.mount_vehicle.aimAdjustDelay;						
			}
		},		
	};
	
	////////////////////////////////////////////////////////////////////////////////
	// Set which aim mode you want to use.
	ScriptGoals.mount_vehicle.useAimMode = ScriptGoals.mount_vehicle.aimModes.vehicleVelocity;	
	////////////////////////////////////////////////////////////////////////////////
	// The delay between aim adjustments. Only applies to random360 aim mode.
	ScriptGoals.mount_vehicle.aimAdjustDelay = 5000;	
	////////////////////////////////////////////////////////////////////////////////
	// The rate at which the pan360 goal will pan, in degrees
	ScriptGoals.mount_vehicle.aimPanRate = 1.0;	
	////////////////////////////////////////////////////////////////////////////////
	ScriptGoals.mount_vehicle.watchForMountableVehiclesFailed = function(bot)
	{
		bot.SetScriptControlled(false);
		bot.scriptgoal = null;
		bot.scriptgoaldata = null;
		
		if( ScriptGoals.mount_vehicle.Debug )
		{
			print("ScriptGoals.mount_vehicle.watchForMountableVehicles Failed");
		}
	};	
	////////////////////////////////////////////////////////////////////////////////
	ScriptGoals.mount_vehicle.watchForMountableVehicles = function()
	{
		if( ScriptGoals.mount_vehicle.Debug )
		{
			print("ScriptGoals.mount_vehicle.watchForMountableVehicles");
		}
		
		framecounter = 0;
		while(true)
		{
			// Do we have this goal already?
			if(this.scriptgoal == ScriptGoals.mount_vehicle.Name)
			{
				vehicleEntity = this.scriptgoaldata.vehicleEntity;
				
				// Is the vehicle already mounted?
				vehicleFlags = GetEntFlags(vehicleEntity);
			
				// Am I mounted?
				myflags = GetEntFlags(this.GetGameEntity());
				
				if(!(myflags & ENTFLAG.MOUNTED))
				{
					// If the tank is already mounted, someone beat us to it, so fail.
					if(vehicleFlags & ENTFLAG.MOUNTED)
					{
						ScriptGoals.mount_vehicle.watchForMountableVehiclesFailed(this);
						
						if(ScriptGoals.mount_vehicle.Debug)
						{
							print("Someone beat me to it");
						}
					}
					else
					{
						vehPos = GetEntPosition(vehicleEntity);
					
						// If we lose sight of it, let's abandon the goal.
						// This should cover the case of when we die.
						if(!vehPos || !this.HasLineOfSightTo(vehPos, vehicleEntity))
						{
							ScriptGoals.mount_vehicle.watchForMountableVehiclesFailed(this);							
						}
						else
						{
							// Still available, so lets go for it.
							framecounter += 1;
							
							// Not mounted, lets try to get mounted.
							this.MoveTowards(vehPos);						
							
							// A simple way to get the but to hit the use key and let off each frame.
							if(framecounter & 1)
							{
								this.PressButton(BTN.USE);
							}
						}						
					}					
				}
				else
				{				
					// Wohoo we're mounted. Let's do some simple logic for aiming the gun toward where the vehicle is going.
					
					// Allow the current aim mode to do any processing to change the aimDirection
					aimFunc = ScriptGoals.mount_vehicle.useAimMode;
					this:aimFunc();					
					
					// If the vehicle is moving & we have no target. let's face the direction of movement.
					if(!this.HasTarget())
					{						
						this.TurnToFacing(this.scriptgoaldata.aimDirection);
					}
				}
				
				yield();
				continue;
			}
		
			// Look for a vehicle to mount.
			vehicle = this.GetNearest(CAT.MOVER, CLASS.VEHICLE);
			if(vehicle)
			{
				// What's my current health/armor.
				vehicleArmorTable = GetEntHealthAndArmor( vehicle );
							
				// Found something. Is it mountable?
				vehicleFlags = GetEntFlags(vehicle);
				
				// Is it mountable AND not already mounted?
				if((vehicleFlags & ENTFLAG.MOUNTABLE) && !(vehicleFlags & ENTFLAG.MOUNTED))
				{
					if(ScriptGoals.mount_vehicle.Debug)
					{
						print("Mountable and not mounted", vehicleArmorTable.CurrentHealth);	
					}
					
					this.SetScriptControlled(true);
					
					// Set our script goal to the name of this goal. This name will show in the first person HUD for the bot.
					this.scriptgoal = ScriptGoals.mount_vehicle.Name;
					
					// make a table to hold extra goal data in.
					aimStart = GetEntFacing(vehicle);
					aimAdjustTime = GetTime() + ScriptGoals.mount_vehicle.aimAdjustDelay;
					this.scriptgoaldata = 
					{
						aimDirection = aimStart,
						aimAdjust = aimAdjustTime,
						vehicleEntity = vehicle
					};
				}
				else
				{
					if(ScriptGoals.mount_vehicle.Debug)
					{
						print("Not Mountable or already mounted!", vehicleArmorTable.CurrentHealth);
					}
				}				
			}
			sleep(1);
		}
	};
}

// Add the following snippet somewhere, such as a spawn callback to use this goal

// Make sure we don't have the thread already.
//if(this.WatchForVehicleThread == null)
//{
//	this.WatchForVehicleThread  = this:thread(ScriptGoals.mount_vehicle.watchForMountableVehicles);		
//}

