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.)
#81
04/20/2005 (8:17 am)
I am using the torque build environment but tried using c++ 6.0 and 2005 none worked

Edit: I tried the echo and it echoed like it was supposed to but I cannot find any problems with the scripts.

Thought: does this resource work with the current build of torque or an older version? I have noticed code differences.
#82
04/20/2005 (8:26 am)
Current...

Non conobject AIGuard?
#83
04/20/2005 (9:42 am)
Okay I tried changing the AIguard marker to the AiGuard player but nothing so here is what I have done:
1. Followed the instructions at the top
2. Went into torque and added an AIGuard/Patrol player shape
3. Gave the shape the AIguard/patrol player datablock
4. clicked on apply
5. saved the mission and restarted it
6. Went to the location of the marker and nothing.

oh and whats Non conobject AIGuard?
#84
04/20/2005 (10:43 am)
Gave the marker the aiguard player datablock? What did you do that for?

Just go into the mission editor, hit F4, place a marker... move it up so its not half in the terrain. Save, ext, reload hte mission.... if you're not calling loadEntities somehwere in script the call it from the console...

Are you adding a AIGuard/player.dts static shape or are you adding a shape/AIMarker/AIMarker shape?

The static shape wont do shit. The Marker will spawn an AIGuard when you run loadentities

Are there no erros in the console? Non con object AIGuard is an error that you could have been gettng in the console.
#85
04/20/2005 (11:11 am)
shape/AIMarker/AIMarker shape.
Cant find a non con object error
i added a new marker saved, reloaded and still nothing
loadentity is an invalid synatx
#86
04/20/2005 (11:16 am)
Think I have found the problem in the console but I cant find a solution.
The console says, after calling many funtions, 'Unable to find object O'

EDIT: I found the noncon error it was in the middle of a load of lines what should I do?
#87
04/20/2005 (11:33 am)
Did you add AIGuard.cc and AIGuard.h to the source, and get them compiled? Remember that you have to add /game/AIGuard.cc \ or something like that to the mk file...
#88
04/20/2005 (11:35 am)
which mk file?

EDIT: Just found the mk file and added both aipatrol and aiguard to it, compiling now.
#89
04/20/2005 (11:47 am)
make -k all
make[1]: *** No rule to make target `out.GCC3.RELEASE/game/AIGuard.obj', needed by `out.GCC3.RELEASE/torqueDemo.exe'.
make[1]: *** No rule to make target `out.GCC3.RELEASE/game/AIPatrol.obj', needed by `out.GCC3.RELEASE/torqueDemo.exe'.
make[1]: Target `torqueDemo' not remade because of errors.
make: *** [default] Error 2
make[2]: *** No rule to make target `out.GCC3.RELEASE/game/AIGuard.obj', needed by `out.GCC3.RELEASE/engine.a'.
make[2]: *** No rule to make target `out.GCC3.RELEASE/game/AIPatrol.obj', needed by `out.GCC3.RELEASE/engine.a'.
make[2]: Target `out.GCC3.RELEASE/engine.a' not remade because of errors.
make[1]: *** [engine.a] Error 2
make[1]: Target `all' not remade because of errors.
make: *** [tools] Error 2
make: Target `all' not remade because of errors.


????????????????????????????????????????????????????????????????????
#90
04/20/2005 (11:49 am)
Did you spell AIguard right? It has to spelled the same as the .cc file is. Also, make sure the line in the mk file is formatted the same as the rest and is in the game section with the others... Put it right under aiPlayer.cc
#91
04/20/2005 (11:58 am)
I spelt it right but with the wrong case AI instead of ai, I have it under aiplayer and im compiling again now
#92
04/20/2005 (11:59 am)
Does your terrain code compileproperly now? Cause we have been waiting for your response in the What Happened? thread...
#93
04/20/2005 (12:03 pm)
oh my god I just loaded the game and in 2 seconds I had 12 AIguards killing me.

Its working now, by the way. Thanks for all the help.
#94
04/20/2005 (12:04 pm)
The terrain code still shows errors but its causing no problems so I decided to leave it. I will post in the what happened thread sorry about that.
#95
04/20/2005 (12:47 pm)
How would I modify this script so when the bots are under fire they run or try to find shelter (in a building etc.)?
#96
04/20/2005 (1:00 pm)
It already has soemthing simailr aclled "Defending" .. alter that code... is the terrain producing errors or warnings? Errors wont allow it to compile. Warnings it acn still compile, but craps juno into the console window (Eclipse console, not Torque console)
#97
04/20/2005 (1:20 pm)
All of the errors are now warnings
#98
04/21/2005 (9:49 am)
return obj? obj->getId(): -1;

this line is at the end of aipatrol/aiguard.cc
When it is compiled it causes warnings, is it needed and if it is why is it causing warnings?
Eclipse says "argument of negative value '-1' to unsigned 'int
#99
04/21/2005 (10:08 am)
yes it is needed... There are tonnes of warnings in the Torque Source. If you want to get rid of them you will have to do your homework and know what is going on in the engine... if you have to ask if you can get rid of it, then you dont have the knowledge to get rid of it.
#100
04/21/2005 (1:45 pm)
My two cents.

@James One of the unfortunate aspects of C/C++ is related to its flexibility and balancing that with rigid adherence to eliminating all the warnings that will be produced in a project has dimishing rewards.

All it's saying is that as far as it knows, at compile time, the result of that expression could be -1 if it doesn't even have the object, much less able to get the ID. So a -1 doesn't match the unsigned int return type of the function.

You could change this to

return obj? obj->getId(): (unsigned int)0xffffffff;

or something like that (I didn't test it) if it makes you feel better, but the results are all still the same.

You learn to just live with these, especially this one, but admittedly, they clutter up the compiler output sometimes to the point you can't see the important warnings.