Game Development Community

dev|Pro Game Development Curriculum

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

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.)
#141
12/12/2005 (9:52 am)
Can anyone help??

I've managed to script this Resource into working. I place my markers in the Mission file and get my AIPlayer spawning with the 'default' weapon dataBlock as string in the Global Variable at the beginning of the file. I then managed to get a dynamic variable of Name associated with each marker and I get a consistent lineup of bots, each 'acting' as a MP player, ie the name stays the same with each spawn, fine, it's what I intended.

This was great, I next expanded the dynamic variable concept to a Skin & Name combination and I can specifiy each texture on the spawned bot!! I was rolling...


Here's where I started to bog: I now want to dynamically specify the weapon the bot is using, alas; I can only get syntax errors or a not finding such a function, looking for ''.....

Will it be possible to do this easily, I feel I'm right on the edge of discovering how...It was extremely satifiying getting the setSkinName going by Trial/Error...getting the weapon dynamic is proving much more difficult.

Thanks
#142
12/20/2005 (8:18 am)
hi i have a similar question to rex, i have a few characters set up all based off of the player.cs and each is refered to as orcbody, playerbody, ghostbody etc. is there a way to dynamically choose which of these "bodies" is set for the bots. thanks
Im also interested in knowing how to dynamically set the weapon
#143
12/21/2005 (6:17 am)
Rex,

I did that a while ago, it's kinda simple you just mount them like you would mount a player weapon.

I'll see if I can find the code
#144
12/21/2005 (7:01 am)
@ Vince: Thanks, I got that part[mounting weapons]; it's the dynamic assignment from the marker object via script/function that I can't get right. I got each bot to have a semi-permanent 'name'-which btw doesn't get linked to the ID # when it's added to the game,(:|), and I can't call the aiplayer by name in the console to do something, I have to use it's ID number in Mission Tree when it spawns/respawns...and I got each marker to give it's spawned player a specific .skin. It's in assigning more dyamic variables via the marker that's got me a little stumped. Thanks again for any tips.

