Game Development Community

Ai Finding Cover

by Bryce · in Technical Issues · 05/27/2007 (5:26 am) · 38 replies

Has anybody figured out how to make AI find cover from an enemy???? I would love to know.


Thanks
Page«First 1 2 Next»
#21
06/15/2007 (12:34 pm)
Here we go. ContainerRayCast returns:

1. Object ID
2. Position of hit
3. Position of the normal of the face it hit

So it should just be
%collPos = getWord(%ray, 1);

Is this wrong?
#22
06/15/2007 (4:15 pm)
It returns the ID, then Position, the Normals. But the position is in "X Y Z", so you need to get numbers 1 through 3, (0 being the first number witch is the ID).



P.S. Bryce, I need to talk to you. If you don't want your email to be public, you can email me your email address at "celab@myway.com".
#23
06/24/2007 (12:56 pm)
Behold, the final code:
function AIPlayer::findCover(%this, %attacker)
{      
    for (%i = 0; %i < 50; %i++)
    {
      %x = getRandom(-25, 25);
      %x = firstWord(%this.getPosition()) + %x);
      %y = getRandom(-25, 25);
      %y = getWord(%this.getPosition(), 1) + %y);
      %start = %x SPC %y SPC getTerrainHeight(%x SPC %y) + 3;
      %end = %attacker.getWorldBoxCenter();
      %masks = $TypeMasks::InteriorObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticTSObjectType;
      if (ContainerRayCast(%start, %end, %masks, %obj))
      {
           %cover = ContainerFindFirst($TypeMasks::InteriorObjectType | $TypeMasks::VehicleObjectType | $TypeMasks::StaticTSObjectType, %start, %end);
           %intersect = getWords(%cover,1,3);
           %newPos = VectorSub(%intersect, "0 -2 0"); // Move the point 2 units back
           %this.setMoveDestination(%newPos);
           return %cover;
      }
      else
      {
           if (%i >= 50) // If no cover at the end of the loop
           {
              %this.setAimObject(%attacker);
              %this.singleShot(); // Not exactly single. More like slow auto.
           }
      }
    }
}

What this will do is choose 50 points around the AI, and if it finds one that obscures the enemy AI's line of fire, adjust the point so that it is 2 units away from the cover (otherwise it'll embed itself). Then, run there. If it doesn't work, try again. If the for loop is done and no cover, he's not having a great day.
#24
10/13/2007 (8:58 am)
I guess you can improve the logic a little bit using the left, right or front from the attacker and get a random point in these area, so the bot is not going to run in direction to the attacker...
#25
10/13/2007 (9:42 am)
@ BrYcE , I did something with the AI to take cover before

I just added a dynamic field of the objects in the level to tell the AI that which objects it can go and take cover with.

Then each time the state machine runs to the take cover pharse the AI would search for the nearest object it can take cover and calculate the player position with the take cover object position and move the AI to the position it needs to take cover.

Aun.
Mayan Software
#26
10/13/2007 (9:47 am)
@ BrYcE, one thing you could do to improve your logic is normalize the vector and scale it by 2 units instead of

%newPos = VectorSub(%intersect, "0 -2 0"); // Move the point 2 units back

Aun.
Mayan Software
#27
10/13/2007 (11:54 am)
Ok, still learning about alot of this stuff, so I may be wrong, or just sound stupid ;p.

What if you had the AI do a radiusSearch(?) of about 20 units, of a mask for objects and vehicles (No interiors because you want the bot to be able to shoot over it.) Loop, Then get the closest one found, draw a ray from 2 units away from it and the enemy (I guess use a vector to see which is direction) if it collides with the object draw another ray a few units higher(this is the shooting height of the AI) and if that one goes through, it's perfect cover. Run there shoot away, end loop. If not, loop to the next closest found, repeat. After 3 or 10, or all, yor choice, loops the AI is less picky and will just jump behind the closest one that was postive for both tests, or stand where he is and shoots.

For hiding you could do the same thing but make sure both rays collide so the enemy cannot get headshots. And add interiors to the mask.

Just an idea, whatever.
#28
10/18/2007 (6:35 am)
@Morrock, Luis, Aun--
Thanks for the ideas, but I've already thought up a good cover searching function about a month ago. What I'm doing is having two methods of cover searching. The first one uses markers in the mission to define cover points, and when we need cover we do the radius search and raycasts and run to it if found. If that doesn't return anything, then we use the method with the random points. So far, its working. This is all part of an AI project that I'm planning to release as a resource in a little while, wish me luck!
#30
10/21/2007 (2:50 pm)
www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=10278 You can just type it into the search bar on the top right of the page, and specify your search for Resources only. It is free(all resources are), and I don't think you need a torque license to see this one.
#31
10/27/2007 (5:32 am)
Yes, Killer Kork is free. It's all in torque script so there shouldn't be a problem.
#32
12/08/2007 (2:11 pm)
So instead of making a new thread, I'll post hear. Good discussion and it's very related.

