mirror of
https://github.com/Ragora/T2-DXAI.git
synced 2026-01-19 18:14:45 +00:00
165 lines
6.3 KiB
C#
165 lines
6.3 KiB
C#
// DXAI_Objectives.cs
|
|
// Objectives for the AI system
|
|
// Copyright (c) 2014 Robert MacGregor
|
|
|
|
//----------------------------------------------------------------------
|
|
// The AIVisualAcuity task is a complementary task for the AI grunt systems
|
|
// to perform better at recognizing things visually with reasonably
|
|
// Human perception capabilities.
|
|
// ---------------------------------------------------------------------
|
|
|
|
function AIVisualAcuity::initFromObjective(%task, %objective, %client)
|
|
{
|
|
// Called to initialize from an objective object
|
|
}
|
|
|
|
function AIVisualAcuity::assume(%task, %client)
|
|
{
|
|
// Called when the bot starts the task
|
|
}
|
|
|
|
function AIVisualAcuity::retire(%task, %client)
|
|
{
|
|
// Called when the bot stops the task
|
|
}
|
|
|
|
function AIVisualAcuity::weight(%task, %client)
|
|
{
|
|
%task.setWeight(999);
|
|
}
|
|
|
|
function AIConnection::visualAcuityUpdate(%this)
|
|
{
|
|
// Called when the bot is performing the task
|
|
if (%this.enableVisualDebug)
|
|
{
|
|
if (!isObject(%this.originMarker))
|
|
{
|
|
%this.originMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Origin"; };
|
|
%this.clockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Clockwise"; };
|
|
%this.counterClockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Counter Clockwise"; };
|
|
%this.upperMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Upper"; };
|
|
%this.lowerMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Lower"; };
|
|
}
|
|
|
|
%viewCone = %this.calculateViewCone();
|
|
%coneOrigin = getWords(%viewCone, 0, 2);
|
|
%viewConeClockwiseVector = getWords(%viewCone, 3, 5);
|
|
%viewConeCounterClockwiseVector = getWords(%viewCone, 6, 8);
|
|
|
|
%viewConeUpperVector = getWords(%viewCone, 9, 11);
|
|
%viewConeLowerVector = getWords(%viewCone, 12, 14);
|
|
|
|
// Update all the markers
|
|
%this.clockwiseMarker.setPosition(%viewConeClockwiseVector);
|
|
%this.counterClockwiseMarker.setPosition(%viewConeCounterClockwiseVector);
|
|
%this.upperMarker.setPosition(%viewConeUpperVector);
|
|
%this.lowerMarker.setPosition(%viewConeLowerVector);
|
|
%this.originMarker.setPosition(%coneOrigin);
|
|
}
|
|
else if (isObject(%this.originMarker))
|
|
{
|
|
%this.originMarker.delete();
|
|
%this.clockwiseMarker.delete();
|
|
%this.counterClockwiseMarker.delete();
|
|
%this.upperMarker.delete();
|
|
%this.lowerMarker.delete();
|
|
}
|
|
|
|
%result = %this.getObjectsInViewcone($TypeMasks::ProjectileObjectType | $TypeMasks::PlayerObjectType, %this.viewDistance, true);
|
|
|
|
// What can we see?
|
|
for (%i = 0; %i < %result.getCount(); %i++)
|
|
{
|
|
%current = %result.getObject(%i);
|
|
%this.awarenessTicks[%current]++;
|
|
|
|
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 properties, so we can easily determine if a dodge is necessary
|
|
if (%className $= "LinearFlareProjectile" || %className $= "LinearProjectile")
|
|
{
|
|
//%this.setDangerLocation(%current.getPosition(), 20);
|
|
|
|
// Perform a raycast to determine a hitpoint
|
|
%currentPosition = %current.getPosition();
|
|
%rayCast = containerRayCast(%currentPosition, vectorAdd(%currentPosition, vectorScale(%current.initialDirection, 200)), -1, 0);
|
|
%hitObject = getWord(%raycast, 0);
|
|
|
|
// We're set for a direct hit on us!
|
|
if (%hitObject == %this.player)
|
|
{
|
|
%this.setDangerLocation(%current.getPosition(), 30);
|
|
continue;
|
|
}
|
|
|
|
// If there is no radius damage, don't worry about it now
|
|
if (!%current.getDatablock().hasDamageRadius)
|
|
continue;
|
|
|
|
// How close is the hit loc?
|
|
%hitLocation = getWords(%rayCast, 1, 3);
|
|
%hitDistance = vectorDist(%this.player.getPosition(), %hitLocation);
|
|
|
|
// Is it within the radius damage of this thing?
|
|
if (%hitDistance <= %current.getDatablock().damageRadius)
|
|
%this.setDangerLocation(%current.getPosition(), 30);
|
|
}
|
|
// A little bit harder to detect.
|
|
else if (%className $= "GrenadeProjectile")
|
|
{
|
|
|
|
}
|
|
}
|
|
// See a player?
|
|
else if (%current.getType() & $TypeMasks::PlayerObjectType)
|
|
{
|
|
// ... 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));
|
|
|
|
%rayCast = containerRayCast(%start, %end, -1, %this.player);
|
|
%hitObject = getWord(%raycast, 0);
|
|
|
|
echo(%hitObject);
|
|
echo(%current);
|
|
if (%hitObject == %current)
|
|
%this.stepEngage(%current);
|
|
}
|
|
}
|
|
|
|
%result.delete();
|
|
}
|
|
|
|
function AIConnection::enhancedLogicUpdate(%this)
|
|
{
|
|
cancel(%this.enhancedLogicHandle);
|
|
|
|
//if (!isObject(%this.))
|
|
|
|
if (!isObject(%this.player))
|
|
{
|
|
%this.enhancedLogicHandle = %this.schedule(32, "enhancedLogicUpdate");
|
|
return;
|
|
}
|
|
|
|
%this.visualAcuityUpdate();
|
|
%this.enhancedLogicHandle = %this.schedule(32, "enhancedLogicUpdate");
|
|
}
|
|
|
|
function AIVisualAcuity::monitor(%task, %client)
|
|
{
|
|
return;
|
|
|
|
|
|
}
|