...this to me is the 'basic' AI I'm looking for: the ability to have a spawn/marker, and being able to choose between 3 basic types of players[stationary,pathed,seeking], and putting a custom skin to them, and finally equiping them with inventory...this to me would be a much needed pack.
#145
01/06/2006 (1:45 pm)
Will this work with TGE 1.4?
#146
01/07/2006 (2:40 am)
Yes, works fine in tge 1.4
#147
01/07/2006 (8:26 am)
Ok thanks.
#148
01/13/2006 (9:47 pm)
i have been having a problem with this resource. every now and then when i kill one of these guards i get the follow errors
Fatal: (../engine/game/player.cc @ 1891) Abnormality in Player::Death::fallToGround()
Cannot display alerts in full screen mode. Dumping message to console...
Fatal: (../engine/game/player.cc @ 1891), Abnormality in Player::Death::fallToGround()
Error, a DecalManager (6433ed0) isn't properly out of the bins!
Error, a InteriorInstance (a459e50) isn't properly out of the bins!
Error, a InteriorInstance (a459e50) isn't properly out of the bins!
Error, a InteriorInstance (a45a130) isn't properly out of the bins!
Error, a InteriorInstance (a45a130) isn't properly out of the bins!
Error, a InteriorInstance (a4b10f0) isn't properly out of the bins!
Error, a InteriorInstance (a4b10f0) isn't properly out of the bins!
Error, a InteriorInstance (a4b10f0) isn't properly out of the bins!
Error, a InteriorInstance (a4b10f0) isn't properly out of the bins!
Error, a InteriorInstance (a4b13d0) isn't properly out of the bins!
Error, a InteriorInstance (a4b2320) isn't properly out of the bins!
Error, a TSStatic (a4b2600) isn't properly out of the bins!
Error, a TSStatic (a4b2600) isn't properly out of the bins!
Error, a TSStatic (a4b2600) isn't properly out of the bins!
Error, a TSStatic (a4b2600) isn't properly out of the bins!
Error, a WaterBlock (a4aa330) isn't properly out of the bins!
Error, a TerrainBlock (a4abc20) isn't properly out of the bins!
Error, a Sky (a4ae1f0) isn't properly out of the bins!
Error, a AdvancedCamera (a4df580) isn't properly out of the bins!
Error, a Camera (a1c3a80) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a Item (a480410) isn't properly out of the bins!
Error, a Item (a47a790) isn't properly out of the bins!
Error, a AIGuard (a1c4580) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a Player (a4dfdc0) isn't properly out of the bins!
Error, a Item (a47b060) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (a4def20) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a GameBase (c4e37f0) isn't properly out of the bins!
Error, a Projectile (c51cc60) isn't properly out of the bins!
Error, a InteriorInstance (65418f0) isn't properly out of the bins!
Error, a InteriorInstance (a27b430) isn't properly out of the bins!
Error, a InteriorInstance (c4cc270) isn't properly out of the bins!
Error, a InteriorInstance (c4cc9f0) isn't properly out of the bins!
Error, a InteriorInstance (c4cc270) isn't properly out of the bins!
Error, a InteriorInstance (c4cc270) isn't properly out of the bins!
Error, a InteriorInstance (c4cc270) isn't properly out of the bins!
Error, a InteriorInstance (c4cc9f0) isn't properly out of the bins!
Error, a InteriorInstance (a4590f0) isn't properly out of the bins!
Error, a Item (a1cb9d0) isn't properly out of the bins!
Error, a Item (a1caab0) isn't properly out of the bins!
Error, a Item (a8843d0) isn't properly out of the bins!
Error, a InteriorInstance (a4590f0) isn't properly out of the bins!
Error, a Camera (a4ad410) isn't properly out of the bins!
Error, a Camera (a4ad410) isn't properly out of the bins!
Error, a Camera (a4ad410) isn't properly out of the bins!
Error, a Camera (a4ad410) isn't properly out of the bins!
Error, a AIGuard (a872fb0) isn't properly out of the bins!
Error, a AdvancedCamera (a871bd0) isn't properly out of the bins!
Error, a TSStatic (a885b60) isn't properly out of the bins!
Error, a Projectile (c4e3e70) isn't properly out of the bins!
Error, a TerrainBlock (a474fc0) isn't properly out of the bins!
Error, a WaterBlock (a266cd0) isn't properly out of the bins!
Error, a TSStatic (a885b60) isn't properly out of the bins!
Error, a TSStatic (a885b60) isn't properly out of the bins!
Error, a TSStatic (a885b60) isn't properly out of the bins!
Error, a Sky (a4740a0) isn't properly out of the bins!
Error, a Player (c4d3a80) isn't properly out of the bins!
Fatal: (../engine/interior/interiorLMManager.cc @ 165) InteriorLMManager::removeInterior: cannot remove base interior
Cannot display alerts in full screen mode. Dumping message to console...

im pretty sure these are related to this chunk of code but im not sure what to do to fix it.
// Try to get them to conform to stairs by doing several LOS calls.  We do this if
      // normal is within about 5 deg. of vertical.
      if (desNormal.z > 0.995)
      {
         Point3F  corners[3], downpts[3];
         S32      c;
         for (c = 0; c < 3; c++) {    // Build 3 corners to cast down from-
            corners[c].set(loc.x - boxRad, loc.y - boxRad, loc.z + 1.0);
            if (c)      // add (0,boxWidth) and (boxWidth,0)
               corners[c][c - 1] += (boxRad * 2.0);
            downpts[c].set(corners[c].x, corners[c].y, loc.z - sConformCheckDown);
         }
         // Do the three casts-
         for (S32 c = 0; c < 3; c++)
            if (gClientContainer.castRay(corners[c], downpts[c], sPlayerConformMask, &coll))
               downpts[c] = coll.point;
            else
               break;
         // Do the math if everything hit below-
         if (c == 3) {
            mCross(downpts[1] -= downpts[0], downpts[2] -= downpts[1], &desNormal);
            AssertFatal(desNormal.z > 0, "Abnormality in Player::Death::fallToGround()");
            desNormal.normalize();
            conformToStairs = true;
         }
      }
