// bounty game support

function BountyGame::onAIRespawn(%game, %client)
{
   //add the default task
	if (! %client.defaultTasksAdded)
	{
		%client.defaultTasksAdded = true;
	   %client.addTask(AIPickupItemTask);                                             
	   %client.addTask(AIUseInventoryTask);
	   %client.addTask(AITauntCorpseTask);
		%client.addTask(AIEngageTurretTask);
		%client.addTask(AIDetectMineTask);
		%client.addTask(AIBountyPatrolTask);
		%client.bountyTask = %client.addTask(AIBountyEngageTask);
	}

   //set the inv flag
   %client.spawnUseInv = true;
}

function BountyGame::AIInit(%game)
{
   AIInit();
}

function BountyGame::aiBountyAssignTarget(%game, %client, %target)
{
	if (!isObject(%client.bountyTask))
		%client.bountyTask = %client.addTask(AIBountyEngageTask);
	%task = %client.bountyTask;

   %task.baseWeight = $AIWeightKillFlagCarrier[1];
	%task.buyEquipmentSet = "LightEnergySniper";
}

function AIBountyEngageTask::assume(%task, %client)
{
   %task.setWeightFreq(15);
   %task.setMonitorFreq(15);
}

function AIBountyEngageTask::retire(%task, %client)
{
	%client.setEngageTarget(-1);
}

function AIBountyEngageTask::weight(%task, %client)                              
{
   %player = %client.player;
	if (!isObject(%player))
		return;

   %clientPos = %player.getWorldBoxCenter();
   %client.shouldEngage = -1;

	//first, make sure we actually can fight
	if (AIEngageOutOfAmmo(%client))
	{
		%task.setWeight(0);
		return;
	}

	//see if anyone has fired on us recently...
   %mustEngage = false;
   %losTimeout = $AIClientMinLOSTime + ($AIClientLOSTimeout * %client.getSkillLevel());
   if (AIClientIsAlive(%client.lastDamageClient, %losTimeout) && getSimTime() - %client.lastDamageTime < %losTimeout)
   {
		//see if the attacker is either our target or, we are their target
		if (%client.lastDamageClient == %client.objectiveTarget || %client.lastDamageClient.objectiveTarget == %client)
		{
         %mustEngage = true;
			%currentTarget = %client.getEngageTarget();

			//see if this is a new attacker
			if (AIClientIsAlive(%currentTarget) && %currentTarget != %client.lastDamageClient)
			{
	         %targPos = %currentTarget.player.getWorldBoxCenter();
	         %curTargDist = %client.getPathDistance(%targPos);
	      
	         %newTargPos = %client.lastDamageClient.player.getWorldBoxCenter();
	         %newTargDist = %client.getPathDistance(%newTargPos);
	      
	         //see if the new targ is no more than 30 m further
	         if (%newTargDist > 0 && %newTargDist < %curTargDist + 30)
	            %client.shouldEngage = %client.lastDamageClient;
				else
					%client.shouldEngage = %currentTarget;
	      }
	      else
	         %client.shouldEngage = %client.lastDamageClient;
		}

		//otherwise we should run react to an attacker who is not really supposed to be attacking us...
		else
			%client.setDangerLocation(%client.player.position, 20);
	}

   //no one has fired at us recently, see if we're near our objective target...
   else
   {
		//see if we still have sight of the current target
		%hasLOS = %client.hasLOSToClient(%client.objectiveTarget);
		%losTime = %client.getClientLOSTime(%client.objectiveTarget);
		if (%hasLOS || %losTime < %losTimeout)
	      %client.shouldEngage = %client.objectiveTarget;
		else
			%client.shouldEngage = -1;
	}

	//now set the weight
	if (%client.shouldEngage > 0)
   {
      //if we've been fired upon...
      if (%mustEngage)
	      %task.setWeight($AIWeightReturnFire);

      //see if we can allow the bot to use an inv station...
      else if (%client.spawnUseInv)
      {
         //see if there's an available inv station
         %result = AIFindClosestInventory(%client, false);
         %closestInv = getWord(%result, 0);
	      %closestDist = getWord(%result, 1);
	      if (isObject(%closestInv))
         {
            if (isObject(%client.shouldEngage.player))
            {
               %dist = %client.getPathDistance(%client.shouldEngage.player.position);
               if (%dist < 70 || %closestDist > 200)
	               %task.setWeight($AIWeightReturnFire);
               else
	               %task.setWeight($AIBountyWeightShouldEngage);
            }
            else
	            %task.setWeight($AIBountyWeightShouldEngage);
         }
         else
         {
            %client.spawnUseInv = false;
	         %task.setWeight($AIWeightReturnFire);
         }
      }
      else
	      %task.setWeight($AIWeightReturnFire);
   }
	else
	   %task.setWeight(0);
}

function AIBountyEngageTask::monitor(%task, %client)
{
   if (AIClientIsAlive(%client.shouldEngage))
      %client.stepEngage(%client.shouldEngage);
}

//-----------------------------------------------------------------------------
//AIPatrolTask used to wander around the map (DM and Hunters mainly) looking for something to do...

function AIBountyPatrolTask::init(%task, %client)
{
}

