URCS Quagents Home


Quagents: Creating new bot types

Motivation

For simple class projects, using the built in Quake 2 monsters is sufficient.  However, custom models and animations can be used to give a demo a professional look an feel.  Most of this tutorial is on how to add new simple models into URQuake, but a little will be said on integrating new models for additional behaviors by coding extensions.

There are four sections to this tutorial.  You can skip either or both of the first two, just grab the necessary files:

1. For Creating a Quake 2 model from a 3ds model, you need a model of a lander.
2. For Coding your bot, you need pak1.pak placed in your baseq2 directory(rename pak1.pak to one number higher than your current highest,) and m_generic.c and m_generic.h.
3. For Integrating with URQuake, you need the above pak1.pak, m_driller.c, and m_driller.h.
4. For Running your new bot, you need pak1.pak in your baseq2, m_driller.c and m_driller.h in your .../quagent directory, and a few modified quagent files.

Programs you need:

NPherno's Skin Editor Tool
Quake Model Editor
Qped
A program for creating 3ds files, such as Bryce or 3D Studio Max

Note that there are a wide variety of tools available that do the same job, but these are probably the simplest.  There aren't many good tools for use with Linux, but the output from these works fine in the Linux version of URQuake.

Creating a Quake 2 model from a 3ds model:

Actually modeling anything from scratch is complex and is better left to other tutorials.  For the purposes of this tutorial, you can use this model of a lander.
  

Warning!
Many helper programs use the Quake 2 PAK file system in unusual ways.  The main thing is to remember that the root directory of a PAK is the same as your Quake2/baseq2, and any subdirectories will be accessible in the same way.  (For example, the equivalent to /models/monsters/driller would be c:\Quake2\baseq2\models\monsters\driller.)  Some programs get confused if your files are not edited and saved with this structure in mind.

  1. To begin, create a directory c:\Quake2\baseq2\models\monsters\driller.  It is not necessary to actually have a copy of Quake 2, but any time you're asked about its location, refer to c:\Quake2.
  2. Save the lander model to that directory and start Quake Model Editor.  Select File->Import Objects... and open the driller.3ds model.
  3. In the frame view on the left, right click on skin and select Rename Scene.  Change it to stand.
  4. Select File->Save Model As....  Save it as tris.md2, a Quake2 (*.md2), in the .../driller directory.
  5. Start NPherno's Skin Tool.  Open the tris.md2 file.
  6. Select Skins->New.  Click Yes for all questions, and you will see a skin with a checkerboard pattern and model lines drawn on it.  Edit the skin in any way you'd like, then select Skins->Save As, and save it as skin.pcx.  Exit the Skin Tool, but don't save the model.
  7. Go back to the Quake Model Editor, and select File->Import Skin..., and open skin.pcx.  "Replace current skin" and "Crop to skin size", if asked.  Save the model.
  8. Start Qped.  Use Edit->New Directory to create the structure root/models/monsters/driller.  Left click on the driller directory, then select Object->Import from file, and import your md2 and pcx files.  You will have a number of pak files in your baseq2 directory.  Save the file you made as one number higher than your highest numbered pak.  For instance, if you only have pak0.pak, save it as pak1.pak.  If you have pak0.pak through pak3.pak, save it as pak4.pak, etc.  Copy the file to the baseq2 directory in your copy of URQuake.  You're now ready to begin coding.

Coding your bot:

To begin, get a copy of m_generic.c and m_generic.h.  Rename them to m_driller.c and .h, and put them in your quagent directory.  Open up m_generic.c:

Built into the generic bot is a single frame animation for standing, running, and walking, as well as an explosion upon death.  If you don't want to make any changes here, just change every instance of "generic" to "driller".  If you want to make more complex animations or take advantage of extra behaviors, look at the other m_*.c files for examples. 

There are several built in behaviors, named: stand, walk, run, dodge, attack, melee, sight, and search.  Technically, these behaviors can refer to anything.  For instance, dodge could be changed so that when it is called, the bot could be made to dance or run around in circles, or whatever you'd like.

Integrating with URQuake:

To fully integrate your new model and code with URQuake, you need to modify quagent.c, quagent_funcs.c,  quagent_server.c, config.l, and config.y.  I can't provide a modified copy of these, as your version of URQuake could be different from the one that I'm currently using.  However, these modification should work for any version.  First, open up quagent.c:

In quagent_stand, you will see a set of if-elses, of the format

else if(strstr(self->classname, "mutant")){
    self->monsterinfo.currentmove = &mutant_move_stand;
}

When the quagent controller wants the quagent to stand, URQuake has to know which stand function to call.  Now create your own:

else if(strstr(self->classname, "driller")){
    self->monsterinfo.currentmove = &driller_move_stand;
}

Now open up quagent_funcs.c:

Name_dict is used for actions such as ASK RAYS and DO GETINVENTORY.  It maps the names used by the quagent controller to the internal URQuake names.  Look for

} name_dict[] = {
{"health","tofu"}
...
{"bot_mutant", "george"}
};

Add your driller at the end of the name list:

{"bot_driller", "driller"}

Next, in is_bot, add "bot_driller" to the array *bot_list[]. 

char *bot_list[] = {"bot_soldier", "bot_berserk", "bot_chick",
"bot_gladiator", "bot_gunner", "bot_infantry", "bot_parasite",
"bot_mutant", "bot_driller"};

Right below *bot_list[], still in is_bot, there is a loop to check if the entity is a bot, looking something like the following:

for(i=0;i<8;i++){
if(strcasecmp(bot_list[i], quake_name) == 0)
    return i+1;
}
if(i==8) return 0;

Change the 8 in i<8 and i==8 to the number of elements in *bot_list[], including your new addition (In this example, change it to 9.)

Open up quagent_server.c and create a new quagent_spawn_info:

quagent_spawn_info driller_info={0,0,100,0,0,5000,1000.f,5.f,4000, {0,0,0}};

These quagent info structs hold initial properties for quagents, such as health and wealth.  If you like, you can modify any of them for your driller bot.

Next, still in quagent_server.c, look for the switch block with

switch(quagent_spawns[current_quagent].type){
case PARASITE:
newbot = SP_quagent_parasite(fpsclient);
load_default_info(newbot, &parasite_info);
break;
...


When URQuake is asked to spawn a new bot, it needs to call the correct spawn function attached to the specified bot type.  Add driller, with the case

case DRILLER:
newbot = SP_quagent_driller(fpsclient);
load_default_info(newbot, &driller_info);
 break;

Now open up the Bison script config.l.  There is a group of token definitions, such as

berserk|BERSERK|Randal|randal {yyval.index=BERSERK; return BERSERK;}

This means that in your quagent.config script, you can refer to the berserk bot as "berserk", "BERSERK", "Randal, or "randal", and each will cause the correct bot to be spawned.  And as before, put in yours:

driller|DRILLER|Driller {yyval.index=DRILLER; return DRILLER}

Almost done!  Open config.y, and look for a a set of token definitions, in the form:

%token <index> BERSERK CHICK GLADIATOR GUNNER INFANTRY PARASITE SOLDIER

Bison will automatically create an index number and attach it to a string, as it's a lot easier to talk about DRILLERs and SOLDIERs than numbers.  Add:

%token <index> DRILLER

Finally, for the last modification, look for quagent_type:

quagent_type:BERSERK|CHICK|...|MUTANT;

This is a list of all of the possible quagent types.  Put DRILLER at the end

quagent_type:BERSERK|CHICK|...|MUTANT|DRILLER;

At the terminal window, type "make", and if you typed everything in correctly your new bot is now ready to run!

Running your new bot:

Modify your quagent.config script, to add at the beginning

quagent { type driller initiallocation 0 0 0 }

Or just download this quagent.config.  Run Quake, and the first quagent that pops up will be your new driller, which operates in the same way as the other quagents.

Last updated:    by barnum