AI Tutorial
Opening Secret Doors

 

      This is the tutorial which has been bugging me for I while. I expect several of you have tried something similar to this, and had no luck. The idea seems simple. Search around the area for a secret door, and make it your enemy. Easy, right?
      Wrong. The main problem is this. The ID routine visible() won't spot secret doors. At first, I simply couldn't understand why, until I physicaly edited a BSP file, and discovered the horible truth ... secret doors don't have a .origin point set! .origin points are required for both visible() and bot_aim_at_enemy(). After a while, I came up with a solution. Instead of using an origin point, tell it to use a point halfway between the top right and bottom left corners of the door. Easy to say, not so easy to implement.
      Ok, lets begin coding on this monster. Open up tutor.qc, and scroll down to bot_aim_at_enemy. It may look like this, but it may not:


// -------------------------------------
vector() bot_aim_at_enemy =
// -------------------------------------
{
	return normalize(self.enemy.origin - self.origin);
};

      Now at the begining of that routine, whatever it now looks like, add this:

	if (self.enemy.classname == "door")
		return normalize((self.enemy.absmin + (self.enemy.absmax - self.enemy.absmin) * 0.5) - self.origin);

     That is short but sweet. That's my code for making it aim at the centre of an object, not it's origin. Next, go up to bot_walk, and above it paste these two routines:

// ------------------------------------------------
float (entity targ) wall_visible =
// ------------------------------------------------
{
local vector	spot1, spot2;

	spot1 = self.origin + self.view_ofs;
	spot2 = targ.absmin + ((targ.absmax - targ.absmin) * 0.5);

	traceline (spot1, spot2, TRUE, self);	// see through other monsters

	if (trace_inopen && trace_inwater)
		return FALSE;			// sight line crossed contents

	if ((trace_fraction == 1) || (trace_ent == targ))
		return TRUE;

	return FALSE;

};

// ------------------------------------------------
void() bot_find_secret =
// ------------------------------------------------
{
local entity item;

// he gives up on that item and marks it to avoid it for a while

	if (self.goalentity != world)
		return;

// checks a radius around him for items
        item = findradius(self.origin, 200);

	while(item)
		{
		if ((item.health) && (item.classname == "door") && (wall_visible(item))) 
			{
			self.search_time = time + 2;
			self.goalentity = item;
			self.enemy = item;
			self.th_run();
			return;
			}
		item = item.chain;
		}

	return;

};

      The first routine is my version of visible, which uses the centre of the door as the target point instead of the origin point.
      The second routine is the simplish routine for locating a secret door as an enemy. You may notice I set it to only attack the door for two seconds. This is a bit of a cheat really, as it saves having to edit at many more points to recognise if the door if dead. Instead, I made it give up on the door after a moment anyway.
      Just a couple more steps now. Scroll to bot_walk, which begins like this:

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void() bot_walk =
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
	

// this is his main AI routine, where he will look for items and enemies

	if (!(self.flags & FL_ONGROUND))
		return;

	bot_look_for_bots();
	bot_look_for_players();
	bot_search_for_items();

    After this stick in a line saying:

	bot_find_secret();

      Onwards, onwards to the final step (I hope). Go down to bot_run and at the very end of it, add the following two lines.

	if ((self.enemy.classname == "door") && (wall_visible(self.enemy)) && (time > self.attack_finished))
		self.th_missile();

      Phew! I didn't really explain much of this tutorial, but it should be kinda obvious. Basically, everywhere that visible() is used, I've added a bit saying "if my enemy is a door, use the wall_visible code to determine if I can see it."
      I'm pretty sure that's it really. If I've missed something, such is life!
 


What We Learned

1. If something doesn't work, try to find out why
2. Many weapons can only be found behind secrets on some levels
3. Always think of other ways to solve problems


Author: SkinSki
Questions: skinski@storm-1.freeserve.co.uk
AI chat on ICQ: 30578982