Page 1 of 1

check_damage[ ()

Posted: Tue Jun 24, 2008 8:29 pm
by metal_head
As I was looking at Juutis's I found that he/you have made a great descision about the blood throwing system (if I can call it that way).The command I'm talking about checks if the pawn has been damaged,it detects for example whe the player shoots at the pawn.And when that is detected,starts a blood explosion:

Code: Select all

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

			if(LeftCopy(GetLastBoneHit(),4) = "head")
			{
				ModifyAttribute(HEALTHATTRIBUTE,-2*lastdamage);
				AddExplosion("headshot",GetLastBoneHit(),0,0,0);

				splatter();

				headshot = true;
			}
			else
			{
				if(random(0,100) < 25)
				{
					splatter();
				}

				headshot = false;
			}

			if(LeftCopy(GetLastBoneHit(),3) = "arm")
			{
				ModifyAttribute(HEALTHATTRIBUTE,lastdamage/2);
			}

			if(LeftCopy(GetLastBoneHit(),4) = "feet")
			{
				ModifyAttribute(HEALTHATTRIBUTE,lastdamage/2);
			}



			AddExplosion("bullethit",GetLastBoneHit(),0,0,0);

			lasthp = GetAttribute(HEALTHATTRIBUTE);

			if(GetAttribute(HEALTHATTRIBUTE) < 0)
			{
				self.think = "die";
				return 0;
			}

			return true;
		}

		if(GetAttribute(HEALTHATTRIBUTE) < 0)
		{
			self.think = "die";
			return 0;
		}

		return false;
	} ]
If that's right (what I said) can someone explain me how is it working and how can I put this command for example in the Perfectai.s script :?: :)

Re: check_damage[ ()

Posted: Tue Jul 08, 2008 7:48 pm
by Juutis

Code: Select all

		if(GetAttribute(HEALTHATTRIBUTE) < lasthp)
		{
			lastdamage = lasthp - GetAttribute(HEALTHATTRIBUTE);
Check if the health attribute has decreased since last check and if so, calculate how much damage has been taken. Store this value to a variable called 'lastdamage'.

Code: Select all

		if(LeftCopy(GetLastBoneHit(),4) = "head")
			{
				ModifyAttribute(HEALTHATTRIBUTE,-2*lastdamage);
				AddExplosion("headshot",GetLastBoneHit(),0,0,0);

				splatter();

				headshot = true;
			}
If the first four letters of the bone that was hit last are 'head' (for example, bones called 'head_mouth', 'head_hat') take triple damage (the original damage + 2x the original damage). Add the blood effect of a headshot and call the 'splatter()' function. This function is another function in the script and it shoots blood to the wall behind the enemy. Additionally, set 'headshot = true' for various reasons.

Code: Select all

			else
			{
				if(random(0,100) < 25)
				{
					splatter();
				}

				headshot = false;
			}
Other hits than headshots have a 25% chance of leaving a bloodstain on the wall (aka. calling the 'splatter()' function).

Code: Select all

			if(LeftCopy(GetLastBoneHit(),3) = "arm")
			{
				ModifyAttribute(HEALTHATTRIBUTE,lastdamage/2);
			}

			if(LeftCopy(GetLastBoneHit(),4) = "feet")
			{
				ModifyAttribute(HEALTHATTRIBUTE,lastdamage/2);
			}
Hits to arms and feet deal only half the damage.

Code: Select all

			AddExplosion("bullethit",GetLastBoneHit(),0,0,0);

			lasthp = GetAttribute(HEALTHATTRIBUTE);
Always add a blood effect and update the 'lasthp' variable so we can calculate 'lastdamage' next time the pawn is hit.

Code: Select all

			if(GetAttribute(HEALTHATTRIBUTE) < 0)
			{
				self.think = "die";
				return 0;
			}

			return true;
		}
If health is less than zero the pawn dies. Also, 'if(GetAttribute(HEALTHATTRIBUTE) < lasthp)' ends here; So if the pawn is damaged, the function returns true.

Code: Select all

		if(GetAttribute(HEALTHATTRIBUTE) < 0)
		{
			self.think = "die";
			return 0;
		}

		return false;
	} ]
