Game Development Community

Making bots call for help

by Jamal Moon · in Technical Issues · 01/31/2008 (5:03 pm) · 13 replies

How do you make it so that when the bot is under attack, it will call for help? For example...I shoot a bot1 and if bot2 is nearby(or within a certain radius from bot1), it will move to bot1's location and attack the enemy.

#1
01/31/2008 (8:38 pm)
You sort of answered your own question there. The steps you would need the bots to take (in script or code) would be:

1) bot1 recognizes it is under attack (via damage, etc)
2) bot1 searches certain radius for bot2 (you could actually do a distance check instead of a radius or container search).
3) if bot2 is found, it changes bot2's target to the player, then sets it's state to attack
4) bot2 gets location of bot1
5) bot2 moves to bot1's location
6) bot2 attacks player
#2
01/31/2008 (9:11 pm)
This is a loaded question and while the above answer by Ted -could- work it has fundamental flaws, such as what if bot2 is already engaged? You do not want bot2 to just suddenly whip around and assist its team mate - ignoring its opponent in front of it.

My suggestion is to check out Programming Game AI by Example by Mat Buckland. Read the whole thing and you will have a solid grip on how to do practically any AI you need.
#3
01/31/2008 (9:22 pm)
Thanks for the response guys

@Ted
The main problem I have is to check if bot2 is within the radius. I'm still learning programming and I don't know what function to use in order to check if the bot is in range. But you mentioned something about a container search...

@Ben
You do make a good point that if bot2 is already facing an enemy, you wouldn't want him to assist an ally. The way to overcome that is to check bot2's state; if the state is either "attack", or "defense" he will ignore helping bot1 until his own threat is gone. If Bot2's state is "guarding", then he will assist the ally.
#4
01/31/2008 (9:58 pm)
Jamal, Programming Game AI by Example actually go through and creates a fairly complex AI system by the end of the book that would handle many many of the complicated issues with AI, such as weapon selection, path finding, target selection, memory, evaluating which targets should be elimated first - so and so forth. Its always best to have a strong background in something first before trying to find a different way to do it.

Also the radius / distance check largely depends on the engine you are using. TGE, TGEA, TorqueX, or some other engine?
#5
01/31/2008 (10:18 pm)
@Ben
I understand that Programming Game AI by Example is a great book for this situation, but I already asked my parents for enough stuff (books for example). They kinda get a little...upset if I ask for a lot. I would have to work for my dad in order to get the money...and I worked for my dad before and it's not worth it. Although when I somehow get the money, I'll keep that book in mind. By the way, I am using TGE 1.4.2.
#6
02/01/2008 (6:48 am)
@Ben: My example also doesn't take pathfinding or special actions (loading ammo, climbing, opening doors, etc) into consideration, but as a starting point for Jamal, I think it's the best steps to start off with.

@Jamal: While the steps do not account for many things, what you can do is search on the types of things you'll need to do in order to accomplish each step. As you learn those things, you'll be able to apply them to other areas. Books are nice, but this in itself doesn't require a book to learn. Check out the TGE docs and search on the forums here for getting the distance between two objects- do a few .dump()'s in the console to see what you can do with them in script, and you'll be okay.
#7
02/01/2008 (4:27 pm)
@ Ted
Quote: Check out the TGE docs
I wasn't able to find anything on the forums or docs... So instead, I used TDN :-) ,I checked the section under "raycasts" and I think I found the answer.
Quote: As you learn those things, you'll be able to apply them to other areas.
That's a great idea and I probably will use it for bot targeting so it would have a more accurate aim...
#8
02/03/2008 (1:40 am)
Still can't get it to work. Here's my code...

function AIPlayer::CallForHelp(%this, %obj)
{
   %bPos = %obj.getPosition();                     // This is the bot's position.
   %position = %bPos;                             
   %radius = $AI_PLAYER_HELP_RADIUS;               // Detect distance is set to 175.
   %targetObject = InitContainerRadiusSearch(%position, %radius, $TypeMasks::PlayerObjectType);
   %targetObject = containerSearchNext();
   error("Found Something... Name:" SPC %targetObject);
   
  	   if(%targetObject.getDataBlock() $= "DemoPlayer")   
      {
  	      error("Help is on the way from" SPC %targetObject.getTransform());
  	      %targetObject.enhanceFov(%obj);                 
  	      %targetObject.setMoveDestination(%bPos);        // Make the bot move to where the attack began.
      } 
  	   else
  	   {
  	      error("No allies nearby for assistance");       //Must be no one around to help...
  	   }
}