any ideas?? thanks
#149
01/22/2006 (11:02 am)
does anyone know why this is happening??
#150
02/13/2006 (12:11 am)
This resource is awsome for anyone wanting to learn or extend AI. I highly recommend it to anyone looking into starting AI with Torque. Great example, and greatly appreciated!

You can also check out this resource for implementing a navnet for pathfinding. However, it will take some script modifications to get it working properly with AIGuard.

-Jase
#151
02/26/2006 (3:59 pm)
Question: is it possible to use this with the version of Torque included in 3D Game Programming All In One?
#152
03/06/2006 (9:04 am)
This is an amazeing resource to get you started from practically no knowledge of scripting to understanding what's going on in pretty much every line. I am a Tribes 1 junkie, and wanted to share a link to Spoonbot (This is a evil hatefull vile cheating AI program and I love it.) The author of it has them playing several different games, and using vehicles includeing flying ones. It's a great resource for tips on how to get bots to do things not covered in Garage Games, but since it was built for Tribes 1, it is slightly out of date for simply copying parts you need as a patch.

http://www.playspoon.com/awf/index.php?id=36
#153
03/15/2006 (7:14 pm)
I've tried this resource out and everything seems to work fine, until I insert the aiMarker. There's an Orc character standing there but he doesn't do anything. And I can run right through him. What's the problem here?
#154
03/25/2006 (8:23 am)
Greetings all :)

I am not sure if anyone is monitoring this but I have one slight problem, and I am sure its me:)

I have AIguard working fine, and have also duplicated the scripts and the C++ files so I also have AIGuard, AIOrc, AIHuman etc etc so I can spawn different mobs with different weapons and settings, and randomly dropping loot from loot tables however:-

Here's the problem. If I set the respawn time to greater than 20000 then they never respawn.. actually to be more specific, it seems that they will not respawn if the corpse has already decayed. Any period less than this works fine.

Is this something to do with schedule loosing track if the original object has vanished?? I know I have schedules running every 60000 elsewhere so I don't think thats a problem.

If anyone could help I would really appreciate it.

Regards

Graham Evans.
#155
04/02/2006 (7:54 pm)
This is a great resource, easy to follow got it working first time.
Very helpful.

Thanks
#156
04/26/2006 (5:08 am)
I got this resource in and everything just didnt realize it would not work on a vehicle...
#157
05/03/2006 (4:33 pm)
It's possible to add a point in to AIguard?
Example....
When player death point go to -1
When player kill another player point go to +1
It's possible to kill a AIguard point go to +1 and kill by AIguard point go to -1?
THANKS
#158
05/10/2006 (8:59 am)
Great Resource!

I tried using it last year and had a ton of trouble. I think that it had a lot to do with other outside aspects and not the resource itself.

I recently downloaded the engine again and started over fresh. Put this in and it works!


Only slight issues I am having. Right now I have 5 AIGuards near each other. Some of them seem to be in an endless loop and others are 'Guarding'. An interesting thing happens sometimes: sometimes I can actually walk right in front of them and they do nothing. Sometimes they wont move or even come after me until I shoot the Crossbow once. Then they move and run after me.

If there a variable that needs to be changed?
#159
05/10/2006 (9:25 am)
HOW DO I RECOMPILE A PROJECT AND SAVE THE NEW EXECUTABLE??
#160
05/10/2006 (9:25 am)
I have no idea how to do this and I think this is why aiguard is not working. Could someone list the steps on how to do this? Thanks