AI Tutorial
Play Dead

 

      You're going to love this lesson. I figured that after that long and messy bot items tutorial that we needed a short and sweet one. This is the one.
      After this our bot will sometimes fall down when he gets hurt. You can call it getting knocked unconscious or playing dead. Either way, it is very cool.
      Crack open tutor.qc and scroll down to bot_pain(), which looks like this:


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void(entity attacker, float damage)	bot_pain =
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{

      Before that routine, we want to paste this:

void()  bot_fall1		=[	$deatha1,	bot_fall2	] {self.pain_finished = time + 18; self.solid = SOLID_NOT;};
void()  bot_fall2		=[	$deatha2,	bot_fall3	] {};
void()  bot_fall3		=[	$deatha3,	bot_fall4	] {};
void()  bot_fall4		=[	$deatha4,	bot_fall5	] {};
void()  bot_fall5		=[	$deatha5,	bot_fall6	] {};
void()  bot_fall6		=[	$deatha6,	bot_fall7	] {};
void()  bot_fall7		=[	$deatha7,	bot_fall8	] {};
void()  bot_fall8		=[	$deatha8,	bot_fall9	] {};
void()  bot_fall9		=[	$deatha9,	bot_fall10	] {};
void()  bot_fall10		=[	$deatha10,	bot_fall11	] {};
void()  bot_fall11		=[	$deatha11,	bot_fall12	] {};

      This is a new animation sequence with old frames. The frames come directly from the scene bot_deatha1(). In other words, when he falls down, it looks like he's dying.
      There are three things to look at here. One, we set his self.pain_finished to 18 seconds, the time he will be laying down. Two, we make him non-solid, so you can't shoot him when he's down. Three, the last line refers to "bot_fall12" which isn't here. So I guess we have to make it. Before that sequence, paste this:

void()  bot_fall12 =
{
	self.enemy = world;
	self.goalentity = world;
	self.think = bot_rise1;
	self.nextthink = time + 15;

};

      Cool stuff. This clears his variables, so when he gets up, he won't be mad at anyone (in case they left). This also tells him to think the routine bot_rise1() 15 seconds from now. He'll stay still during that time. Now we have to make the rising scene. Paste the following code *before* the previous code:

void()  bot_rise1		=[	$deatha11,	bot_rise2	] {self.solid = SOLID_SLIDEBOX;};
void()  bot_rise2		=[	$deatha10,	bot_rise3	] {};
void()  bot_rise3		=[	$deatha9,	bot_rise4	] {};
void()  bot_rise4		=[	$deatha8,	bot_rise5	] {};
void()  bot_rise5		=[	$deatha7,	bot_rise6	] {};
void()  bot_rise6		=[	$deatha6,	bot_rise7	] {};
void()  bot_rise7		=[	$deatha5,	bot_rise8	] {};
void()  bot_rise8		=[	$deatha4,	bot_rise9	] {};
void()  bot_rise9		=[	$deatha3,	bot_rise10	] {};
void()  bot_rise10		=[	$deatha2,	bot_rise11	] {};
void()  bot_rise11		=[	$deatha1,	bot_rise12	] {};
void()  bot_rise12		=[	$stand1,	bot_walk1	] {};

      I just love working with animation; it's so fun. Here all I did was renumber the death sequence to play in reverse, so it looks like he's getting up off the ground. Also, we make him solid again, and we tell him to return to his walking routine, bot_walk1(), when he's done.
      Next we have to tell the bot when to fall over. Look inside the routine bot_pain(), where you'll see this:

	if (self.pain_finished > time)
		return;

	if (random() < 0.25)
		return;

      After that, paste this:

	if (random() <= 0.02)
		{
		bot_fall1();
		return;
		}

      So he will get knocked down according to a random number. This 0.02 value may be too frequent or too seldom for you; please feel feel to change it. The bot will now ocassionally get knocked unconscious.
      One last change, though. We want other bots to stop fighting him when he falls over. Go into bot_run(), where you'll see this:

	if (visible(self.enemy))
		self.search_time = time + 6;

	if (time > self.search_time || self.enemy.health <= 0)

      The last line is what we're looking at; it's where he gives up fighting if he's been searching too long or if his enemy died. We need to add to that, so change the last line to this:

	if (time > self.search_time || self.enemy.health <= 0 || self.enemy.solid == SOLID_NOT)

      That'll do the trick. Now bots will give up on other bots who fall unconscious. Pretty neat, huh? How many bots do that?
      Speaking of neat, there is one more little thing we can do to really make our bot play dead. It requires that you have done the previous tutorial on exploding backpacks. In the routine bot_fall1(), where we make the bot non-solid, we can add a call to drop_fake_backpack(). It will look like this wehen we're done:

void()  bot_fall1		=[	$deatha1,	bot_fall2	] {self.pain_finished = time + 18; self.solid = SOLID_NOT; drop_fake_backpack();};

      Now, when the bot plays dead, he will throw an exploding backpack! His killer will go for it and be gibbed. You're probably thinking, "Damn Coffee, you must've had this planned!" And you'd be right. Enjoy.
 


What We Learned

1. We can rearrange the player frames into new animation scenes
2. You can't hurt an object that is SOLID_NOT
3. Animation sequences can be tricky to work with
4. Animation sequences happen every 0.1 seconds
 


     Author: Coffee
     Questions: coffee@planetquake.com
     AI chat on ICQ: 2716002