mirror of
https://github.com/Ragora/T2-DXAI.git
synced 2026-01-19 18:14:45 +00:00
Initial attempts at getting bots unstuck on broken paths; AI visual acuity is now the primary system of picking targets, improving performance
This commit is contained in:
parent
657545aaac
commit
ec3b86cdf6
|
|
@ -34,7 +34,6 @@ function AICommander::setup(%this)
|
|||
for (%iteration = 0; %iteration < ClientGroup.getCount(); %iteration++)
|
||||
{
|
||||
%currentClient = ClientGroup.getObject(%iteration);
|
||||
%currentClient.updateVisualAcuity();
|
||||
|
||||
if (%currentClient.isAIControlled() && %currentClient.team == %this.team)
|
||||
{
|
||||
|
|
@ -42,6 +41,11 @@ function AICommander::setup(%this)
|
|||
%this.idleBotList.add(%currentClient);
|
||||
|
||||
%currentClient.commander = %this;
|
||||
|
||||
%currentClient.initialize();
|
||||
%currentClient.visibleHostiles = new SimSet();
|
||||
%currentClient.updateVisualAcuity();
|
||||
%currentClient.stuckCheck();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,9 +78,7 @@ function AICommander::_skimObjectiveGroup(%this, %group)
|
|||
case "AIODefendLocation":
|
||||
// FIXME: Console spam from .targetObjectID not being set?
|
||||
%datablockName = %current.targetObjectID.getDatablock().getName();
|
||||
|
||||
echo(%datablockName);
|
||||
|
||||
|
||||
// Defending the flag?
|
||||
if (%datablockName $= "FLAG")
|
||||
%this.objectiveCycles[$DXAI::Priorities::DefendFlag].add(%current);
|
||||
|
|
@ -243,14 +245,24 @@ function AICommander::assignTask(%this, %taskID, %bot)
|
|||
%objective = %this.objectiveCycles[%taskID].next();
|
||||
|
||||
// Set the bot to defend the location
|
||||
%bot.defendLocation = %objective.location;
|
||||
%bot.defendTargetLocation = %objective.location;
|
||||
%datablockName = %objective.targetObjectID.getDatablock().getName();
|
||||
|
||||
switch$(%datablockName)
|
||||
{
|
||||
case "FLAG":
|
||||
%bot.defenseDescription = "flag";
|
||||
case "GeneratorLarge":
|
||||
%bot.defenseDescription = "generator";
|
||||
}
|
||||
|
||||
%bot.addTask("AIEnhancedDefendLocation");
|
||||
|
||||
case $DXAI::Priorities::ScoutBase:
|
||||
%objective = %this.objectiveCycles[%taskID].next();
|
||||
|
||||
// Set the bot to defend the location
|
||||
%bot.scoutLocation = %objective.location;
|
||||
%bot.scoutTargetLocation = %objective.location;
|
||||
%bot.scoutDistance = %objective.distance;
|
||||
%bot.addTask("AIEnhancedScoutLocation");
|
||||
}
|
||||
|
|
@ -267,6 +279,13 @@ function AICommander::setDefaultPriorities(%this)
|
|||
|
||||
function AICommander::cleanUp(%this)
|
||||
{
|
||||
for (%iteration = 0; %iteration < %this.botList.getCount(); %iteration++)
|
||||
{
|
||||
%current = %this.botList.getObject(%iteration);
|
||||
cancel(%current.visualAcuityTick);
|
||||
cancel(%current.stuckCheckTick);
|
||||
}
|
||||
|
||||
%this.botList.delete();
|
||||
%this.idleBotList.delete();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,15 +9,10 @@
|
|||
// Refer to LICENSE.txt for more information.
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
function AIConnection::initialize(%this, %aiClient)
|
||||
function AIConnection::initialize(%this)
|
||||
{
|
||||
%this.fieldOfView = 3.14 / 2; // 90* View cone
|
||||
%this.viewDistance = 300;
|
||||
|
||||
if (!isObject(%aiClient))
|
||||
error("AIPlayer: Attempted to initialize with bad AI client connection!");
|
||||
|
||||
%this.client = %aiClient;
|
||||
}
|
||||
|
||||
function AIConnection::update(%this)
|
||||
|
|
@ -77,6 +72,9 @@ function AIConnection::setMoveTarget(%this, %position)
|
|||
%this.isFollowingTarget = false;
|
||||
%this.setPath(%position);
|
||||
%this.stepMove(%position);
|
||||
|
||||
%this.minimumPathDistance = 9999;
|
||||
%this.maximumPathDistance = -9999;
|
||||
}
|
||||
|
||||
function AIConnection::setFollowTarget(%this, %target, %minDistance, %maxDistance, %hostile)
|
||||
|
|
@ -97,14 +95,72 @@ function AIConnection::setFollowTarget(%this, %target, %minDistance, %maxDistanc
|
|||
%this.stepEscort(%target);
|
||||
}
|
||||
|
||||
function AIConnection::stuckCheck(%this)
|
||||
{
|
||||
if (isEventPending(%this.stuckCheckTick))
|
||||
cancel(%this.stuckCheckTick);
|
||||
|
||||
%targetDistance = %this.pathDistRemaining(9000);
|
||||
if (!%this.isMovingToTarget || !isObject(%this.player) || %this.player.getState() !$= "Move" || %targetDistance <= 5)
|
||||
{
|
||||
%this.stuckCheckTick = %this.schedule(5000, "stuckCheck");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!%this.isPathCorrecting && %targetDistance >= %this.minimumPathDistance && %this.minimumPathDistance != 9999)
|
||||
%this.isPathCorrecting = true;
|
||||
|
||||
if (%targetDistance > %this.maximumPathDistance)
|
||||
%this.maximumPathDistance = %targetDistance;
|
||||
if (%targetDistance < %this.minimumPathDistance)
|
||||
%this.minimumPathDistance = %targetDistance;
|
||||
|
||||
%this.stuckCheckTick = %this.schedule(5000, "stuckCheck");
|
||||
}
|
||||
|
||||
function AIConnection::updateLegs(%this)
|
||||
{
|
||||
%now = getSimTime();
|
||||
%delta = %now - %this.lastUpdateLegs;
|
||||
%this.lastUpdateLegs = %now;
|
||||
|
||||
if (%this.isMovingToTarget)
|
||||
{
|
||||
if (%this.aimAtLocation)
|
||||
%this.aimAt(%this.moveTarget);
|
||||
else if(%this.manualAim)
|
||||
%this.aimAt(%this.moveTarget);
|
||||
|
||||
%targetDistance = %this.pathDistRemaining(9000);
|
||||
|
||||
if (%targetDistance > %this.maximumPathDistance)
|
||||
%this.maximumPathDistance = %targetDistance;
|
||||
if (%targetDistance < %this.minimumPathDistance)
|
||||
%this.minimumPathDistance = %targetDistance;
|
||||
|
||||
// Bots follow a set of lines drawn between nodes to slowly decrement the path distance,
|
||||
// so bots that are stuck usually get their remaining distance stuck in some range of
|
||||
// arbitrary values, so we monitor the minimum and maximum values over a period of 5 seconds
|
||||
|
||||
// Test...
|
||||
%pathDistance = %this.getPathDistance(%this.moveTarget);
|
||||
if(%pathDistance > 10 && %this.moveTravelTime < 10000)
|
||||
%this.moveTravelTime += %delta;
|
||||
else if (%pathDistance < 10)
|
||||
%this.moveTravelTime = 0;
|
||||
else if (%this.moveTravelTime >= 10000)
|
||||
{
|
||||
// We appear to be stuck, so pick a random nearby node and try to run to it
|
||||
%this.moveTravelTime = 0;
|
||||
%this.isPathCorrecting = true;
|
||||
|
||||
if (isObject(NavGraph))
|
||||
{
|
||||
%randomNode = NavGraph.randNode(%this.player.getPosition(), 200, true, true);
|
||||
if (%randomNode != -1)
|
||||
%this.setMoveTarget(NavGraph.nodeLoc(%randomNode));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (%this.isFollowingTarget)
|
||||
{
|
||||
|
|
@ -119,7 +175,24 @@ function AIConnection::updateLegs(%this)
|
|||
|
||||
function AIConnection::updateWeapons(%this)
|
||||
{
|
||||
|
||||
if (isObject(%this.engageTarget))
|
||||
{
|
||||
%player = %this.player;
|
||||
%targetDistance = vectorDist(%player.getPosition(), %this.engageTarget.getPosition());
|
||||
|
||||
// Firstly, just aim at them for now
|
||||
%this.aimAt(%this.engageTarget.getWorldBoxCenter());
|
||||
|
||||
// What is our current best weapon? Right now we just check target distance and weapon spread.
|
||||
%bestWeapon = 0;
|
||||
|
||||
for (%iteration = 0; %iteration < %player.weaponSlotCount; %iteration++)
|
||||
{
|
||||
// Weapons with a decent bit of spread should be used <= 20m
|
||||
}
|
||||
|
||||
%player.selectWeaponSlot(%bestWeapon);
|
||||
}
|
||||
}
|
||||
|
||||
function AIConnection::updateVisualAcuity(%this)
|
||||
|
|
@ -127,7 +200,7 @@ function AIConnection::updateVisualAcuity(%this)
|
|||
if (isEventPending(%this.visualAcuityTick))
|
||||
cancel(%this.visualAcuityTick);
|
||||
|
||||
if (!isObject(%this.player) || %this.player.getState() !$= "Move")
|
||||
if (%this.visibleDistance = 0 || !isObject(%this.player) || %this.player.getState() !$= "Move")
|
||||
{
|
||||
%this.visualAcuityTick = %this.schedule(getRandom(230, 400), "updateVisualAcuity");
|
||||
return;
|
||||
|
|
@ -167,24 +240,26 @@ function AIConnection::updateVisualAcuity(%this)
|
|||
%this.upperMarker.delete();
|
||||
%this.lowerMarker.delete();
|
||||
}
|
||||
|
||||
%now = getSimTime();
|
||||
%deltaTime = %now - %this.lastVisualAcuityUpdate;
|
||||
%this.lastVisualAcuityUpdate = %now;
|
||||
|
||||
%result = %this.getObjectsInViewcone($TypeMasks::ProjectileObjectType | $TypeMasks::PlayerObjectType, %this.viewDistance, true);
|
||||
|
||||
// What can we see?
|
||||
for (%i = 0; %i < %result.getCount(); %i++)
|
||||
%visibleObjects = %this.getObjectsInViewcone($TypeMasks::ProjectileObjectType | $TypeMasks::PlayerObjectType, %this.viewDistance, true);
|
||||
|
||||
for (%iteration = 0; %iteration < %visibleObjects.getCount(); %iteration++)
|
||||
{
|
||||
%current = %result.getObject(%i);
|
||||
%this.awarenessTicks[%current]++;
|
||||
%current = %visibleObjects.getObject(%iteration);
|
||||
|
||||
%this.awarenessTime[%current] += %deltaTime;
|
||||
|
||||
// Did we "notice" the object yet?
|
||||
%noticeTime = getRandom(700, 1200);
|
||||
if (%this.awarenessTime[%current] < %noticeTime)
|
||||
continue;
|
||||
|
||||
if (%current.getType() & $TypeMasks::ProjectileObjectType)
|
||||
{
|
||||
// Did we "notice" the object yet?
|
||||
// We pick a random notice time between 700ms and 1200 ms
|
||||
// Obviously this timer runs on a 32ms tick, but it should help provide a little unpredictability
|
||||
%noticeTime = getRandom(700, 1200);
|
||||
if (%this.awarenessTicks[%current] < (%noticeTime / 32))
|
||||
continue;
|
||||
|
||||
{
|
||||
%className = %current.getClassName();
|
||||
|
||||
// LinearFlareProjectile and LinearProjectile have linear trajectories, so we can easily determine if a dodge is necessary
|
||||
|
|
@ -223,26 +298,43 @@ function AIConnection::updateVisualAcuity(%this)
|
|||
}
|
||||
}
|
||||
// See a player?
|
||||
else if (%current.getType() & $TypeMasks::PlayerObjectType)
|
||||
else if (%current.getType() & $TypeMasks::PlayerObjectType && %current.client.team != %this.team)
|
||||
{
|
||||
%this.clientDetected(%current);
|
||||
%this.clientDetected(%current.client);
|
||||
%this.visibleHostiles.add(%current);
|
||||
//%this.clientDetected(%current);
|
||||
// %this.clientDetected(%current.client);
|
||||
|
||||
// ... if the moron is right there in our LOS then we probably should see them
|
||||
%start = %this.player.getPosition();
|
||||
%end = vectorAdd(%start, vectorScale(%this.player.getEyeVector(), %this.viewDistance));
|
||||
// %start = %this.player.getPosition();
|
||||
// %end = vectorAdd(%start, vectorScale(%this.player.getEyeVector(), %this.viewDistance));
|
||||
|
||||
%rayCast = containerRayCast(%start, %end, -1, %this.player);
|
||||
%hitObject = getWord(%raycast, 0);
|
||||
// %rayCast = containerRayCast(%start, %end, -1, %this.player);
|
||||
// %hitObject = getWord(%raycast, 0);
|
||||
|
||||
if (%hitObject == %current)
|
||||
{
|
||||
%this.clientDetected(%current);
|
||||
%this.stepEngage(%current);
|
||||
}
|
||||
// if (%hitObject == %current)
|
||||
// {
|
||||
// %this.clientDetected(%current);
|
||||
// %this.stepEngage(%current);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
%result.delete();
|
||||
%this.visualAcuityTick = %this.schedule(getRandom(230, 400), "updateVisualAcuity");
|
||||
// Now we run some logic on some things that we no longer can see.
|
||||
for (%iteration = 0; %iteration < %this.visibleHostiles.getCount(); %iteration++)
|
||||
{
|
||||
%current = %this.visibleHostiles.getObject(%iteration);
|
||||
|
||||
if (%this.visibleHostiles.isMember(%current) && !%visibleObjects.isMember(%current))
|
||||
{
|
||||
%this.awarenessTime[%current] -= %deltaTime;
|
||||
if (%this.awarenessTime[%current] < 200)
|
||||
{
|
||||
%this.visibleHostiles.remove(%current);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%visibleObjects.delete();
|
||||
%this.visualAcuityTick = %this.schedule(getRandom($DXAI::Bot::MinimumVisualAcuityTime, $DXAI::Bot::MaximumVisualAcuityTime), "updateVisualAcuity");
|
||||
}
|
||||
|
|
@ -13,3 +13,6 @@ $DXAI::Commander::minimumGeneratorDefense = 1;
|
|||
|
||||
$DXAI::Bot::DefaultFieldOfView = 3.14159 / 2; // 90*
|
||||
$DXAI::Bot::DefaultViewDistance = 300;
|
||||
|
||||
$DXAI::Bot::MinimumVisualAcuityTime = 200;
|
||||
$DXAI::Bot::MaximumVisualAcuityTime = 400;
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ function GameConnection::getObjectsInViewcone(%this, %typeMask, %distance, %perf
|
|||
%result.add(%currentObject);
|
||||
else
|
||||
{
|
||||
%rayCast = containerRayCast(%coneOrigin, %currentObject.getWorldBoxCenter(), -1, 0);
|
||||
%rayCast = containerRayCast(%coneOrigin, %currentObject.getWorldBoxCenter(), $TypeMasks::AllObjectType, %this.player);
|
||||
|
||||
%hitObject = getWord(%raycast, 0);
|
||||
|
||||
|
|
@ -224,6 +224,16 @@ function vectorMultiply(%vec1, %vec2)
|
|||
(getWord(%vec1, 2) * getWord(%vec2, 2));
|
||||
}
|
||||
|
||||
function listStuckBots()
|
||||
{
|
||||
for (%iteration = 0; %iteration < ClientGroup.getCount(); %iteration++)
|
||||
{
|
||||
%client = ClientGroup.getObject(%iteration);
|
||||
if (%client.isAIControlled() && %client.isPathCorrecting)
|
||||
error(%client);
|
||||
}
|
||||
}
|
||||
|
||||
// If the map editor was instantiated, this will prevent a little bit
|
||||
// of console warnings
|
||||
function Terraformer::getType(%this) { return 0; }
|
||||
|
|
|
|||
|
|
@ -245,6 +245,9 @@ package DXAI_Hooks
|
|||
%client.shouldRearm = true;
|
||||
%client.targetLoadout = 1;
|
||||
|
||||
%client.engageTargetLastPosition = "";
|
||||
%client.engageTarget = -1;
|
||||
|
||||
return 11595;
|
||||
}
|
||||
|
||||
|
|
@ -270,10 +273,26 @@ package DXAI_Hooks
|
|||
//switch$ (%eventTag)
|
||||
//{
|
||||
schedule(250, %targetClient, "AIPlayAnimSound", %targetClient, %clientPos, "cmd.decline", $AIAnimSalute, $AIAnimSalute, 0);
|
||||
schedule(2000, %targetClient, "AIPlayAnimSound", %targetClient, %clientPos, ObjectiveNameToVoice(%targetClient.getTaskName()), $AIAnimSalute, $AIAnimSalute, 0);
|
||||
schedule(2000, %targetClient, "AIPlayAnimSound", %targetClient, %clientPos, ObjectiveNameToVoice(%targetClient), $AIAnimSalute, $AIAnimSalute, 0);
|
||||
schedule(3700, %targetClient, "AIPlayAnimSound", %targetClient, %clientPos, "vqk.sorry", $AIAnimSalute, $AIAnimSalute, 0);
|
||||
}
|
||||
|
||||
function AISystemEnabled(%enabled)
|
||||
{
|
||||
parent::AISystemEnabled(%enabled);
|
||||
|
||||
echo(%enabled);
|
||||
$DXAI::AISystemEnabled = %enabled;
|
||||
}
|
||||
|
||||
function AIConnection::onAIDrop(%client)
|
||||
{
|
||||
parent::onAIDrop(%client);
|
||||
|
||||
if (isObject(%client.visibleHostiles))
|
||||
%client.visibleHostiles.delete();
|
||||
}
|
||||
|
||||
function Station::stationTriggered(%data, %obj, %isTriggered)
|
||||
{
|
||||
parent::stationTriggered(%data, %obj, %isTriggered);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ $DXAI::Task::NoPriority = 0;
|
|||
$DXAI::Task::LowPriority = 100;
|
||||
$DXAI::Task::MediumPriority = 200;
|
||||
$DXAI::Task::HighPriority = 500;
|
||||
$DXAI::Task::VeryHighPriority = 1000;
|
||||
$DXAI::Task::VeryHighPriority = 1000;
|
||||
$DXAI::Task::ReservedPriority = 5000;
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// +Param %bot.escortTarget: The ID of the object to escort. This can be literally
|
||||
|
|
@ -119,7 +120,10 @@ function AIEnhancedScoutLocation::retire(%task, %client) { }
|
|||
function AIEnhancedScoutLocation::weight(%task, %client) { %task.setWeight($DXAI::Task::MediumPriority); }
|
||||
|
||||
function AIEnhancedScoutLocation::monitor(%task, %client)
|
||||
{
|
||||
{
|
||||
if (%client.engageTarget)
|
||||
return AIEnhancedScoutLocation::monitorEngage(%task, %client);
|
||||
|
||||
// We can't really work without a NavGraph
|
||||
if (!isObject(NavGraph))
|
||||
return;
|
||||
|
|
@ -127,7 +131,7 @@ function AIEnhancedScoutLocation::monitor(%task, %client)
|
|||
// We just received the task, so find a node within distance of our scout location
|
||||
if (%client.currentNode == -1)
|
||||
{
|
||||
%client.currentNode = NavGraph.randNode(%client.scoutLocation, %client.scoutDistance, true, true);
|
||||
%client.currentNode = NavGraph.randNode(%client.scoutTargetLocation, %client.scoutDistance, true, true);
|
||||
|
||||
if (%client.currentNode != -1)
|
||||
%client.setMoveTarget(NavGraph.nodeLoc(%client.currentNode));
|
||||
|
|
@ -138,7 +142,7 @@ function AIEnhancedScoutLocation::monitor(%task, %client)
|
|||
%pathDistance = %client.getPathDistance(%client.moveTarget);
|
||||
|
||||
// Don't move if we're close enough to our next node
|
||||
if (%pathDistance <= 40 && %client.isMoving)
|
||||
if (%pathDistance <= 40 && %client.isMovingToTarget)
|
||||
{
|
||||
%client.setMoveTarget(-1);
|
||||
%client.nextScoutRotation = getRandom(5000, 10000);
|
||||
|
|
@ -159,7 +163,7 @@ function AIEnhancedScoutLocation::monitor(%task, %client)
|
|||
%client.nextScoutRotation = getRandom(5000, 10000);
|
||||
|
||||
// Pick a new node
|
||||
%client.currentNode = NavGraph.randNode(%client.scoutLocation, %client.scoutDistance, true, true);
|
||||
%client.currentNode = NavGraph.randNode(%client.scoutTargetLocation, %client.scoutDistance, true, true);
|
||||
|
||||
// Ensure that we found a node.
|
||||
if (%client.currentNode != -1)
|
||||
|
|
@ -167,6 +171,11 @@ function AIEnhancedScoutLocation::monitor(%task, %client)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AIEnhancedScoutLocation::monitorEngage(%task, %client)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
|
@ -182,40 +191,24 @@ function AIEnhancedEngageTarget::retire(%task, %client) { }
|
|||
|
||||
function AIEnhancedEngageTarget::weight(%task, %client)
|
||||
{
|
||||
if (!isObject(%client.engageTarget))
|
||||
// Blow through seen targets
|
||||
%chosenTarget = -1;
|
||||
%chosenTargetDistance = 9999;
|
||||
|
||||
%botPosition = %client.player.getPosition();
|
||||
for (%iteration = 0; %iteration < %client.visibleHostiles.getCount(); %iteration++)
|
||||
{
|
||||
%visibleObjects = %client.getObjectsInViewcone($TypeMasks::PlayerObjectType, %client.viewDistance, true);
|
||||
%current = %client.visibleHostiles.getObject(%iteration);
|
||||
|
||||
// Choose the closest target
|
||||
// TODO: Choose on more advanced metrics like HP
|
||||
%chosenTarget = -1;
|
||||
%chosenTargetDistance = 9999;
|
||||
for (%iteration = 0; %iteration < %visibleObjects.getCount(); %iteration++)
|
||||
%targetDistance = vectorDist(%current.getPosition(), %botPosition);
|
||||
if (%targetDistance < %chosenTargetDistance)
|
||||
{
|
||||
%potentialTarget = %visibleObjects.getObject(%iteration);
|
||||
|
||||
%potentialTargetDistance = vectorDist(%potentialTarget.getPosition(), %client.player.getPosition());
|
||||
if (%potentialTarget.client.team != %client.team && %potentialTargetDistance < %chosenTargetDistance)
|
||||
{
|
||||
%chosenTargetDistance = %potentialTargetDistance;
|
||||
%chosenTarget = %potentialTarget;
|
||||
}
|
||||
%chosenTargetDistance = %targetDistance;
|
||||
%chosenTarget = %current;
|
||||
}
|
||||
|
||||
%visibleObjects.delete();
|
||||
%client.engageTarget = %chosenTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can we still see them?
|
||||
%rayCast = containerRayCast(%client.player.getWorldBoxCenter(), %client.engageTarget.getWorldBoxCenter(), -1, %client.player);
|
||||
%hitObject = getWord(%raycast, 0);
|
||||
|
||||
// TODO: Go to the last known position.
|
||||
if (%hitObject != %client.engageTarget)
|
||||
%client.engageTarget = -1;
|
||||
}
|
||||
|
||||
|
||||
%client.engageTarget = %chosenTarget;
|
||||
if (!isObject(%client.engageTarget) && %client.engageTargetLastPosition $= "")
|
||||
%task.setWeight($DXAI::Task::NoPriority);
|
||||
else
|
||||
|
|
@ -225,26 +218,16 @@ function AIEnhancedEngageTarget::weight(%task, %client)
|
|||
function AIEnhancedEngageTarget::monitor(%task, %client)
|
||||
{
|
||||
if (isObject(%client.engageTarget))
|
||||
{
|
||||
%player = %client.player;
|
||||
%targetDistance = vectorDist(%player.getPosition(), %client.engageTarget.getPosition());
|
||||
|
||||
// Firstly, just aim at them for now
|
||||
%client.aimAt(%client.engageTarget.getWorldBoxCenter());
|
||||
|
||||
// What is our current best weapon? Right now we just check target distance and weapon spread.
|
||||
%bestWeapon = 0;
|
||||
|
||||
for (%iteration = 0; %iteration < %player.weaponSlotCount; %iteration++)
|
||||
{
|
||||
if (%client.engageTarget.getState() !$= "Move")
|
||||
{
|
||||
// Weapons with a decent bit of spread should be used <= 20m
|
||||
%client.engageTarget = -1;
|
||||
%client.engageTargetLastPosition = "";
|
||||
return;
|
||||
}
|
||||
|
||||
%player.selectWeaponSlot(%bestWeapon);
|
||||
%client.engageTargetLastPosition = %client.engageTarget.getWorldBoxCenter();
|
||||
|
||||
%client.setMoveTarget(getRandomPositionOnTerrain(%client.engageTargetLastPosition, 40));
|
||||
|
||||
%client.engageTargetLastPosition = %client.engageTarget.getWorldBoxCenter();
|
||||
%client.setMoveTarget(getRandomPositionOnTerrain(%client.engageTargetLastPosition, 40));
|
||||
%client.pressFire();
|
||||
}
|
||||
else if (%client.engageTargetLastPosition !$= "")
|
||||
|
|
@ -258,6 +241,7 @@ function AIEnhancedEngageTarget::monitor(%task, %client)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
|
@ -275,6 +259,8 @@ function AIEnhancedRearmTask::weight(%task, %client)
|
|||
%task.setWeight($DXAI::Task::HighPriority);
|
||||
else
|
||||
%task.setWeight($DXAI::Task::NoPriority);
|
||||
|
||||
%task.setMonitorFreq(getRandom(10, 32));
|
||||
}
|
||||
|
||||
function AIEnhancedRearmTask::monitor(%task, %client)
|
||||
|
|
@ -322,26 +308,44 @@ function AIEnhancedReturnFlagTask::monitor(%task, %client)
|
|||
{
|
||||
if (!isObject(%client.returnFlagTarget))
|
||||
return;
|
||||
|
||||
%client.setMoveTarget(%client.returnFlagTarget.getPosition());
|
||||
|
||||
if (isObject(%client.engageTarget) && %client.engageTarget.getState() $= "Move")
|
||||
AIEnhancedReturnFlagTask::monitorEngage(%task, %client);
|
||||
else
|
||||
%client.setMoveTarget(%client.returnFlagTarget.getPosition());
|
||||
}
|
||||
|
||||
function AIEnhancedReturnFlagTask::monitorEngage(%task, %client)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
// Description: A task that performs path correction.
|
||||
//------------------------------------------------------------------------------------------`
|
||||
function AIEnhancedPathCorrectionTask::initFromObjective(%task, %objective, %client) { }
|
||||
function AIEnhancedPathCorrectionTask::assume(%task, %client) { %task.setMonitorFreq(32); }
|
||||
function AIEnhancedPathCorrectionTask::assume(%task, %client) { %task.setMonitorFreq(2); }
|
||||
function AIEnhancedPathCorrectionTask::retire(%task, %client) { }
|
||||
|
||||
function AIEnhancedPathCorrectionTask::weight(%task, %client)
|
||||
{
|
||||
%task.setWeight(0);
|
||||
if (%client.isPathCorrecting)
|
||||
%task.setWeight($DXAI::Task::VeryHighPriority);
|
||||
else
|
||||
%task.setWeight($DXAI::Task::NoPriority);
|
||||
}
|
||||
|
||||
function AIEnhancedPathCorrectionTask::monitor(%task, %client)
|
||||
{
|
||||
|
||||
{
|
||||
if (%client.isPathCorrecting)
|
||||
{
|
||||
if (%client.player.getEnergyPercent() >= 1)
|
||||
%client.isPathCorrecting = false;
|
||||
else
|
||||
%client.setMoveTarget(-1);
|
||||
}
|
||||
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -383,8 +387,10 @@ function AIEnhancedFlagCaptureTask::monitor(%task, %client)
|
|||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
function ObjectiveNameToVoice(%objective)
|
||||
function ObjectiveNameToVoice(%bot)
|
||||
{
|
||||
%objective = %bot.getTaskName();
|
||||
|
||||
%result = "avo.grunt";
|
||||
switch$(%objective)
|
||||
{
|
||||
|
|
@ -397,7 +403,15 @@ function ObjectiveNameToVoice(%objective)
|
|||
case "AIEnhancedScoutLocation":
|
||||
%result = "slf.def.defend";
|
||||
case "AIEnhancedDefendLocation":
|
||||
%result = "slf.def.defend";
|
||||
switch$(%bot.defenseDescription)
|
||||
{
|
||||
case "flag":
|
||||
%result = "slf.def.flag";
|
||||
case "generator":
|
||||
%result = "slf.def.generator";
|
||||
default:
|
||||
%result = "slf.def.defend";
|
||||
}
|
||||
case "AIEnhancedEscort":
|
||||
%result = "slf.tsk.cover";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue