Oak Tutorial

Back to Tutorials

Next Lesson

 

Oak Tutorial 4: Finding Targets

Lesson Requirements
A C compiler, and the Quake2 Source code

Instructions on using the LCCWin32 Compiler.

Example source code

Lesson Summary

In this tutorial I`ll explain a little more about what some of the functions in my source code do. This code does not represent what Oak II is capable of, and I am not going to write a entire bot that you can compile and call your own, I do expect you to make some effort. Ok this tutorial is based on how I`ve been writing my bot, you may choose to do it differently, this is only a guideline :) Please remember that this is a ongoing tutorial series, and if something is not explained or done in this one then its probably going to be in the next one.

 Lesson

Ok firstly its worth noting what is not in my code release:

  1. Proper death animations - I consider this a minor aspect which is less important than good roaming AI.
  2. Ability to fire weapons.
  3. Ability to collect weapons, health, ammo etc.
  4. Any sort of roaming AI at all.
  5. Decent chase AI.
  6. Bots on scoreboard.

These are all things that it is up to you to add, all the required code is already in the source code released by me or id. Now lets look at how we can make the bot "see" things and move towards them. In the code I gave you find the function oak_stand and look for this code:

	// look for a target
	target = findradius(NULL, self->s.origin, OAK_FIND_RANGE);
	while(target)
	{
		if (visible(self, target))
		{
			if (infront(self, target))
			{
				if (strcmp(target->classname, "player") == 0)
				{
					//gi.bprintf(PRINT_HIGH, "Oak: in oak_stand selecting you as target\n");
					self->enemy = target;
				}
			}
		}

		// next taget
		target = findradius(target, self->s.origin, OAK_FIND_RANGE);
	}

This uses the findradius function which id provide (defined in g_utils.c) to find entities within a certain range. Findradius is prototyped:

edict_t *findradius (edict_t *from, vec3_t org, float rad)

So it takes three parameters, the entity to begin the serach from in the entity list, the origin of the radius to search in, and the radius to search from that origin. The above code shows how to use it to get all the entities with a cetain range of the bot. Next the code uses the function visible to determine if the entity we found is visible from the bots position. Finally we use the function infront to determine if the target is invfront of the bot, i.e. visible given the direction the bot is facing. Finally the above code checks if the target is a player, this is something you will wish to expand to check for items, weapons other bots etc, though for the purpose of this tutorial it is enough. Now lets look at the rest of the stand function:

	if (self->enemy != NULL)
	{
		//gi.bprintf(PRINT_HIGH, "Oak: in oak_stand turning to face you\n");	
		OakAI_FaceEnemy(self);
		OakAI_RunFrames(self, FRAME_run1, FRAME_run6);
		self->think = oak_run;
	}
	else
	{
		// run the anim frames
		OakAI_RunFrames(self, FRAME_stand01, FRAME_stand40);
	}
	self->nextthink = level.time + 0.1;

This determines if we found a enemy if so we turn to face them, prepare to run to them, otherwise we simply run the standing animation frames. Finally theres the all important line to tell the bot when next to execute its think function. Until next time, happy quaking.

That should give you something to be getting on with, I`ll further explain what some of the other code does in my next tutorial and why I`ve chosen to do things the way I have.

Ok if you compile the code you can then spawn a bot by typing cmd oak in the console. Remember you must run quake with the command line:

quake2 +set game oak +set deathmatch 1

Assuming you put the new gamex86.dll in the dir called oak.

 

Back to Tutorials

Next Lesson


Copyright © 1998, John Crickett.
Legal Information