With all this, the AI finds cover succesfully, but say that the cover object moves or is destroyed? It still thinks it has cover. I've seen videos of AI reacting to their cover objects moving (i.e. in Counterstrike source, cs_Office. If you shoot down a cabinet a bot was hidding behind, he runs to a new spot.) And was thinking of ways to do this, anyone have any ideas?

I was thinking you could either:
1) Set a scheduled function to check if you still have cover every 3-10 seconds. If not, do another findCover() check and react.

2) Set a variable to remember the tag and location of the object being used as cover. Set a schedule to check if it has moved from it's original position, if it's still nearby react and move along with it, if not, find new cover. This could also allow AI to take cover beside a slow-moving vehicle, like a tank.

Any other ideas that could be better than these?
#33
12/12/2007 (6:14 am)
There's a few other choices, but I think these would be more performance friendly:

1: Recall the function in the bots onDamage function. The bots response wouldn't be instant, but you don't need to move if your not being shot.

2: Recall the function in the bots onEnterFOV function. If the bot as the player targeted, he would look for cover when he can be seen. You could also tell the bot to fire in this function. I think this option would make things look a bit more realistic.

I'm sure there are better ways out there.
#34
12/12/2007 (3:01 pm)
Here's my AI case system

***Sees target, target is looking away--Fire a single shot every 1/3 seconds.
***Sees target, target is looking this way, not firing--Fire weapon at full rate.
***Sees target, target is looking this way, firing--Switch to StateFindCover, which handles the cover search, laying down suppressing fire on the way there, and hiding and firing from cover.

Instead of doing the raycast system that Caleb and I were discussing, I decided to just stick with manually-placed cover nodes. The problem with the random points is that if a point is inside an object, the raycast returns that object. Then the AI tries to run for that point in the center of the object, performing the famous "trying-to-run-through-the-wall-but-I-cant-so-I'd-better-just-keep-trying" routine. Maybe there is a way to use GetWorldBox() (I don't know what it returns, hopefully something on the object's dimensions) to check if a point is inside that object?
#35
12/14/2007 (2:35 pm)
Caleb, I like the onEnterFOV one much better, if it were me in that situation I would much rather get to new cover before I'm being shot at :p But at the same time they would stay in their spot if no enemies are in sight.

Though how resource intensive do you think my 2nd idea would be though? Just something like:

Get the %coverObj variable from the cover function and add a %coverObjPos variable (do a getPosition()), and start a schedule(3000, checkCoverObj, %this, %coverObj, %coverObjPos) then:
function checkCoverObj(%this, %coverObj, %coverObjPos)
{
  %newCoverObjPos = %coverObj.getPosition();
  if (%coverObjPos != %newCoverObjPos)
  //here just create a new findCover function, 
  //but skip the parts where you need to find the cover object. 
  //Set %newCoverObjPos to the place to the object to take cover behind.

  %coverObjPos = %newCoverObjPos;
  schedule(3000, checkCoverObj, %this, %coverObj, %coverObjPos);
}

Hmm, BrYce. You said you wanted really tactical AI, why not try adding something to make gun accuracy lower over time (I'm not exactly sure how you could do this, setting a counter to the weapons onFire state, then randomly set the bullet of a few 0.01's degrees?) Like a real gun when you just spray continuously. Then instead of bots firing full blast or single shot, have them shoot in bursts like real soldiers.
#36
12/14/2007 (4:21 pm)
@Morrock: I did get the bots firing bursts, just a matter of adjusting how many fire schedules you want in one state loop. I also did implement innacuracy (Not just because it really adds realism, but it's hard to watch bots fight eachother when they are killed before they can take a step for cover).
#37
12/14/2007 (5:35 pm)
What about having the AI check to find out if he is getting attacked, then have him run to the nearest defense and get a position where he can't get hit based on the enemies position?
#38
12/16/2007 (10:35 am)
@Tyler: Okay, but should we run for cover when we see an enemy or wait until we know that we are being attacked also or were about to be (for example, there is another enemy in view that is aiming in my direction, he could hurt me)
Page«First 1 2 Next»