Check if health is less than zero even if the health attribute hasn't decreased. Otherwise, if no damage has been taken and health > zero, the function returns false.



So basically what does this mean? You can check if the pawn has been damaged with the line:

Code: Select all

if(check_damage() = true)
or, even simpler:

Code: Select all

if(check_damage())
And it automatically adds the blood effects, makes the pawn die and calculates the extra damages or damage reductions.


Of course, without modifications it only works with my models and the original script. To make it work with perfectai you have to add the variables I've used (lastdamage, lasthp) and the custom function called splatter() that can be found in my scripts.

Re: check_damage[ ()

Posted: Wed Jul 09, 2008 12:18 pm
by metal_head
WoW,that's very cool! and well tough!
But I'm trying to do this with the perfectai script now and don't know where to start.Let's say I've copied it what should I do to make it work on the perfectai.s.I tried to make this pain order,but it didn't work.

Re: check_damage[ ()

Posted: Thu Jul 10, 2008 11:03 am
by Juutis
If the blood effect is the only thing you want, then forget this whole thing. I made this whole system to get the extra damage with headshots and reduced damage to arms and legs.

There's a variable called 'self.in_pain'. Whenever the attribute that you gave it with AttributeOrder() is decreased self.in_pain is true. I'm not too familiar with perfectai but I do believe that in the low level parts there is something like this:

Code: Select all

if(self.in_pain)
{
     <some stuff here>
}
For the low level parts adding the explosion command there would be enough:

Code: Select all

if(self.in_pain)
{
     AddExplosion("blood",GetLastBoneHit(),0,0,0);
}
In high level that's a bit harder. That's why I don't use high level at all in my AI scripts. The only way would be to use AddPainOrder(). You'd have to jump to a whole new order and on top of that GetLastBoneHit() (the command that we use to put the explosion to the right place) works in low level only. So you'd have to go to a high level order with AddPainOrder(), then use LowLevel() to go to a low level order and THEN you could use AddExplosion(). Jumping between orders naturally takes time and I think the animations get messed up too. For example, if you hit the pawn when he's playing his running animation in high level, I believe the animation would stop for the duration of the order changes.

Anyway, if you decide to go with this here's a something to start working on:

Code: Select all

Setup[ ()
{
     AddPainOrder("Pain",100);
     < other setup stuff, like AttributeOrder() etc... >

     NewOrder("Idle");   // ... or whatever your idle order is called
}

...
...

Pain[ ()
{
     LowLevel("blood");
}

blood[ ()
{
     AddExplosion("blood",GetLastBoneHit(),0,0,0);
     HighLevel("Pain_Return");
}

Pain_Return[ ()
{
     NewOrder("Idle");
}
I'm not very experienced with high level so this whole thing may not even work. And even if it works, it's awfully bad looking because of the animations. There may also be an easier way but this is the only one I could come up with.

Re: check_damage[ ()

Posted: Thu Jul 10, 2008 12:22 pm
by metal_head
SWEAT! It worked,thanks Juutis I can learn so much from you guys.

Code: Select all

monster_missile[ ()
	{
		self.ThinkTime = 0.3;
		if(self.health<=0)
		{
			self.think = "death_biz";
			return 0;
			}
		if((self.in_pain = true) and (random(1,100)<PAINPERCENT))
		{
			 AddExplosion("blood",GetLastBoneHit(),0,0,0);
                         }
This is what I did.Also I set the PAINPERCENT variable to 100.I did this in the "monster_run[ ()" and the monster_lost_target[ (). Thanks a lot! Now I don't have to worry about bleeding anymore.