I placed 2 AIPlayers (bot1 and bot2) next to each other and I shot bot1. Bot1 returned fire and killed me (only because I was checking the console), but bot2 didn't do anything. In the console I get

Found Something...Name: 1598
No allies nearby for assistance
starter.fps/server/scripts/AIPlayer.cs (737): Call to initContainerRadiusSearch in CallForHelp uses result of void function call

1598 was the ID number of bot2. Does anyone know what "Call to initContainerRadiusSearch in CallForHelp uses result of void function call" means?
#9
02/03/2008 (9:14 am)
InitContainerRadiusSearch() doesn't return anything. Make it independent from %targetObject like so:

function AIPlayer::CallForHelp(%this, %obj)
{
   %bPos = %obj.getPosition();                     // This is the bot's position.
   %position = %bPos;                             
   %radius = $AI_PLAYER_HELP_RADIUS;               // Detect distance is set to 175.

   InitContainerRadiusSearch(%position, %radius, $TypeMasks::PlayerObjectType);

   %targetObject = containerSearchNext();
   error("Found Something... Name:" SPC %targetObject);
   
  	   if(%targetObject.getDataBlock() $= "DemoPlayer")   
      {
  	      error("Help is on the way from" SPC %targetObject.getTransform());
  	      %targetObject.enhanceFov(%obj);                 
  	      %targetObject.setMoveDestination(%bPos);        // Make the bot move to where the attack began.
      } 
  	   else
  	   {
  	      error("No allies nearby for assistance");       //Must be no one around to help...
  	   }
}
#10
02/03/2008 (9:20 am)
Actually, here's a thought. Maybe the bot that ends up being called is the bot you're attacking. Nothing is exempt in a radius search.

I'd add an object test like so:

while((%targetObject = containerSearchNext()) != 0 && %targetObject != %obj)
{
if(%targetObject.getDataBlock() $= "DemoPlayer")   
      {
  	      error("Help is on the way from" SPC %targetObject.getTransform());
  	      %targetObject.enhanceFov(%obj);                 
  	      %targetObject.setMoveDestination(%bPos);        // Make the bot move to where the attack began.
      } 
  	   else
  	   {
  	      error("No allies nearby for assistance");       //Must be no one around to help...
  	   }
}
#11
02/03/2008 (2:20 pm)
@Matt
Thanks for responding but still no luck :-(. I know that the bot1 is not being called by itself because in the console I got

Found Something...Name: 1598


1598 was the ID number of bot2, and bot1's ID was 1599.
#12
02/04/2008 (6:30 am)
Hmm, as a test, try cut and pasting this in your code:
function AIPlayer::findHelp(%this)
{
   %pos = %this.getPosition();
   %radius = 20; //or whatever you want

    InitContainerRadiusSearch(%pos, %radius, $TypeMasks::PlayerObjectType);
    %obj = containerSearchNext();

   echo("bot: " @ %obj.getID() @ " is in range!");
   return %obj.getID();
}
Either call this yourself when the bots are next to each other, or call it in their onDamage function. It should work, and help you find where the problem is.
#13
05/30/2008 (6:06 pm)
I finally got it to work! I couldn't get rays to work, so I did what Ted said which is to do a distance check.
Here's the code/instructions if anyone is interested.

1) Add the bots in a group called AIPlayerGroup.

2) Put the code in your AI script (or wherever you want it).

function AIPlayer::CallForHelp(%obj, %maxDist)
{ 
   // Step 1: Find the bot's position.
   // Step 2: Find out how many bots are in the group.
   // Step 3: Find the ally's position.
   // Step 4: Find the distance between the bots.
   // Step 5: If the ally IS in range, increase its FOV.
   
   %pos = %obj.getTransform();               // Step 1
   
   %groupNum = AIPlayerGroup.getCount();     // Step 2
   
   error(%obj SPC "is calling for help!");
   
   for(%x = 0; %x < %groupNum; %x++)         
   {
      %bot = AIPlayerGroup.getObject(%x);
      %botPos = %obj.getTransform();         // Step 3
      %dist = vectorDist(%pos, %botPos());   // Step 4
      
      if(%dist <= %maxDist)
      {
         echo(%bot SPC "is in range!" NL "Dist:" SPC %dist);
         %bot.enhanceFov(%bot);              // Step 5
      }
      else
      {
         echo("An ally is not in range");
         echo("Range:" SPC %dist);
      }
   }
}

3) In the bot's OnDamage function, type
%obj.callForHelp(%obj, 25); // You can change the distance (which is currently 25) to whatever 
                                                 // you want it to be.


PS: Part of the code uses a function (which is Step 5) from this resource www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=6742