function AIBountyPatrolTask::assume(%task, %client)
{
	%task.setWeightFreq(13);
	%task.setMonitorFreq(13);
	%task.findLocation = true;
	%task.patrolLocation = "0 0 0";
	%task.idleing = false;
	%task.idleEndTime = 0;
}

function AIBountyPatrolTask::retire(%task, %client)
{
}

function AIBountyPatrolTask::weight(%task, %client)
{
	%task.setWeight($AIWeightPatrolling);
}

function AIBountyPatrolTask::monitor(%task, %client)
{
	//this call works in conjunction with AIEngageTask
	%client.setEngageTarget(%client.shouldEngage);

	//see if we're close enough to our patrol point
	if (%task.idleing)
	{
		if (getSimTime() > %task.idleEndTime)
		{
			%task.findLocation = true;
			%task.idleing = false;
		}
	}

	//see if we need to find a place to go...
	else if (%task.findLocation)
	{
		//first, see if we're in need of either health, or ammo
		//note: normally, I'd be tempted to put this kind of "looking for health" code
		//into the AIPickupItemTask, however, that task will be used in CTF, where you
		//don't want people on AIDefendLocation to leave their post to hunt for health, etc...
		//AIPickupItemTask only deals with items within a 30m radius around the bot.
		//AIPatrolTask will move the bot to the vicinity of an item, then AIPickUpItemTask
		//will finish the job...
		%foundItemLocation = false;
		%damage = %client.player.getDamagePercent();
		if (%damage > 0.7)
		{
			//search for a health kit
			%closestHealth = AIFindSafeItem(%client, "Health");
			if (%closestHealth > 0)
			{
				%task.patrolLocation = %closestHealth.getWorldBoxCenter();
				%foundItemLocation = true;
			}
		}
		else if (AIEngageOutOfAmmo(%client))
		{
			//search for a Ammo or a weapon...
			%closestItem = AIFindSafeItem(%client, "Ammo");
			if (%closestItem > 0)
			{
				%task.patrolLocation = %closestItem.getWorldBoxCenter();
				%foundItemLocation = true;
			}
		}

		//now see if we don't really have good equipment...
		if (!%foundItemLocation && AIEngageWeaponRating(%client) < 20)
		{
			//search for any useful item
			%closestItem = AIFindSafeItem(%client, "Any");
			if (%closestItem > 0)
			{
				%task.patrolLocation = %closestItem.getWorldBoxCenter();
				%foundItemLocation = true;
			}
		}
		//choose a randomish location only if we're not in need of health or ammo
		if (!%foundItemLocation)
		{
			//find a random item/inventory in the map, and pick a spawn point near it...
			%pickGraphNode = false;
			%chooseSet = 0;
			if ($AIInvStationSet.getCount() > 0)
				%chooseSet = $AIInvStationSet;
			else if ($AIWeaponSet.getCount() > 0)
				%chooseSet = $AIWeaponSet;
			else if ($AIItemSet.getCount() > 0)
				%chooseSet = $AIItemSet;

			if (!%chooseSet)
				%pickGraphNode = true;

			//here we pick whether we choose a random map point, or a point based on an item...
			if (getRandom() < 0.3)
				%pickGraphNode = true;

			//here we decide whether we should choose a player location...  a bit of a cheat but
			//it's scaled by the bot skill level
			%pickPlayerLocation = false;
			%skill = %client.getSkillLevel();
			if (%skill < 1.0)
				%skill = %skill / 2.0;
			if (getRandom() < (%skill * %skill) && AIClientIsAlive(%client.objectiveTarget))
			{
				%task.patrolLocation = %client.objectiveTarget.player.getWorldBoxCenter();
				%pickGraphNode = false;
				%pickPlayerLocation = true;
			}
			
			if (!%pickGraphNode && !%pickPlayerLocation)
			{
				%itemCount = %chooseSet.getCount();
				%item = %chooseSet.getObject(getRandom() * (%itemCount - 0.1));
		      %nodeIndex = navGraph.randNode(%item.getWorldBoxCenter(), 10, true, true);
				if (%nodeIndex <= 0)
					%pickGraphNode = true;
				else
					%task.patrolLocation = navGraph.randNodeLoc(%nodeIndex);
			}

			//see if we failed above or have to pick just a random spot on the graph - use the spawn points...
			if (%pickGraphNode)
			{
			   %task.patrolLocation = Game.pickPlayerSpawn(%client, true);
				if (%task.patrolLocation == -1)
				{
					%client.stepIdle(%client.player.getWorldBoxCenter());
					return;
				}
			}
		}

		//now that we have a new location - move towards it
		%task.findLocation = false;
		%client.stepMove(%task.patrolLocation, 8.0);
	}

	//else we're on patrol - see if we're close to our destination
	else
	{
		%client.stepMove(%task.patrolLocation, 8.0);
		%distToDest = %client.getPathDistance(%task.patrolLocation);
		if (%distToDest > 0 && %distToDest < 10)
		{
			%task.idleing = true;
			%task.idleEndTime = 4000 + getSimTime() + (getRandom() * 6000);
			%client.stepIdle(%client.player.getWorldBoxCenter());
		}
	}
}

function aiB()
{
   exec("scripts/aiBountyGame");
}