Some Basic AI Questions

Topics regarding Scripting with Reality Factory
Post Reply
User avatar
metal_head
Posts: 1244
Joined: Sat Jan 05, 2008 8:31 pm
Location: Bulgaria,Sofia
Contact:

Some Basic AI Questions

Post by metal_head » Fri May 15, 2009 3:53 pm

Until now, I have been workin on non-AI scripts, but I've come to a point where I really need to make cool enemy scripts for my game. I'm using the perfectai.s script as a base.

First question is about pawn's health:
How does a pawn know when is damaged and when it's health attribute has reached zero? Juutis, I've copied a small part from one of your scripts, the:

Code: Select all

check_damage[ ()
	{
		if(GetAttribute(HEALTHATTRIBUTE) < lasthp)
		{
			lastdamage = lasthp - GetAttribute(HEALTHATTRIBUTE);

			if(LeftCopy(GetLastBoneHit(),10) = "BIP01 HEAD")
			{
				ModifyAttribute(HEALTHATTRIBUTE,-2*lastdamage);
				AddExplosion("pain",GetLastBoneHit(),0,0,0);

				splatter();

				headshot = true;
			}
				
			AddExplosion("pain",GetLastBoneHit(),0,0,0);

			lasthp = GetAttribute(HEALTHATTRIBUTE);

			if(GetAttribute(HEALTHATTRIBUTE) < 0)
			{
				self.think = "death_biz";
				return 0;
			}
		
	} ]
I modified it to suite my needs and put it in the script, then I removed the commands that check if the pawn's in pain and I placed this everywhere where I want the pawn to check what type of injury should it recieve, but now when I shoot the pawn, it doesn't get hurt and doesn't bleed, which tells me, that this order isn't executed... Here's the script:
I think I need a little explanation about the whole thing with the health.
EDIT: In the low level commands, everywhere where there was the if statement:

Code: Select all

if (self.health <= 0)
{
self.think "death_biz"'
return0;
}
I modified it to:

Code: Select all

if (self.health < lasthp)
{
self_think "check_damage";
return 0;
}
lasthp is a variable, which in the begining of the script gets the value of the HEALTHATTRIBUTE variable...
alien1.rar
(5.67 KiB) Downloaded 39 times


The second thing is that I want to use almost the same scripts for everything, so I won't get confused with all the scripts in the folder, so I'll need a little more help on that:

viewtopic.php?f=8&t=3741

This is the topic, where I needed a hjelp on how to make perfectai search for the nearest pawn from another group and then attack it. Everything's fine there, but when the hostile pawns detect the player in their range, they forget about the other pawns that they are fighting with, and start attacking the player (only) . It's like the player is more important to the enemy pawns than the other pawns (normal.. :lol: ), but is it possible to make the pawns detect the player... I dunno, as another pawn, so they all don't don't forget the other pawns?




And the last one is:
When the pawn is chasing the player and the player goes through a doocase, sometimes collides with the wall (it can't aim properly at the doorcase :D ) and than starts it's avoidance order, which is just looking rediculus (you know it, whith the backing up than strafing left, then going forward on adn on and on :D ) would it be possible to make the pawn...somehow be aware of the walls and be aware of the doorcases and others like them, I need the pawn to know where it can go and where it cannot. I know there are commands for calculating the distances of the walls and stuff, but I don't know if they could be useful for this.



Theese are three things that I absolytely don't have Idea how they could be done. Some help on "what should the pawn do" will be really appreciated

User avatar
Juutis
Posts: 1511
Joined: Thu Jan 12, 2006 12:46 pm
Location: Finland

Re: Some Basic AI Questions

Post by Juutis » Tue May 19, 2009 6:28 pm

How does a pawn know when is damaged and when it's health attribute has reached zero?
For basic needs RF has a great system. The one that also PerfectAI uses. You can add a health attribute for the pawn with the high level command AttributeOrder(). The health system works a bit differently depending on if the pawn is executing high or low level orders.

High level: When the health attribute goes to 0 the order, which you gave to AttributeOrder() as a parameter, is executed. That's usually an order for the pawn's death. Additionally, you can add a pain order with the AddPainOrder() command. Then, every time the pawn is damaged that order is executed automatically.

Low level: There's a built-in variable called self.health that tells how much health the pawn has. In low level you have to check manually if the health has been reduced to 0. The low level equivalent for AddPainOrder() is the variable self.in_pain which tells if the pawn has been damaged. That's also something you have to check manually.

This system that should work most of the time. If you don't need special health attributes (for different damage types etc.) then this is what you should use. Also, if you have high level orders that take a long time to execute (moving, playing animations etc.) this is your only option since there's no way to break out of a high level command other than AttributeOrder() and AddPainOrder(): Let's say your pawn is moving between two scriptpoints and you shoot it. If you don't use the default health system you can't break out of the move-command to check if the pawn has been damaged and so you have to wait for the pawn to reach the scriptpoint before it receives any damage.

The biggest downside of the whole AddAttributeOrder() thing is that you can't have multiple health attributes for different damage types. And that's what I wanted when I wrote the AI for Nirhis so I used normal attributes. I just gave each pawn a health attribute with the AddAttribute() command and checked manually if it has been damaged. And that's where the check_damage() method steps in. With the AddAttributeOrder()-system it's easy to check if a pawn is damaged with the self.in_pain variable. I wanted something similar. I didn't wanna write if(GetAttribute(HEALTHATTRIBUTE) < lasthp) everywhere, so I wrote a method to check if the pawn has been damaged, then bleed, and ultimately if the health reached zero, kill the pawn.

I hope that clears the whole pawns' health stuff.

And now on to your problems.

First off, there's a syntax error in your check_damage() method. You're missing one closing bracket }. Also, there's no splatter() method in your script. It's another method I wrote to spill blood on the walls around the pawn whenever it is hit.

Secondly...

Code: Select all

if (self.health < lasthp)
{
self.think = "check_damage";
return 0;
}
That's not how you should use it. :)
The check_damage() method always checks if the pawn has been damaged so there's no need to do it twice. In addition, self.think is used to jump between orders. You only need to execute check_damage() once and then return back to the original order. So you should simply call the method:

Code: Select all

check_damage();
And finally, you should decide if you wanna do it the AddAttributeOrder()-way (AddPainOrder(), self.health, self.in_pain) or the AddAttribute()-way (SetAttribute(), GetAttribute() etc.). I think the SetAttribute(), GetAttribute() and ModifyAttribute() commands work on attributes given to the pawn with the AddAttributeOrder() as well. But self.health and self.in_pain won't work with attributes given with AddAttribute(). I hope I'm not confusing you too much. :lol:
This is the topic, where I needed a hjelp on how to make perfectai search for the nearest pawn from another group and then attack it. Everything's fine there, but when the hostile pawns detect the player in their range, they forget about the other pawns that they are fighting with, and start attacking the player (only) . It's like the player is more important to the enemy pawns than the other pawns (normal.. ), but is it possible to make the pawns detect the player... I dunno, as another pawn, so they all don't don't forget the other pawns?
Dunno, judging from the piece of script I posted in that thread they shouldn't do that. :?
I'll test it when I got time.
When the pawn is chasing the player and the player goes through a doocase, sometimes collides with the wall (it can't aim properly at the doorcase) and than starts it's avoidance order, which is just looking rediculus (you know it, whith the backing up than strafing left, then going forward on adn on and on) would it be possible to make the pawn...somehow be aware of the walls and be aware of the doorcases and others like them, I need the pawn to know where it can go and where it cannot. I know there are commands for calculating the distances of the walls and stuff, but I don't know if they could be useful for this.
I actually managed to pull this off with a very basic pathfinding. But the thing is my level is very linear: It only has two directions, north and south and the pawns are able to navigate through the level using predefined paths. But in more complex levels it gets really complicated. Especially since RF lacks built-in pathfinding. I guess you could somehow try to guess where the door is by comparing the distances to nearby walls or something. Or maybe even have an invisible pawn to act as a marker of some sort. I'll have to think about this and get back to you if I come up with something.


Phew, another wall of text. You all love to read these, don't ya? :twisted:
Pain is only psychological.

User avatar
metal_head
Posts: 1244
Joined: Sat Jan 05, 2008 8:31 pm
Location: Bulgaria,Sofia
Contact:

Re: Some Basic AI Questions

Post by metal_head » Tue May 19, 2009 9:18 pm

Thanks Juutis, so much things just got pretty clear to me! I didn't get confused for even a second.

I needed the check_damage order to make a headshot system in the game

Well, I'll test it again, with a pure copy of the perfectai and watch carefuly

Well, pawns as markers won't be a relly good decision, because there will have to be marker pawns everywhere :D, but it would be much better than now after all.
Phew, another wall of text. You all love to read these, don't ya?
Indeed, the text walls bring really helpful information :lol: Thanks!

Post Reply