diff --git a/scripts/DXAI/aicommander.cs b/scripts/DXAI/aicommander.cs index c746aac..b9fea53 100644 --- a/scripts/DXAI/aicommander.cs +++ b/scripts/DXAI/aicommander.cs @@ -34,6 +34,7 @@ function AICommander::setup(%this) for (%iteration = 0; %iteration < ClientGroup.getCount(); %iteration++) { %currentClient = ClientGroup.getObject(%iteration); + %currentClient.updateVisualAcuity(); if (%currentClient.isAIControlled() && %currentClient.team == %this.team) { @@ -138,10 +139,14 @@ function AICommander::assignTasks(%this) %bot = %this.botList.getObject(%iteration); %bot.addTask(AIEnhancedEngageTarget); %bot.addTask(AIEnhancedRearmTask); + %bot.addTask(AIEnhancedPathCorrectionTask); // We only need this task if we're actually playing CTF. if ($CurrentMissionType $= "CTF") + { %bot.addTask(AIEnhancedReturnFlagTask); + %bot.addTask(AIEnhancedFlagCaptureTask); + } %bot.targetLoadout = 0; %bot.shouldRearm = true; diff --git a/scripts/DXAI/aiconnection.cs b/scripts/DXAI/aiconnection.cs index e57dbeb..73df8fd 100644 --- a/scripts/DXAI/aiconnection.cs +++ b/scripts/DXAI/aiconnection.cs @@ -25,7 +25,7 @@ function AIConnection::update(%this) if (isObject(%this.player) && %this.player.getState() $= "Move") { %this.updateLegs(); - %this.updateVisualAcuity(); + %this.updateWeapons(); } } @@ -41,19 +41,74 @@ function AIConnection::isIdle(%this) return true; return %this.commander.idleBotList.isMember(%this); -} +} + +function AIConnection::reset(%this) +{ + // AIUnassignClient(%this); + + %this.stop(); + // %this.clearTasks(); + %this.clearStep(); + %this.lastDamageClient = -1; + %this.lastDamageTurret = -1; + %this.shouldEngage = -1; + %this.setEngageTarget(-1); + %this.setTargetObject(-1); + %this.pilotVehicle = false; + %this.defaultTasksAdded = false; + + if (isObject(%this.controlByHuman)) + aiReleaseHumanControl(%this.controlByHuman, %this); +} + +function AIConnection::setMoveTarget(%this, %position) +{ + if (%position == -1) + { + %this.reset(); + %this.isMovingToTarget = false; + %this.isFollowingTarget = false; + return; + } + + %this.moveTarget = %position; + %this.isMovingToTarget = true; + %this.isFollowingTarget = false; + %this.setPath(%position); + %this.stepMove(%position); +} + +function AIConnection::setFollowTarget(%this, %target, %minDistance, %maxDistance, %hostile) +{ + if (!isObject(%target)) + { + %this.reset(); + %this.isMovingToTarget = false; + %this.isFollowingTarget = false; + return; + } + + %this.followTarget = %target; + %this.isFollowingTarget = true; + %this.followMinDistance = %minDistance; + %this.followMaxDistance = %maxDistance; + %this.followHostile = %hostile; + %this.stepEscort(%target); +} function AIConnection::updateLegs(%this) { - if (%this.isMoving && %this.getTaskID() != 0) + if (%this.isMovingToTarget) { - %this.setPath(%this.moveLocation); - %this.stepMove(%this.moveLocation); - if (%this.aimAtLocation) - %this.aimAt(%this.moveLocation); + %this.aimAt(%this.moveTarget); else if(%this.manualAim) - %this.aimAt(%this.aimLocation); + %this.aimAt(%this.moveTarget); + } + else if (%this.isFollowingTarget) + { + } else { @@ -62,8 +117,22 @@ function AIConnection::updateLegs(%this) } } +function AIConnection::updateWeapons(%this) +{ + +} + function AIConnection::updateVisualAcuity(%this) { + if (isEventPending(%this.visualAcuityTick)) + cancel(%this.visualAcuityTick); + + if (!isObject(%this.player) || %this.player.getState() !$= "Move") + { + %this.visualAcuityTick = %this.schedule(getRandom(230, 400), "updateVisualAcuity"); + return; + } + if (%this.enableVisualDebug) { if (!isObject(%this.originMarker)) @@ -118,7 +187,7 @@ function AIConnection::updateVisualAcuity(%this) %className = %current.getClassName(); - // LinearFlareProjectile and LinearProjectile have linear properties, so we can easily determine if a dodge is necessary + // LinearFlareProjectile and LinearProjectile have linear trajectories, so we can easily determine if a dodge is necessary if (%className $= "LinearFlareProjectile" || %className $= "LinearProjectile") { //%this.setDangerLocation(%current.getPosition(), 20); @@ -175,4 +244,5 @@ function AIConnection::updateVisualAcuity(%this) } %result.delete(); + %this.visualAcuityTick = %this.schedule(getRandom(230, 400), "updateVisualAcuity"); } \ No newline at end of file diff --git a/scripts/DXAI/config.cs b/scripts/DXAI/config.cs index b158fe4..e19579e 100644 --- a/scripts/DXAI/config.cs +++ b/scripts/DXAI/config.cs @@ -1,6 +1,12 @@ +//------------------------------------------------------------------------------------------ // config.cs -// Configuration for the DXAI System +// Configuration file for the experimental DXAI system. +// https://github.com/Ragora/T2-DXAI.git +// // Copyright (c) 2014 Robert MacGregor +// This software is licensed under the MIT license. +// Refer to LICENSE.txt for more information. +//------------------------------------------------------------------------------------------ $DXAI::Commander::minimumFlagDefense = 1; $DXAI::Commander::minimumGeneratorDefense = 1; diff --git a/scripts/DXAI/helpers.cs b/scripts/DXAI/helpers.cs index 3f97550..92def14 100644 --- a/scripts/DXAI/helpers.cs +++ b/scripts/DXAI/helpers.cs @@ -1,6 +1,12 @@ +//------------------------------------------------------------------------------------------ // helpers.cs -// Helper functions for the AI System +// Helper functions used in the experimental DXAI system. +// https://github.com/Ragora/T2-DXAI.git +// // Copyright (c) 2014 Robert MacGregor +// This software is licensed under the MIT license. +// Refer to LICENSE.txt for more information. +//------------------------------------------------------------------------------------------ function sameSide(%p1, %p2, %a, %b) { @@ -29,25 +35,6 @@ function pointInTriangle(%point, %a, %b, %c) return false; } -function AIConnection::reset(%this) -{ - AIUnassignClient(%this); - - %this.stop(); - %this.clearTasks(); - %this.clearStep(); - %this.lastDamageClient = -1; - %this.lastDamageTurret = -1; - %this.shouldEngage = -1; - %this.setEngageTarget(-1); - %this.setTargetObject(-1); - %this.pilotVehicle = false; - %this.defaultTasksAdded = false; - - if (isObject(%this.controlByHuman)) - aiReleaseHumanControl(%this.controlByHuman, %this); -} - // TODO: Return in a faster-to-read format: Could try as static GVar names // as the game's scripting environment for the gameplay is single threaded // and it probably does a hash to store the values. @@ -254,6 +241,4 @@ $TypeMasks::BaseAssetObjectType = $TypeMasks::ForceFieldObjectType | $TypeMasks: $TypeMasks::GameSupportObjectType = $TypeMasks::TriggerObjectType | $TypeMasks::MarkerObjectType | $TypeMasks::CameraObjectType | $TypeMasks::VehicleBlockerObjectType | $TypeMasks::PhysicalZoneObjectType; $TypeMasks::GameContentObjectType = $TypeMasks::ExplosionObjectType | $TypeMasks::CorpseObjectType | $TypeMasks::DebrisObjectType; $TypeMasks::DefaultLOSObjectType = $TypeMasks::TerrainObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::StaticObjectType; - -// We declare the AllObjectType like this instead of -1 because it seems -1 can sometimes not work? -$TypeMasks::AllObjectType = $TypeMasks::InteractiveObjectType | $TypeMasks::DefaultLOSObjectType | $TypeMasks::GameContentObjectType | $TypeMasks::GameSupportObjectType | $TypeMasks::BaseAssetObjectType | $TypeMasks::UnInteractiveObjectType; +$TypeMasks::AllObjectType = -1; diff --git a/scripts/DXAI/objectives.cs b/scripts/DXAI/objectives.cs index b6b49de..b1cfaa3 100644 --- a/scripts/DXAI/objectives.cs +++ b/scripts/DXAI/objectives.cs @@ -7,6 +7,21 @@ // This software is licensed under the MIT license. Refer to LICENSE.txt for more information. //------------------------------------------------------------------------------------------ +// Weights +// AIEnhancedFlagCaptureTask - $DXAI::Task::MediumPriority +// AIEnhancedEscort - $DXAI::Task::MediumPriority +// AIEnhancedDefendLocation - $DXAI::Task::MediumPriority +// AIEnhancedScoutLocation - $DXAI::Task::MediumPriority +// AIEnhancedEngageTarget - $DXAI::Task::VeryHighPriority +// AIEnhancedReturnFlagTask - $DXAI::Task::HighPriority +// AIEnhancedRearmTask - $DXAI::Task::HighPriority + +$DXAI::Task::NoPriority = 0; +$DXAI::Task::LowPriority = 100; +$DXAI::Task::MediumPriority = 200; +$DXAI::Task::HighPriority = 500; +$DXAI::Task::VeryHighPriority = 1000; + //------------------------------------------------------------------------------------------ // +Param %bot.escortTarget: The ID of the object to escort. This can be literally // any object that exists in the game world. @@ -20,7 +35,7 @@ function AIEnhancedEscort::initFromObjective(%task, %objective, %client) { } function AIEnhancedEscort::assume(%task, %client) { %task.setMonitorFreq(1); } function AIEnhancedEscort::retire(%task, %client) { %client.isMoving = false; %client.manualAim = false; } -function AIEnhancedEscort::weight(%task, %client) { %task.setWeight(500); } +function AIEnhancedEscort::weight(%task, %client) { %task.setWeight($DXAI::Task::MediumPriority); } function AIEnhancedEscort::monitor(%task, %client) { @@ -37,7 +52,7 @@ function AIEnhancedEscort::monitor(%task, %client) %client.manualAim = true; %client.aimLocation = %escortLocation; - %client.moveLocation = getRandomPositionOnTerrain(%escortLocation, 40); + %client.setMoveTarget(getRandomPositionOnTerrain(%escortLocation, 40)); } //------------------------------------------------------------------------------------------ @@ -53,22 +68,22 @@ function AIEnhancedEscort::monitor(%task, %client) function AIEnhancedDefendLocation::initFromObjective(%task, %objective, %client) { } function AIEnhancedDefendLocation::assume(%task, %client) { %task.setMonitorFreq(1); } function AIEnhancedDefendLocation::retire(%task, %client) { %client.isMoving = false; } -function AIEnhancedDefendLocation::weight(%task, %client) { %task.setWeight(500); } +function AIEnhancedDefendLocation::weight(%task, %client) { %task.setWeight($DXAI::Task::MediumPriority); } function AIEnhancedDefendLocation::monitor(%task, %client) { - if (%client.getPathDistance(%client.defendLocation) <= 40) + if (%client.getPathDistance(%client.defendTargetLocation) <= 40) { // Pick a random time to move to a nearby location if (%client.defendTime == -1) { %client.nextDefendRotation = getRandom(5000, 10000); - %client.isMoving = false; + %client.setMoveTarget(-1); } // If we're near our random point, just don't move if (%client.getPathDistance(%client.moveLocation) <= 10) - %client.isMoving = false; + %client.setMoveTarget(-1); %client.defendTime += 32; if (%client.defendTime >= %client.nextDefendRotation) @@ -77,15 +92,13 @@ function AIEnhancedDefendLocation::monitor(%task, %client) %client.nextDefendRotation = getRandom(5000, 10000); // TODO: Replace with something that detects interiors as well - %client.moveLocation = getRandomPositionOnTerrain(%client.defendLocation, 40); - %client.isMoving = true; + %client.setMoveTarget(getRandomPositionOnTerrain(%client.defendTargetLocation, 40)); } } else { %client.defendTime = -1; - %client.moveLocation = %client.defendLocation; - %client.isMoving = true; + %client.setMoveTarget(%client.defendTargetLocation); } } @@ -103,7 +116,7 @@ function AIEnhancedDefendLocation::monitor(%task, %client) function AIEnhancedScoutLocation::initFromObjective(%task, %objective, %client) { } function AIEnhancedScoutLocation::assume(%task, %client) { %task.setMonitorFreq(1); %client.currentNode = -1; } function AIEnhancedScoutLocation::retire(%task, %client) { } -function AIEnhancedScoutLocation::weight(%task, %client) { %task.setWeight(500); } +function AIEnhancedScoutLocation::weight(%task, %client) { %task.setWeight($DXAI::Task::MediumPriority); } function AIEnhancedScoutLocation::monitor(%task, %client) { @@ -117,25 +130,23 @@ function AIEnhancedScoutLocation::monitor(%task, %client) %client.currentNode = NavGraph.randNode(%client.scoutLocation, %client.scoutDistance, true, true); if (%client.currentNode != -1) - { - %client.moveLocation = NavGraph.nodeLoc(%client.currentNode); - %client.isMoving = true; - } + %client.setMoveTarget(NavGraph.nodeLoc(%client.currentNode)); } // We're moving, or are near enough to our target else { - %pathDistance = %client.getPathDistance(%client.moveLocation); + %pathDistance = %client.getPathDistance(%client.moveTarget); + // Don't move if we're close enough to our next node if (%pathDistance <= 40 && %client.isMoving) { - %client.isMoving = false; + %client.setMoveTarget(-1); %client.nextScoutRotation = getRandom(5000, 10000); %client.scoutTime += 32; } - else if(%client.getPathDistance(%client.moveLocation) > 40) + else if(%client.getPathDistance(%client.moveTarget) > 40) { - %client.isMoving = true; + // %client.setMoveTarget(%client.moveTarget); %client.scoutTime = 0; } else @@ -152,10 +163,7 @@ function AIEnhancedScoutLocation::monitor(%task, %client) // Ensure that we found a node. if (%client.currentNode != -1) - { - %client.moveLocation = NavGraph.nodeLoc(%client.currentNode); - %client.isMoving = true; - } + %client.setMoveTarget(NavGraph.nodeLoc(%client.currentNode)); } } } @@ -174,90 +182,88 @@ function AIEnhancedEngageTarget::retire(%task, %client) { } function AIEnhancedEngageTarget::weight(%task, %client) { - if (!isObject(%client.engageTarget)) - { - %visibleObjects = %client.getObjectsInViewcone($TypeMasks::PlayerObjectType, %client.viewDistance, true); - - // Choose the closest target - // TODO: Choose on more advanced metrics like HP - %chosenTarget = -1; - %chosenTargetDistance = 9999; - for (%iteration = 0; %iteration < %visibleObjects.getCount(); %iteration++) + if (!isObject(%client.engageTarget)) { - %potentialTarget = %visibleObjects.getObject(%iteration); - - %potentialTargetDistance = vectorDist(%potentialTarget.getPosition(), %client.player.getPosition()); - if (%potentialTarget.client.team != %client.team && %potentialTargetDistance < %chosenTargetDistance) - { - %chosenTargetDistance = %potentialTargetDistance; - %chosenTarget = %potentialTarget; - } + %visibleObjects = %client.getObjectsInViewcone($TypeMasks::PlayerObjectType, %client.viewDistance, true); + + // Choose the closest target + // TODO: Choose on more advanced metrics like HP + %chosenTarget = -1; + %chosenTargetDistance = 9999; + for (%iteration = 0; %iteration < %visibleObjects.getCount(); %iteration++) + { + %potentialTarget = %visibleObjects.getObject(%iteration); + + %potentialTargetDistance = vectorDist(%potentialTarget.getPosition(), %client.player.getPosition()); + if (%potentialTarget.client.team != %client.team && %potentialTargetDistance < %chosenTargetDistance) + { + %chosenTargetDistance = %potentialTargetDistance; + %chosenTarget = %potentialTarget; + } + } + + %visibleObjects.delete(); + %client.engageTarget = %chosenTarget; } - - %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); + 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; - } + // TODO: Go to the last known position. + if (%hitObject != %client.engageTarget) + %client.engageTarget = -1; + } - if (!isObject(%client.engageTarget) && %client.engageTargetLastPosition $= "") - %task.setWeight(0); - else - %task.setWeight(1000); + if (!isObject(%client.engageTarget) && %client.engageTargetLastPosition $= "") + %task.setWeight($DXAI::Task::NoPriority); + else + %task.setWeight($DXAI::Task::VeryHighPriority); } 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++) - { - // Weapons with a decent bit of spread should be used <= 20m + 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++) + { + // Weapons with a decent bit of spread should be used <= 20m + } + + %player.selectWeaponSlot(%bestWeapon); + %client.engageTargetLastPosition = %client.engageTarget.getWorldBoxCenter(); + + %client.setMoveTarget(getRandomPositionOnTerrain(%client.engageTargetLastPosition, 40)); + + %client.pressFire(); } - - %player.selectWeaponSlot(%bestWeapon); - %client.engageTargetLastPosition = %client.engageTarget.getWorldBoxCenter(); - - %client.isMoving = true; - %client.moveLocation = getRandomPositionOnTerrain(%client.engageTargetLastPosition, 40); - - %client.pressFire(); - } - else if (%client.engageTargetLastPosition !$= "") - { - %client.isMoving = true; - %client.moveLocation = %client.engageTargetLastPosition; + else if (%client.engageTargetLastPosition !$= "") + { + %client.setMoveTarget(%client.engageTargetLastPosition); - if (vectorDist(%client.player.getPosition(), %client.engageTargetLastPosition) <= 10) - { - %client.engageTargetLastPosition = ""; - %client.isMoving = false; + if (vectorDist(%client.player.getPosition(), %client.engageTargetLastPosition) <= 10) + { + %client.engageTargetLastPosition = ""; + %client.setMoveTarget(-1); + } } - } } //------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------ // +Param %bot.shouldRearm: A boolean representing whether or not this bot should go // and rearm. -// +Param %bot.targetInventory: The ID of the inventory station to rearm at. +// +Param %bot.rearmTarget: The ID of the inventory station to rearm at. //------------------------------------------------------------------------------------------` function AIEnhancedRearmTask::initFromObjective(%task, %objective, %client) { } function AIEnhancedRearmTask::assume(%task, %client) { %task.setMonitorFreq(1); } @@ -265,30 +271,27 @@ function AIEnhancedRearmTask::retire(%task, %client) { } function AIEnhancedRearmTask::weight(%task, %client) { - if (%client.shouldRearm) - %task.setWeight(600); - else - %task.setWeight(0); + if (%client.shouldRearm) + %task.setWeight($DXAI::Task::HighPriority); + else + %task.setWeight($DXAI::Task::NoPriority); } function AIEnhancedRearmTask::monitor(%task, %client) { - if (!isObject(%client.targetInventory)) - %client.targetInventory = %client.getClosestInventory(); - - if (isObject(%client.targetInventory)) - { - // Politely wait if someone is already on it. - if (vectorDist(%client.targetInventory.getPosition(), %client.player.getPosition()) <= 7 && isObject(%client.targetInventory.triggeredBy)) - %client.isMoving = false; - else + if (!isObject(%client.rearmTarget)) + %client.rearmTarget = %client.getClosestInventory(); + + if (isObject(%client.rearmTarget)) { - %client.isMoving = true; - %client.moveLocation = %client.targetInventory.getPosition(); + // Politely wait if someone is already on it. + if (vectorDist(%client.rearmTarget.getPosition(), %client.player.getPosition()) <= 7 && isObject(%client.rearmTarget.triggeredBy)) + %client.setMoveTarget(-1); + else + %client.setMoveTarget(%client.rearmTarget.getPosition()); } - } - else - %client.shouldRearm = false; // No inventories? + else + %client.shouldRearm = false; // No inventories? } //------------------------------------------------------------------------------------------ @@ -296,54 +299,108 @@ function AIEnhancedRearmTask::monitor(%task, %client) // Description: A task that actually makes the bots return a flag that's nearby. //------------------------------------------------------------------------------------------` function AIEnhancedReturnFlagTask::initFromObjective(%task, %objective, %client) { } -function AIEnhancedReturnFlagTask::assume(%task, %client) { %task.setMonitorFreq(1); } +function AIEnhancedReturnFlagTask::assume(%task, %client) { %task.setMonitorFreq(32); } function AIEnhancedReturnFlagTask::retire(%task, %client) { } function AIEnhancedReturnFlagTask::weight(%task, %client) { - %flag = nameToID("Team" @ %client.team @ "Flag1"); - if (!isObject(%flag) || %flag.isHome) - { - %task.setWeight(0); - %client.targetFlag = -1; - %client.isMoving = false; - } - else - { - // TODO: For now, all the bots go after it! Make this check if the bot is range. - %task.setWeight(700); - - %client.targetFlag = %flag; - } + %flag = nameToID("Team" @ %client.team @ "Flag1"); + if (!isObject(%flag) || %flag.isHome) + { + // %client.setMoveTarget(-1); + %task.setWeight($DXAI::Task::NoPriority); + } + else + { + // TODO: For now, all the bots go after it! Make this check if the bot is range. + %task.setWeight($DXAI::Task::HighPriority); + %client.returnFlagTarget = %flag; + } } function AIEnhancedReturnFlagTask::monitor(%task, %client) { - if (!isObject(%client.targetFlag)) - return; - - // TODO: Make the bot engage the flag runner if its currently held. - %client.isMoving = true; - %client.moveLocation = %client.targetFlag.getPosition(); + if (!isObject(%client.returnFlagTarget)) + return; + + // %client.setFollowTarget(%client.returnFlagTarget, 0, 0, false); +} +//------------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------------ +// Description: A task that performs path correction. +//------------------------------------------------------------------------------------------` +function AIEnhancedPathCorrectionTask::initFromObjective(%task, %objective, %client) { } +function AIEnhancedPathCorrectionTask::assume(%task, %client) { %task.setMonitorFreq(1); } +function AIEnhancedPathCorrectionTask::retire(%task, %client) { } + +function AIEnhancedPathCorrectionTask::weight(%task, %client) +{ + %task.setWeight(0); +} + +function AIEnhancedPathCorrectionTask::monitor(%task, %client) +{ + +} +//------------------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------------------ +// Description: A task that triggers bots to grab & run the enemy flag. +//------------------------------------------------------------------------------------------ +function AIEnhancedFlagCaptureTask::initFromObjective(%task, %objective, %client) { } +function AIEnhancedFlagCaptureTask::assume(%task, %client) { %task.setMonitorFreq(1); } +function AIEnhancedFlagCaptureTask::retire(%task, %client) { } + +function AIEnhancedFlagCaptureTask::weight(%task, %client) +{ + if (%client.shouldRunFlag) + { + // First, is the enemy flag home? + %enemyTeam = %client.team == 1 ? 2 : 1; + %enemyFlag = nameToID("Team" @ %enemyTeam @ "Flag1"); + + if (isObject(%enemyFlag) && %enemyFlag.isHome) + { + %client.targetCaptureFlag = %enemyFlag; + %task.setWeight($DXAI::Task::MediumPriority); + } + } + else + %task.setWeight($DXAI::Task::NoPriority); +} + +function AIEnhancedFlagCaptureTask::monitor(%task, %client) +{ + if (!isObject(%client.targetCaptureFlag)) + return; + + %client.isMovingToTarget = true; + // if (%client.targetCaptureFlag.getObjectMount() != %client.player) + // %client.setMoveTarget(%client.targetCaptureFlag.getPosition()); + //// else + %client.setMoveTarget(nameToID("Team" @ %client.team @ "Flag1").getPosition()); } //------------------------------------------------------------------------------------------ function ObjectiveNameToVoice(%objective) { - %result = "avo.grunt"; - switch$(%objective) - { - case "AIEnhancedReturnFlagTask": - %result = "slf.def.flag"; - case "AIEnhancedRearmTask": - %result = "avo.grunt"; - case "AIEnhancedEngageTarget": - %result = "slf.att.attack"; - case "AIEnhancedScoutLocation": - %result = "slf.def.defend"; - case "AIEnhancedEscort": - %result = "slf.tsk.cover"; - } - - return %result; + %result = "avo.grunt"; + switch$(%objective) + { + case "AIEnhancedReturnFlagTask": + %result = "slf.def.flag"; + case "AIEnhancedRearmTask": + %result = "avo.grunt"; + case "AIEnhancedEngageTarget": + %result = "slf.att.attack"; + case "AIEnhancedScoutLocation": + %result = "slf.def.defend"; + case "AIEnhancedDefendLocation": + %result = "slf.def.defend"; + case "AIEnhancedEscort": + %result = "slf.tsk.cover"; + } + + return %result; } \ No newline at end of file