AI Guard Unit
by Mark Holcomb · 11/27/2004 (5:18 pm) · 335 comments
Download Code File
This is my second attempt at making an AI controlled character. The first was an
AIPlayer that would follow paths. This character is a guard unit. The guard will
wait at it's post (spawn point) until it sees a target. It will then attack that
target while trying to close with it.
If the target is lost the bot will wait at the last place it saw the character and
look around for a little bit, and then it will try to return to it's post.
There is a chance the bot will get stuck trying to return, but there is a simple
routine that has the bot try to move in random directions to try and clear itself
of any obstacles between it and it's post. It's not perfect.
The thinking routine is a simple state machine - which can be expanded on to give the bot more responses and actions.
As with my first ai character, I am using a simple system that allows the designer to drop
markers in the game map that will mark where the bots will start out. When the mission is loaded, the markers are detected and bots are spawned at the marker locations. The markers are then hidden from view. (The markers can be left visible to help in map editing.)
The markers for the guards can be given a dynamic variable called respawn. (Assigned to the marker during map editing.) 'Respawn' will determine whether a bot respawns or not upon death.
The bots have an attention setting. How often they scan is determined by their attention level. The bots get more sluggish (freeing up processor time) when targets are too far away. Conversely, the bot becomes incrementally more attentive as targets come within range, and further aware as targets come into sight.
When a target is found in range and in sight the bot will shoot at the target. The firing sequence is a step of scheduled calls that call for a firing cycle, a trigger down cycle, and a firing delay to control bot rate of fire.
When a bot is attacked it will attempt to sideatep and it's field of vision is temporarily increased to a 360deg field of vision - to emulate looking around to see what happened. The bot's attention level is also set to make it think at it's fastest rate when attacked.
To use the AIGuard...the following changes need to be made.
1. Back up your original game.cs, player.cs, and your current build of Torque. To install AIGuard will require a recompile, since I have created a new class cloned by copying AIPlayer.cc and AIPlayer.h and renaming all references to AIPlayer to AIGuard.
(I did this because I wanted to be able to run both my AIPatroller and AIGuards in the same maps and did not want to have any confusion between them.)
2. Add the files AIGuard.cc and AIGuard.h to your Torque project. (In my instance I saved them to my c:\Torque\engine\game directory and then added them into my project.)
3. Recompile your project and copy your new executable to the appropriate directory for your app.
4. Copy the file AIGuard.cs into your server/scripts directory.
5. Modify game.cs to add the line
to the function onServerCreated().
6. Also in game.cs: The section for function StartGame needs to modified the following ways:
Below the lines that read:
add this:
(If you followed my previous resource you may not have any reference to AImanager. Don't fret... just look for the place in game.cs where you have
and put in
right underneath it.
7. In player.cs in the code for Armor::Damage modify the lines
to read:
*** If you followed my previous resource there should be no need to change this code.
8. Load your map - Stronghold as an example.
9. Go into the map editor. (F11) Then go into the Editor Creator (F4)
10. Under Shapes there should be a drop down called AIMarker, under that a new item called AIGuard.
11. Create a new AIGuard marker.
12. Select your marker, position it where you like and hit (F3) to modify the marker.
13. If you want to override the default respawn value - create a dynamic variable called respawn and set it's value to true or false.
14. Update your item by clicking 'APPLY'- very important and easy to miss step.
15. Save your mission and reload it.
A bot called Guard1 should appear at the spot of your marker.
If you come within range of the guard he should shoot at you and try to hunt you down.
If you get away, or when you die, he should return to his post.
I hope the resource helps other people get up and running with some AI code in their game.
And again, I'd like to thank the other members of this website whose code has been used in several places in the scripting to make this all work.
Mark H.
P.S. I've also included my AIPatrol class files with this - to install it follow the same instructions as for AIGuard, just substitute AIPatrol where AIGuard appears in the instructions. They can both be run at the same times with no problems.
P.S.S. 11/28/04 - I modified the AIPatrol.cs file to correct for a couple of typos.
P.S.S.S 12/3/04 - Added ammo and health seeking capabilities and fixed some errors. (Read posts below - or file in .zip for full details.)
This is my second attempt at making an AI controlled character. The first was an
AIPlayer that would follow paths. This character is a guard unit. The guard will
wait at it's post (spawn point) until it sees a target. It will then attack that
target while trying to close with it.
If the target is lost the bot will wait at the last place it saw the character and
look around for a little bit, and then it will try to return to it's post.
There is a chance the bot will get stuck trying to return, but there is a simple
routine that has the bot try to move in random directions to try and clear itself
of any obstacles between it and it's post. It's not perfect.
The thinking routine is a simple state machine - which can be expanded on to give the bot more responses and actions.
As with my first ai character, I am using a simple system that allows the designer to drop
markers in the game map that will mark where the bots will start out. When the mission is loaded, the markers are detected and bots are spawned at the marker locations. The markers are then hidden from view. (The markers can be left visible to help in map editing.)
The markers for the guards can be given a dynamic variable called respawn. (Assigned to the marker during map editing.) 'Respawn' will determine whether a bot respawns or not upon death.
The bots have an attention setting. How often they scan is determined by their attention level. The bots get more sluggish (freeing up processor time) when targets are too far away. Conversely, the bot becomes incrementally more attentive as targets come within range, and further aware as targets come into sight.
When a target is found in range and in sight the bot will shoot at the target. The firing sequence is a step of scheduled calls that call for a firing cycle, a trigger down cycle, and a firing delay to control bot rate of fire.
When a bot is attacked it will attempt to sideatep and it's field of vision is temporarily increased to a 360deg field of vision - to emulate looking around to see what happened. The bot's attention level is also set to make it think at it's fastest rate when attacked.
To use the AIGuard...the following changes need to be made.
1. Back up your original game.cs, player.cs, and your current build of Torque. To install AIGuard will require a recompile, since I have created a new class cloned by copying AIPlayer.cc and AIPlayer.h and renaming all references to AIPlayer to AIGuard.
(I did this because I wanted to be able to run both my AIPatroller and AIGuards in the same maps and did not want to have any confusion between them.)
2. Add the files AIGuard.cc and AIGuard.h to your Torque project. (In my instance I saved them to my c:\Torque\engine\game directory and then added them into my project.)
3. Recompile your project and copy your new executable to the appropriate directory for your app.
4. Copy the file AIGuard.cs into your server/scripts directory.
5. Modify game.cs to add the line
exec("./aiGuard.cs"); to the function onServerCreated().
6. Also in game.cs: The section for function StartGame needs to modified the following ways:
Below the lines that read:
// Start the AIManager
new ScriptObject(AIManager) {};
MissionCleanup.add(AIManager);
AIManager.think();add this:
AIGuard::LoadEntities();
(If you followed my previous resource you may not have any reference to AImanager. Don't fret... just look for the place in game.cs where you have
AIPlayer::LoadEntities
and put in
AIGuard::LoadEntities();
right underneath it.
7. In player.cs in the code for Armor::Damage modify the lines
// Deal with client callbacks here because we don't have this
// information in the onDamage or onDisable methods
%client = %obj.client;
%sourceClient = %sourceObject ? %sourceObject.client : 0;
if (%obj.getState() $= "Dead")
%client.onDeath(%sourceObject, %sourceClient, %damageType, %location);to read:
// Deal with client callbacks here because we don't have this
// information in the onDamage or onDisable methods
%client = %obj.client;
%sourceClient = %sourceObject ? %sourceObject.client : 0; if (%obj.isbot == true)
{
%obj.attentionlevel=1;
%obj.enhancefov(%obj);
}
if (%obj.getState() $= "Dead")
{
if (%obj.isbot == true)
{
if (%obj.respawn == true)
{
%obj.delaybeforerespawn(%obj.botname, %obj.markerpos, %obj.marker);
%this.player=0;
}
}
else
{
%client.onDeath(%sourceObject, %sourceClient, %damageType, %location);
}
}*** If you followed my previous resource there should be no need to change this code.
8. Load your map - Stronghold as an example.
9. Go into the map editor. (F11) Then go into the Editor Creator (F4)
10. Under Shapes there should be a drop down called AIMarker, under that a new item called AIGuard.
11. Create a new AIGuard marker.
12. Select your marker, position it where you like and hit (F3) to modify the marker.
13. If you want to override the default respawn value - create a dynamic variable called respawn and set it's value to true or false.
14. Update your item by clicking 'APPLY'- very important and easy to miss step.
15. Save your mission and reload it.
A bot called Guard1 should appear at the spot of your marker.
If you come within range of the guard he should shoot at you and try to hunt you down.
If you get away, or when you die, he should return to his post.
I hope the resource helps other people get up and running with some AI code in their game.
And again, I'd like to thank the other members of this website whose code has been used in several places in the scripting to make this all work.
Mark H.
P.S. I've also included my AIPatrol class files with this - to install it follow the same instructions as for AIGuard, just substitute AIPatrol where AIGuard appears in the instructions. They can both be run at the same times with no problems.
P.S.S. 11/28/04 - I modified the AIPatrol.cs file to correct for a couple of typos.
P.S.S.S 12/3/04 - Added ammo and health seeking capabilities and fixed some errors. (Read posts below - or file in .zip for full details.)
#222
The bots initial think state is set to wait 5 seconds when he spawns and then he should sense you after that.
Did you wait the 5 seconds?
02/26/2007 (10:00 am)
Louis, The bots initial think state is set to wait 5 seconds when he spawns and then he should sense you after that.
Did you wait the 5 seconds?
Here is the variable that holds the value for it found at the top of aiguard.cs $AI_GUARD_CREATION_DELAY =5000; //How long a bot waits after creation before his think cycles are controlled by //his attention rate. (Used to help free up think cycles on bots while mission //finishes loading.
#223
I am able to jump around, move, or stand still right in front of them with no action. It is only when I fire either at them or near them, that they respond.
02/26/2007 (6:20 pm)
When I enter the game I fall from the sky. By the time I hit the ground and walk over to the closest bot it takes about a total of 10-15 seconds, so yes.I am able to jump around, move, or stand still right in front of them with no action. It is only when I fire either at them or near them, that they respond.
#224
If everything works using the default model (ork) then it might be they way your custom model is setup.
Alaric was or still is having a similar issue related to LOS (Line of sight). Hope this helps.
02/26/2007 (8:16 pm)
Louis,If everything works using the default model (ork) then it might be they way your custom model is setup.
Alaric was or still is having a similar issue related to LOS (Line of sight). Hope this helps.
Quote:
Alaric Karczag (Oct 11, 2006 at 05:03)
Note- I had the same issue with the bots not seeing my player (custom) and found out that if i moved the players center point to chest level, the bots find me alot easier. This has to do with the LOS being drawn to the bounding boxes centerpoint by default if the proper object/node/LOS is not present.
Origionally my objects point was between his legs, as that was easies, but then i moved it to mid chest.
I still have issues with the bots losing track of me. If i shoot the ground beside the bot, if the splash damage hits the bot, he looses me, even if im in front of him.
If i shoot past him he re-aquires me and attacks, or if he returns to his start box he will then find me too.
#225
Here is another interesting note to this:
I have a couple of maps, one with terrain and one without terrain just dts shapes to walk on.
When I am in the map with the terrain is when I have the problem. However when I am in the other map with the dts shapes, all works fine. I come in they shoot at me and run after me.
Seems more weird but its what is happenning lol
02/27/2007 (6:16 pm)
OK, that could be the problem. In fact I am using the ork right now for the player model but have my own custome model for the AI.Here is another interesting note to this:
I have a couple of maps, one with terrain and one without terrain just dts shapes to walk on.
When I am in the map with the terrain is when I have the problem. However when I am in the other map with the dts shapes, all works fine. I come in they shoot at me and run after me.
Seems more weird but its what is happenning lol
#226
03/01/2007 (11:37 am)
Did you make any modifications to the terrain code in the engine or is this a stock build?
#227
03/04/2007 (8:37 pm)
Which part of the code makes it spawn a bot for every marker that is in place?
#228
The code is (Please note it's a little modded code // is Mark comment to code /// is mine comment to code, I just added a simset and commented out the check on $AI_GUARD_ENABLED):
//The LoadEntities function replaces the markers placed in the map with the AI bots during the
//mission loading.
function AIGuard::LoadEntities()
{
/// GB mod simset creation
new simset(GoodAIgroup);
//Check to see if the AIGuards are to be loaded.
///if ($AI_GUARD_ENABLED == true)
///{
echo("Loading Guard entities...");
//This performs a search for all items within the radius from the starting point.
//All of the items that match "AIGuardMarker" trigger a bot to be placed at the
//position of the marker found.
%position = "0 0 0";
%radius = 100000.0;
InitContainerRadiusSearch(%position, %radius, $TypeMasks::StaticObjectType);
%i=0;
while ((%targetObject = containerSearchNext()) != 0)
{
if(%targetobject.getclassname() $= "StaticShape")
{
if (%targetobject.getDataBlock().getName() $= "AIGuardMarker")
{
%i++;
%player = AIGuard::spawnAtMarker("Guard" @ %i, %targetobject);
}
}
}
///}
///else
///{
/// echo("Guard entities disabled...");
///}
03/05/2007 (2:02 am)
@ChristianThe code is (Please note it's a little modded code // is Mark comment to code /// is mine comment to code, I just added a simset and commented out the check on $AI_GUARD_ENABLED):
//The LoadEntities function replaces the markers placed in the map with the AI bots during the
//mission loading.
function AIGuard::LoadEntities()
{
/// GB mod simset creation
new simset(GoodAIgroup);
//Check to see if the AIGuards are to be loaded.
///if ($AI_GUARD_ENABLED == true)
///{
echo("Loading Guard entities...");
//This performs a search for all items within the radius from the starting point.
//All of the items that match "AIGuardMarker" trigger a bot to be placed at the
//position of the marker found.
%position = "0 0 0";
%radius = 100000.0;
InitContainerRadiusSearch(%position, %radius, $TypeMasks::StaticObjectType);
%i=0;
while ((%targetObject = containerSearchNext()) != 0)
{
if(%targetobject.getclassname() $= "StaticShape")
{
if (%targetobject.getDataBlock().getName() $= "AIGuardMarker")
{
%i++;
%player = AIGuard::spawnAtMarker("Guard" @ %i, %targetobject);
}
}
}
///}
///else
///{
/// echo("Guard entities disabled...");
///}
#229
03/05/2007 (2:40 am)
Thank you Gianfranco.
#230
You can also change their names by modifying like so...
if (%targetobject.getDataBlock().getName() $= "AIGuardMarker")
{
%i++;
%player = AIGuard::spawnAtMarker("Big Ugly Ork Guard" @ %i, %targetobject);
}
@Gianfranco
Thanks for the simset mod, didn't know you could do it like that. :)
03/06/2007 (9:09 am)
@ChristianYou can also change their names by modifying like so...
if (%targetobject.getDataBlock().getName() $= "AIGuardMarker")
{
%i++;
%player = AIGuard::spawnAtMarker("Big Ugly Ork Guard" @ %i, %targetobject);
}
@Gianfranco
Thanks for the simset mod, didn't know you could do it like that. :)
#231
I have to jump or walk up a hill before he will attack.
And also there is no damage applied. Even the original kork from fps.starter doesnt take damage. Please help.
wanted you all too know that this resource works with TGEA, except for these issues, probably an oversite on my part.
Thanks to all.
03/24/2007 (10:28 pm)
I just noticed that the guard only attacks when i excist on a higher plain than him...in other words, when i am higher than him. strange.I have to jump or walk up a hill before he will attack.
And also there is no damage applied. Even the original kork from fps.starter doesnt take damage. Please help.
wanted you all too know that this resource works with TGEA, except for these issues, probably an oversite on my part.
Thanks to all.
#232
Project.Weapon/server/scripts/aiguard.cs (292): Unable to find object: '' attempting to call function 'clearAim'
I am getting this error. And also how do i stop the AiGuard from jumping in the vehicles and driving them in circles. i have not made any changes other the the .dts and equipment (a standard M16), it fires and tracks me, but its filling my console with these errors.
03/26/2007 (7:33 am)
I love this resource though i am having a few issues.Project.Weapon/server/scripts/aiguard.cs (292): Unable to find object: '' attempting to call function 'clearAim'
I am getting this error. And also how do i stop the AiGuard from jumping in the vehicles and driving them in circles. i have not made any changes other the the .dts and equipment (a standard M16), it fires and tracks me, but its filling my console with these errors.
#234
but i've a little problem, and i cant find the reason why this happen. Maybe somebody can confirm.
If i change the $AI_GUARD_RESPAWN_DELAY > 22 the bot will not respawn.
With 20 it works fine.
Edit:
i added following code :
The "blatrigger" ends after 21 secounds .... does the object then dissapear ?
Edit 2:
lol i found it this make the bot-object disapear:
Edit3:
My solution:
I did add:
and modify:
the aiguard::respawn is not longer used then.
Btw. if you have the same problem and use this code $AI_GUARD_RESPAWN_DELAY are secounds not ms like in the original code.
04/19/2007 (9:36 am)
Hi, first of all this bot code rocks :Dbut i've a little problem, and i cant find the reason why this happen. Maybe somebody can confirm.
If i change the $AI_GUARD_RESPAWN_DELAY > 22 the bot will not respawn.
With 20 it works fine.
Edit:
i added following code :
//------------------------------------------------------------------------------
//The delay before respawn function is set to wait a specified duration before
//respawning an AIPlayer
function AIGuard::DelayBeforeRespawn(%this, %name, %marker)
{
echo("XXTH AIGuard::DelayBeforeRespawn... sec:" @ $AI_GUARD_RESPAWN_DELAY @ "NAME = " @ %name @ " marker = " @ %marker);
%this.respawntrigger = %this.schedule($AI_GUARD_RESPAWN_DELAY * 1000,"respawn", %name, %marker);
%this.bla=0;
%this.blatrigger = %this.schedule(1000,"bla");
%this.dump();
}
//------------------------------------------------------------------------------
function AIGuard::bla(%this) {
%this.bla++;
echo ("bla " @ %this.bla);
%this.blatrigger = %this.schedule(1000,"bla");
}The "blatrigger" ends after 21 secounds .... does the object then dissapear ?
Edit 2:
lol i found it this make the bot-object disapear:
$CorpseTimeoutValue = 22 * 1000;
function Armor::onDisabled(%this,%obj,%state)
{
// The player object sets the "disabled" state when damage exceeds
// it's maxDamage value. This is method is invoked by ShapeBase
// state mangement code.
// If we want to deal with the damage information that actually
// caused this death, then we would have to move this code into
// the script "damage" method.
%obj.playDeathCry();
%obj.playDeathAnimation();
%obj.setDamageFlash(0.75);
// Release the main weapon trigger
%obj.setImageTrigger(0,false);
// Schedule corpse removal. Just keeping the place clean.
%obj.schedule($CorpseTimeoutValue - 1000, "startFade", 1000, 0, true);
%obj.schedule($CorpseTimeoutValue, "delete");
}Edit3:
My solution:
I did add:
// XXTH not fine but it works - since i dont know how to change the namespace i add a loooong method name
function StaticShape::respawnteamguardbot(%this,%name) {
AIGuard::spawn(%name,%this);
}and modify:
function AIGuard::DelayBeforeRespawn(%this, %name, %marker)
{
%marker.respawntrigger=%marker.schedule($AI_GUARD_RESPAWN_DELAY * 1000,"respawnteamguardbot", %name);
}the aiguard::respawn is not longer used then.
Btw. if you have the same problem and use this code $AI_GUARD_RESPAWN_DELAY are secounds not ms like in the original code.
#235
I think my problem lies in this step of the resource:
1. Back up your original game.cs, player.cs, and your current build of Torque. To install AIGuard
will require a recompile, since I have created a new class cloned by copying AIPlayer.cc and
AIPlayer.h and renaming all references to AIPlayer to AIGuard.
I did this because I wanted to be able to run both my AIPatroller and AIGuards in the same maps and
did not want to have any confusion between them.
Sam
04/21/2007 (5:32 pm)
I am a new Torque user and am just learning scripting. I would like to get this working in Torque 1.5. I would like to know how to do a recompile. I have done all the other steps, read all the other forum threads, but am still stuck. I have done all this on a windows machine (XP), an Imac (OS X) and an INtel Mac (OS X) and just cannot spawn any bots. I have enabled the guard and made sure that aiguard.cs was below player.cs.I think my problem lies in this step of the resource:
1. Back up your original game.cs, player.cs, and your current build of Torque. To install AIGuard
will require a recompile, since I have created a new class cloned by copying AIPlayer.cc and
AIPlayer.h and renaming all references to AIPlayer to AIGuard.
I did this because I wanted to be able to run both my AIPatroller and AIGuards in the same maps and
did not want to have any confusion between them.
Sam
#236
it's a long one...good luck
http://tdn.garagegames.com/wiki/Torque/vs2k5
i'm pretty sure its all free too
04/21/2007 (8:41 pm)
@ stephenit's a long one...good luck
http://tdn.garagegames.com/wiki/Torque/vs2k5
i'm pretty sure its all free too
#238
I implemented the script code to make the AI run up to me but then stop at a certain distance. They do run after me and stop, however when they stop, they also stop shooting. In the check for Attacking, the openfire function is being called so i'm not sure what could be causing this.
Any thoughts?
EDIT:
I added
//Tells the bot to start shooting the target.
%obj.openfire(%obj, %tgt);
To the case "Holding" statement in the Think function. This was the only way I was able to get the AI to run after me, stop at a certain distance but continue to shoot.
So if anyone is having this problem just add this to the case "Holding" check after you setAim.
04/26/2007 (8:11 pm)
OK I haven't posted in this resource for a little while. I was able to get the AI to come after me finally.I implemented the script code to make the AI run up to me but then stop at a certain distance. They do run after me and stop, however when they stop, they also stop shooting. In the check for Attacking, the openfire function is being called so i'm not sure what could be causing this.
Any thoughts?
EDIT:
I added
//Tells the bot to start shooting the target.
%obj.openfire(%obj, %tgt);
To the case "Holding" statement in the Think function. This was the only way I was able to get the AI to run after me, stop at a certain distance but continue to shoot.
So if anyone is having this problem just add this to the case "Holding" check after you setAim.
#239
$AI_GUARD_ENABLED = true;
was set to false... no wonder I wasn't getting any bots!
Excellent resource!
05/22/2007 (3:21 pm)
D'oh.. took me a while to figure out:$AI_GUARD_ENABLED = true;
was set to false... no wonder I wasn't getting any bots!
Excellent resource!
#240
05/29/2007 (7:34 pm)
Holy Jahosafat! This is a ton of great code to learn from and use as is. I'm such a newb I could be a turkey and I got it working first try! Thanks so much for this resource, You RULE! 
Torque Owner Louis Dufresne
I am still having trouble with the AI not shooting me until I shoot them.
They will just stand there even if I am right in front of them.
Once I shoot them they do attack and will continue to attack.
I have seen that a few other people on here have this same trouble.
Has anyone figured out a fix?
Thanks.