Better timed AI code; dodging code; better audible dodge code

This commit is contained in:
Robert MacGregor 2015-06-24 21:03:57 -04:00
parent aa87905cf1
commit 8687513a42
3 changed files with 134 additions and 30 deletions

View file

@ -155,6 +155,13 @@ function GameConnection::getObjectsInViewcone(%this, %typeMask, %distance, %perf
return %result; return %result;
} }
function vectorMultiply(%vec1, %vec2)
{
return (getWord(%vec1, 0) * getWord(%vec2, 0)) SPC
(getWord(%vec1, 1) * getWord(%vec2, 1)) SPC
(getWord(%vec1, 2) * getWord(%vec2, 2));
}
// If the map editor was instantiated, this will prevent a little bit // If the map editor was instantiated, this will prevent a little bit
// of console warnings // of console warnings
function Terraformer::getType(%this) { return 0; } function Terraformer::getType(%this) { return 0; }

View file

@ -118,7 +118,7 @@ function DXAI::validateEnvironment()
{ {
error("DXAI: Function 'DefaultGame::AIChooseGameObjective' detected to be overwritten by the current gamemode. Correcting ..."); error("DXAI: Function 'DefaultGame::AIChooseGameObjective' detected to be overwritten by the current gamemode. Correcting ...");
eval(%strReplace(%payloadTemplate, "<METHODNAME>", "AIChooseGameObjective")); eval(strReplace(%payloadTemplate, "<METHODNAME>", "AIChooseGameObjective"));
// Make sure the patch took // Make sure the patch took
if (game.AIChooseGameObjective($DXAI::System::RuntimeDummy) != 11595) if (game.AIChooseGameObjective($DXAI::System::RuntimeDummy) != 11595)
@ -129,7 +129,7 @@ function DXAI::validateEnvironment()
{ {
error("DXAI: Function 'DefaultGame::onAIRespawn' detected to be overwritten by the current gamemode. Correcting ... "); error("DXAI: Function 'DefaultGame::onAIRespawn' detected to be overwritten by the current gamemode. Correcting ... ");
eval(%strReplace(%payloadTemplate, "<METHODNAME>", "onAIRespawn")); eval(strReplace(%payloadTemplate, "<METHODNAME>", "onAIRespawn"));
if (game.onAIRespawn($DXAI::System::RuntimeDummy) != 11595) if (game.onAIRespawn($DXAI::System::RuntimeDummy) != 11595)
error("DXAI: Failed to patch 'DefaultGame::onAIRespawn'! DXAI may not function correctly."); error("DXAI: Failed to patch 'DefaultGame::onAIRespawn'! DXAI may not function correctly.");
@ -212,6 +212,14 @@ package DXAI_Hooks
DXAI::update(); DXAI::update();
} }
// Listen server fix
function disconnect()
{
parent::disconnect();
DXAI::Cleanup();
}
function DefaultGame::AIChangeTeam(%game, %client, %newTeam) function DefaultGame::AIChangeTeam(%game, %client, %newTeam)
{ {
// Remove us from the old commander's control first // Remove us from the old commander's control first
@ -250,13 +258,13 @@ package DXAI_Hooks
parent::onExplode(%data, %proj, %pos, %mod); parent::onExplode(%data, %proj, %pos, %mod);
// Look for any bots nearby // Look for any bots nearby
InitContainerRadiusSearch(%pos, 10, $TypeMasks::PlayerObjectType); InitContainerRadiusSearch(%pos, 100, $TypeMasks::PlayerObjectType);
while ((%targetObject = containerSearchNext()) != 0) while ((%targetObject = containerSearchNext()) != 0)
{ {
%currentDistance = containerSearchCurrRadDamageDist(); %currentDistance = containerSearchCurrRadDamageDist();
if (%currentDistance > 10 || !%targetObject.client.isAIControlled()) if (%currentDistance > 100 || !%targetObject.client.isAIControlled())
continue; continue;
// Get the projectile team // Get the projectile team
@ -276,12 +284,12 @@ package DXAI_Hooks
%heardHit = false; %heardHit = false;
%hitDistance = vectorDist(%targetObject.getWorldBoxCenter(), %pos); %hitDistance = vectorDist(%targetObject.getWorldBoxCenter(), %pos);
if (%hitDistance < 55 && %hitDistance <= %data.explosion.soundProfile.description.maxDistance) if (%hitDistance <= 20 && %hitDistance <= %data.explosion.soundProfile.description.maxDistance)
%heardHit = true; %heardHit = true;
// If the thing has any radius damage (and we heard it), run around a little bit if we need to // If the thing has any radius damage (and we heard it), run around a little bit if we need to
if (%data.indirectDamage != 0 && %shouldRun) if (%data.indirectDamage != 0 && %heardHit)
%targetObject.client.setDangerLocation(%pos, 20); %targetObject.client.schedule(getRandom(250, 400), "setDangerLocation", %pos, 20);
// If we should care and it wasn't a teammate projectile, notify // If we should care and it wasn't a teammate projectile, notify
if (%shouldRun && %projectileTeam != %targetObject.client.team) if (%shouldRun && %projectileTeam != %targetObject.client.team)

View file

@ -28,22 +28,21 @@ function AIVisualAcuity::weight(%task, %client)
%task.setWeight(999); %task.setWeight(999);
} }
function AIVisualAcuity::monitor(%task, %client) function AIConnection::visualAcuityUpdate(%this)
{ {
// Called when the bot is performing the task // Called when the bot is performing the task
if (%this.enableVisualDebug)
if (%client.enableVisualDebug)
{ {
if (!isObject(%client.originMarker)) if (!isObject(%this.originMarker))
{ {
%client.originMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %client.team; name = %client.namebase SPC " Origin"; }; %this.originMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Origin"; };
%client.clockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %client.team; name = %client.namebase SPC " Clockwise"; }; %this.clockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Clockwise"; };
%client.counterClockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %client.team; name = %client.namebase SPC " Counter Clockwise"; }; %this.counterClockwiseMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Counter Clockwise"; };
%client.upperMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %client.team; name = %client.namebase SPC " Upper"; }; %this.upperMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Upper"; };
%client.lowerMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %client.team; name = %client.namebase SPC " Lower"; }; %this.lowerMarker = new Waypoint(){ datablock = "WaypointMarker"; team = %this.team; name = %this.namebase SPC " Lower"; };
} }
%viewCone = %client.calculateViewCone(); %viewCone = %this.calculateViewCone();
%coneOrigin = getWords(%viewCone, 0, 2); %coneOrigin = getWords(%viewCone, 0, 2);
%viewConeClockwiseVector = getWords(%viewCone, 3, 5); %viewConeClockwiseVector = getWords(%viewCone, 3, 5);
%viewConeCounterClockwiseVector = getWords(%viewCone, 6, 8); %viewConeCounterClockwiseVector = getWords(%viewCone, 6, 8);
@ -52,24 +51,114 @@ function AIVisualAcuity::monitor(%task, %client)
%viewConeLowerVector = getWords(%viewCone, 12, 14); %viewConeLowerVector = getWords(%viewCone, 12, 14);
// Update all the markers // Update all the markers
%client.clockwiseMarker.setPosition(%viewConeClockwiseVector); %this.clockwiseMarker.setPosition(%viewConeClockwiseVector);
%client.counterClockwiseMarker.setPosition(%viewConeCounterClockwiseVector); %this.counterClockwiseMarker.setPosition(%viewConeCounterClockwiseVector);
%client.upperMarker.setPosition(%viewConeUpperVector); %this.upperMarker.setPosition(%viewConeUpperVector);
%client.lowerMarker.setPosition(%viewConeLowerVector); %this.lowerMarker.setPosition(%viewConeLowerVector);
%client.originMarker.setPosition(%coneOrigin); %this.originMarker.setPosition(%coneOrigin);
} }
else if (isObject(%client.originMarker)) else if (isObject(%this.originMarker))
{ {
%client.originMarker.delete(); %this.originMarker.delete();
%client.clockwiseMarker.delete(); %this.clockwiseMarker.delete();
%client.counterClockwiseMarker.delete(); %this.counterClockwiseMarker.delete();
%client.upperMarker.delete(); %this.upperMarker.delete();
%client.lowerMarker.delete(); %this.lowerMarker.delete();
} }
%result = %client.getObjectsInViewcone($TypeMasks::ProjectileObjectType | $TypeMasks::PlayerObjectType, %client.viewDistance, true); %result = %this.getObjectsInViewcone($TypeMasks::ProjectileObjectType | $TypeMasks::PlayerObjectType, %this.viewDistance, true);
echo(%result.getCount()); // 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(); %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;
}