mirror of
https://github.com/exogen/t2-mapper.git
synced 2026-07-11 06:24:47 +00:00
Initial commit
This commit is contained in:
parent
2211ed7650
commit
ebb3dc9cdd
10121 changed files with 801 additions and 4 deletions
524
docs/base/@vl2/scripts.vl2/scripts/aiHunters.cs
Normal file
524
docs/base/@vl2/scripts.vl2/scripts/aiHunters.cs
Normal file
|
|
@ -0,0 +1,524 @@
|
|||
//-----------------------------------------------
|
||||
// AI functions for Hunters
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// globals
|
||||
$AIHuntersFlagSearchRadius = 300;
|
||||
$AIHuntersCloseFlagDist = 40;
|
||||
$AIHuntersAttackClientFlagCount = 10;
|
||||
$AIHuntersMinFlagsToCap = 3;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function HuntersGame::onAIRespawn(%game, %client)
|
||||
{
|
||||
//add the default task
|
||||
if (! %client.defaultTasksAdded)
|
||||
{
|
||||
%client.defaultTasksAdded = true;
|
||||
%client.addTask(AIEngageTask);
|
||||
%client.addTask(AIPickupItemTask);
|
||||
%client.addTask(AIUseInventoryTask);
|
||||
%client.addTask(AITauntCorpseTask);
|
||||
%client.addTask(AIEngageTurretTask);
|
||||
%client.addtask(AIDetectMineTask);
|
||||
%client.addTask(AIPatrolTask);
|
||||
%client.huntersTask = %client.addTask(AIHuntersTask);
|
||||
}
|
||||
|
||||
//set the inv flag
|
||||
%client.spawnUseInv = true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function HuntersGame::AIInit(%game)
|
||||
{
|
||||
//call the default AIInit() function
|
||||
AIInit();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//AIHuntersTask functions
|
||||
//---------------------------------------------------------------------------
|
||||
function AIHuntersTask::init(%task, %client)
|
||||
{
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function AIHuntersTask::assume(%task, %client)
|
||||
{
|
||||
%task.setWeightFreq(10);
|
||||
%task.setMonitorFreq(10);
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = -1;
|
||||
%task.getHealth = -1;
|
||||
%task.capFlags = false;
|
||||
}
|
||||
|
||||
function AIHuntersTask::retire(%task, %client)
|
||||
{
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = -1;
|
||||
%task.getHealth = -1;
|
||||
%task.capFlags = false;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function AIHuntersTask::weight(%task, %client)
|
||||
{
|
||||
// init flag search vars
|
||||
%player = %client.player;
|
||||
if (!isObject(%player))
|
||||
return;
|
||||
|
||||
%clientPos = %player.getWorldBoxCenter();
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = -1;
|
||||
%task.capFlags = false;
|
||||
|
||||
//find the closest flag
|
||||
%flagVars = AIFindClosestFlag(%client, $AIHuntersFlagSearchRadius);
|
||||
%closestFlag = getWord(%flagVars, 0);
|
||||
%closestFlagDist = getWord(%flagVars, 1);
|
||||
|
||||
//find the dist to the nexus
|
||||
%nexusPos = Game.Nexus.getId().getWorldBoxCenter();
|
||||
%nexusDist = %client.getPathDistance(%nexusPos);
|
||||
if (%nexusDist < 0)
|
||||
%nexusDist = 32767;
|
||||
|
||||
//validate the health item
|
||||
if (isObject(%task.getHealth))
|
||||
{
|
||||
if (%task.getHealth.isHidden())
|
||||
%task.getHealth = -1;
|
||||
else if ((%task.getHealth.getDataBlock().getName() $= "DeployedStationInventory") ||
|
||||
(%task.getHealth.getDataBlock().getName() $= "StationInventory"))
|
||||
{
|
||||
if (%task.getHealth.isDisabled() && !%task.getHealth.isPowered())
|
||||
%task.getHealth = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//find the dist to the closest health
|
||||
%healthDist = 32767;
|
||||
%damage = %client.player.getDamagePercent();
|
||||
if (%client.flagCount < 5)
|
||||
%damageTolerance = 0.7;
|
||||
else
|
||||
%damageTolerance = 0.25 + ((%client.getSkillLevel() * %client.getSkillLevel()) * 0.35);
|
||||
if (%damage > %damageTolerance)
|
||||
{
|
||||
if (!isObject(%task.getHealth))
|
||||
{
|
||||
//search for a health kit
|
||||
%closestHealth = AIFindSafeItem(%client, "Health");
|
||||
if (isObject(%closestHealth))
|
||||
{
|
||||
%healthDist = %client.getPathDistance(%closestHealth.getWorldBoxCenter());
|
||||
if (%healthDist < 0)
|
||||
%healthDist = 32767;
|
||||
else
|
||||
%healthItem = %closestHealth;
|
||||
}
|
||||
|
||||
//else search for an inventory station
|
||||
else
|
||||
{
|
||||
%result = AIFindClosestInventory(%client, false);
|
||||
%closestInv = getWord(%result, 0);
|
||||
%closestDist = getWord(%result, 1);
|
||||
if (isObject(%closestInv))
|
||||
{
|
||||
%healthDist = %closestDist;
|
||||
%healthItem = %closestInv;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
%healthDist = %client.getPathDistance(%task.getHealth.getWorldBoxCenter());
|
||||
if (%healthDist < 0)
|
||||
{
|
||||
%healthDist = 32767;
|
||||
%task.getHealth = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
%task.getHealth = -1;
|
||||
|
||||
//see if we need to cap - make sure we're actually able first
|
||||
%mustCap = false;
|
||||
%shouldCap = false;
|
||||
%numToScore = %client.flagCount - 1;
|
||||
%hoardModeOn = Game.hoardModeActive();
|
||||
if ((!Game.greedMode || %numToScore >= Game.greedMinFlags) && !Game.hoardModeActive() && %numToScore >= $AIHuntersMinFlagsToCap)
|
||||
{
|
||||
//find out how many points would be scored
|
||||
%potentialScore = (%numToScore * (%numToScore + 1)) / 2;
|
||||
|
||||
//find out how many flags we need to take the lead...
|
||||
%needFlagsForLead = 0;
|
||||
%highestScore = 0;
|
||||
%clientIsInLead = false;
|
||||
if (Game.teamMode)
|
||||
{
|
||||
%teamCount = Game.numTeams;
|
||||
for (%i = 1; %i <= %teamCount; %i++)
|
||||
{
|
||||
if ($teamScore[%i] > %highestScore)
|
||||
%highestScore = $teamScore[%i];
|
||||
}
|
||||
|
||||
//see if we're in the lead...
|
||||
if (%highestScore == $teamScore[%client.team])
|
||||
%clientIsInLead = true;
|
||||
else
|
||||
{
|
||||
%tempScore = $teamScore[%client.team] + %potentialScore;
|
||||
%flagValue = %numToScore + 1;
|
||||
while (%tempScore < %highestScore)
|
||||
{
|
||||
%tempScore += %flagValue;
|
||||
%flagValue++;
|
||||
%needFlagsForLead++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
%clientCount = ClientGroup.getCount();
|
||||
for (%i = 0; %i < %clientCount; %i++)
|
||||
{
|
||||
%cl = ClientGroup.getObject(%i);
|
||||
if (%cl.score > %highestScore)
|
||||
%highestScore = %cl.score;
|
||||
}
|
||||
|
||||
//see if we're in the lead
|
||||
if (%highestScore == %client.score)
|
||||
%clientIsInLead = true;
|
||||
else
|
||||
{
|
||||
%tempScore = %client.score + %potentialScore;
|
||||
%flagValue = %numToScore + 1;
|
||||
while (%tempScore < %highestScore)
|
||||
{
|
||||
%tempScore += %flagValue;
|
||||
%flagValue++;
|
||||
%needFlagsForLead++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//the current target is more dangerous than the closest enemy
|
||||
%currentTarget = %client.getEngageTarget();
|
||||
if (AIClientIsAlive(%currentTarget))
|
||||
{
|
||||
%closestEnemy = %currentTarget;
|
||||
%closestEnemydist = %client.getPathDistance(%currentTarget.player.position);
|
||||
if (%closestEnemyDist < 0)
|
||||
%closestEnemyDist = 32767;
|
||||
}
|
||||
else
|
||||
{
|
||||
%losTimeout = $AIClientMinLOSTime + ($AIClientLOSTimeout * %client.getSkillLevel());
|
||||
%result = AIFindClosestEnemy(%client, $AIHuntersCloseFlagDist, %losTimeout);
|
||||
%closestEnemy = getWord(%result, 0);
|
||||
%closestEnemydist = getWord(%result, 1);
|
||||
}
|
||||
|
||||
//find out how much time is left...
|
||||
%curTimeLeftMS = ($Host::TimeLimit * 60 * 1000) + $missionStartTime - getSimTime();
|
||||
|
||||
//If there's a tough or equal enemy nearby, or no flags, think about capping
|
||||
//ie. never cap if there are flags nearby and no enemies...
|
||||
if ((AICheckEnemyDanger(%client, 35) >= 3 && %damage > %damageTolerance) ||
|
||||
(!isObject(%closestFlag) || %closestFlagDist > $AIHuntersCloseFlagDist))
|
||||
{
|
||||
//if we've got enough to take the lead, and there are no flags in the vicinity
|
||||
if ((!%clientIsInLead && %needFlagsForLead == 0) || %highestScore == 0)
|
||||
%mustCap = true;
|
||||
|
||||
//else if we're about to get our butt kicked...
|
||||
else if (AIClientIsAlive(%closestEnemy) && AIEngageWhoWillWin(%closestEnemy, %client) == %closestEnemy)
|
||||
{
|
||||
%mustCap = true;
|
||||
}
|
||||
|
||||
//else if there's no time left in the mission, cap whatever we've got now...
|
||||
else if (%curTimeLeftMS <= 30000)
|
||||
%mustCap = true;
|
||||
|
||||
//else we don't need to cap - see if we should to play it smart
|
||||
else
|
||||
{
|
||||
//if we'd need more than just a couple to take the lead...
|
||||
%waitForFlagsTolerance = %client.getSkillLevel() * $AIHuntersMinFlagsToCap * 2;
|
||||
if (%needFlagsForLead == 0 || (%needFlagsForLead > %waitForFlagsTolerance))
|
||||
{
|
||||
%numEnemyFlags = 0;
|
||||
%clientCount = ClientGroup.getCount();
|
||||
for (%i = 0; %i < %clientCount; %i++)
|
||||
{
|
||||
%cl = ClientGroup.getObject(%i);
|
||||
if (%cl != %client && %cl.flagCount > %numEnemyFlags)
|
||||
%numEnemyFlags = %cl.flagCount;
|
||||
}
|
||||
|
||||
//if we're in the lead, or no one has the flags we need, or it's team mode,
|
||||
//decide whether to cap based on skill level
|
||||
if (%needFlagsForLead == 0 || %numEnemyFlags < %needFlagsForLead || Game.teamMode)
|
||||
{
|
||||
if (%numToScore >= $AIHuntersMinFlagsToCap + (%client.getSkillLevel() * %client.getSkillLevel() * 15))
|
||||
{
|
||||
%shouldCap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//now that we've checked all the possibilities, see if we should or must cap
|
||||
if (%mustCap || %shouldCap)
|
||||
{
|
||||
if (%mustCap)
|
||||
%task.setWeight($AIHuntersWeightMustCap);
|
||||
else
|
||||
%task.setWeight($AIHuntersWeightShouldCap);
|
||||
|
||||
%task.capFlags = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// if we've made it this far, we either can't cap, or there's no need to cap... //
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//see if we need health
|
||||
if (%damage > %damageTolerance && (isObject(%healthItem) || isObject(%task.getHealth)))
|
||||
{
|
||||
if (!isObject(%task.getHealth))
|
||||
%task.getHealth = %healthItem;
|
||||
|
||||
%task.setWeight($AIHuntersWeightNeedHealth);
|
||||
return;
|
||||
}
|
||||
|
||||
//find the closest player with the most flags (that we have los to)
|
||||
%losTimeout = $AIClientMinLOSTime + ($AIClientLOSTimeout * %client.getSkillLevel());
|
||||
%bestClientToEngage = findClientWithMostFlags(%client, %losTimeout);
|
||||
%bestClientDist = 32767;
|
||||
if (AIClientIsAlive(%bestClientToEngage))
|
||||
{
|
||||
%bestClientDist = %client.getPathDistance(%bestClientToEngage.player.position);
|
||||
if (%bestClientDist < 0)
|
||||
%bestClientDist = 32767;
|
||||
}
|
||||
|
||||
//see if there's a flag
|
||||
if (isObject(%closestFlag))
|
||||
{
|
||||
//see if there's a client to shoot
|
||||
if (AIClientIsAlive(%bestClientToEngage))
|
||||
{
|
||||
//calc weight base on closesness to the nearest flag vs. and number of flags the client has...
|
||||
%engageDistFactor = 30 + %bestClientDist - (%bestClientToEngage.flagCount * 5);
|
||||
if (%closestFlagDist < %engageDistFactor)
|
||||
{
|
||||
%task.pickupFlag = %closestFlag;
|
||||
%task.engageTarget = %bestClientToEngage;
|
||||
%task.setWeight($AIHuntersWeightPickupFlag);
|
||||
}
|
||||
|
||||
//otherwise, ignore the flag, and go for the client
|
||||
else
|
||||
{
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = %bestClientToEngage;
|
||||
%task.setWeight($AIHuntersWeightMustEngage);
|
||||
}
|
||||
}
|
||||
|
||||
//else no one to attack
|
||||
else
|
||||
{
|
||||
%task.pickupFlag = %closestFlag;
|
||||
%task.engageTarget = -1;
|
||||
%task.setWeight($AIHuntersWeightPickupFlag);
|
||||
}
|
||||
}
|
||||
|
||||
//else no flag, see if we have someone to attack
|
||||
else if (AIClientIsAlive(%bestClientToEngage))
|
||||
{
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = %bestClientToEngage;
|
||||
%task.setWeight($AIHuntersWeightShouldEngage);
|
||||
}
|
||||
|
||||
//nothing hunter's related to do...
|
||||
else
|
||||
{
|
||||
%task.pickupFlag = -1;
|
||||
%task.engageTarget = -1;
|
||||
%task.setWeight(0);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function AIHuntersTask::monitor(%task, %client)
|
||||
{
|
||||
//see if we should cap
|
||||
if (%task.capFlags)
|
||||
{
|
||||
%nexusPos = Game.Nexus.getId().getWorldBoxCenter();
|
||||
%client.stepMove(%nexusPos, 0.25);
|
||||
}
|
||||
|
||||
//see if we've got a flag to pick up and/or someone to engage
|
||||
else if (isObject(%task.pickupFlag))
|
||||
{
|
||||
%client.stepMove(%task.pickupFlag.getWorldBoxCenter(), 0.25);
|
||||
|
||||
if (AIClientIsAlive(%task.engageTarget))
|
||||
%client.setEngageTarget(%task.engageTarget);
|
||||
}
|
||||
|
||||
//see if we've should go for health...
|
||||
else if (isObject(%task.getHealth))
|
||||
{
|
||||
%client.stepMove(%task.getHealth.getWorldBoxCenter(), 1);
|
||||
|
||||
if (AIClientIsAlive(%task.engageTarget))
|
||||
%client.setEngageTarget(%task.engageTarget);
|
||||
}
|
||||
|
||||
//else see if there's just someone to engage
|
||||
else if (AIClientIsAlive(%task.engageTarget))
|
||||
%client.stepEngage(%task.engageTarget);
|
||||
|
||||
//if we're not engaging someone related to the hunters task, engage whoever the AIEngageTask wants...
|
||||
else
|
||||
%client.setEngageTarget(%client.shouldEngage);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// AIHunters utility functions
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//this function checks to make sure a bot isn't in a mosh pit of enemies
|
||||
//notice it cheats by not using LOS... )
|
||||
function AICheckEnemyDanger(%client, %radius)
|
||||
{
|
||||
%numEnemies = 0;
|
||||
for (%i = 0; %i < ClientGroup.getCount(); %i++)
|
||||
{
|
||||
%cl = ClientGroup.getObject(%i);
|
||||
if (AIClientIsAlive(%cl) && %cl.team != %client.team)
|
||||
{
|
||||
%dist = %client.getPathDistance(%cl.player.position);
|
||||
if (%dist < %radius)
|
||||
{
|
||||
%winner = AIEngageWhoWillWin(%cl, %client);
|
||||
if (%winner == %cl)
|
||||
%numEnemies += 3;
|
||||
else if (%winner != %client)
|
||||
%numEnemies++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return %numEnemies;
|
||||
}
|
||||
|
||||
function AIFindClosestFlag(%client, %radius)
|
||||
{
|
||||
%closestFlag = -1;
|
||||
%closestDist = %radius;
|
||||
%flagCount = $FlagGroup.getCount();
|
||||
for (%i = 0; %i < %flagCount; %i++)
|
||||
{
|
||||
%flag = $FlagGroup.getObject(%i);
|
||||
%flagPos = %flag.getWorldBoxCenter();
|
||||
%dist = %client.getPathDistance(%flagPos);
|
||||
|
||||
if (%dist > 0 && %dist < %closestDist)
|
||||
{
|
||||
%closestDist = %dist;
|
||||
%closestFlag = %flag;
|
||||
}
|
||||
}
|
||||
return %closestFlag @ " " @ %closestDist;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function findClientWithMostFlags(%srcClient, %losTimeout)
|
||||
{
|
||||
%clientCount = 0;
|
||||
%closestClient = -1;
|
||||
%highestFlagFactor = -1; //take both distance and flag count into consideration
|
||||
|
||||
%count = ClientGroup.getCount();
|
||||
for(%i = 0; %i < %count; %i++)
|
||||
{
|
||||
%cl = ClientGroup.getObject(%i);
|
||||
|
||||
//make sure we find someone who's alive, and on an opposing team
|
||||
if (AIClientIsAlive(%cl) && %cl.team != %srcClient.team)
|
||||
{
|
||||
%clIsCloaked = false;
|
||||
if (%cl.player.getInventory("CloakingPack") > 0 && %cl.player.getImageState($BackpackSlot) $= "activate")
|
||||
%clIsCloaked = true;
|
||||
|
||||
//make sure the client can see the enemy
|
||||
%hasLOS = %srcClient.hasLOSToClient(%cl);
|
||||
%losTime = %srcClient.getClientLOSTime(%cl);
|
||||
if (%hasLOS || (%losTime < %losTimeout && AIClientIsAlive(%cl, %losTime + 1000)))
|
||||
{
|
||||
%testPos = %cl.player.getWorldBoxCenter();
|
||||
%distance = %srcClient.getPathDistance(%testPos);
|
||||
if (%distance < 0)
|
||||
%distance = 32767;
|
||||
|
||||
//calculate the flag factor
|
||||
%flagFactor = (100 - %distance) + (%cl.flagCount * 5);
|
||||
|
||||
//see if it's the most suitable client...
|
||||
if (%flagFactor > %highestFlagFactor && (!%clIsCloaked || %distance < 8))
|
||||
{
|
||||
%closestClient = %cl;
|
||||
%highestFlagFactor = %flagFactor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return %closestClient;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function aih()
|
||||
{
|
||||
exec("scripts/aiHunters.cs");
|
||||
}
|
||||
|
||||
function aiHlist()
|
||||
{
|
||||
%count = ClientGroup.getCount();
|
||||
for (%i = 0; %i < %count; %i++)
|
||||
{
|
||||
%cl = ClientGroup.getObject(%i);
|
||||
if (%cl.isAIControlled())
|
||||
error(%cl SPC getTaggedString(%cl.name) SPC "score:" SPC %cl.score SPC "flags:" SPC %cl.flagCount - 1 SPC "capFlags:" SPC %cl.huntersTask.capFlags);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue