t2-mapper/docs/base/@vl2/scripts.vl2/scripts/aiBountyGame.cs
2025-09-11 16:56:30 -07:00

320 lines
9.6 KiB
C#

// 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");
}