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.
About the author
#2
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.
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
@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.
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
Also the radius / distance check largely depends on the engine you are using. TGE, TGEA, TorqueX, or some other engine?
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
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.
01/31/2008 (10:18 pm)
@BenI 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
@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.
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)
@ TedQuote: Check out the TGE docsI 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
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
1598 was the ID number of bot2. Does anyone know what "Call to initContainerRadiusSearch in CallForHelp uses result of void function call" means?
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
I'd add an object test like so:
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
Thanks for responding but still no luck :-(. I know that the bot1 is not being called by itself because in the console I got
1598 was the ID number of bot2, and bot1's ID was 1599.
02/03/2008 (2:20 pm)
@MattThanks 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
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).
3) In the bot's OnDamage function, type
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
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
Torque 3D Owner Ted Southard
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