wiki:ioquake3

Version 1 (modified by jpawlick, 13 years ago) (diff)

--

The following is what I've learned about the ioquake3 engine, which I hope will be helpful to you guys while I'm away.

Server, Client, Interface

TODO: put text here.

The Virtual Machine

TODO: put text here.

Getting In and Out of the VM

TODO: put text here.

Adding a Trap Function

TODO: put text here.

Quagents Behavior

The entry point for an individual Quagent's behavior is the !BotQuagentAI(...) function in game/ai_main.c. Obviously, this already tells you that Quagent AI is running almost entirely in the virtual machine (the only parts that don't are things we trap out of it, such as socket reads, writes, and elementary actions). BotQuagentAI is called between the motion parts of the frame, so usually you have to set up a motion to execute, you can't actually move stuff (or if you do, it can be undone elsewhere!). The main purpose of BotQuagentAI is to (in the following order): check to see if the bot was just set up (and if so, do some initialization, call some built-in functions to get fresh data structures (such as BotUpdateInventory), read any pending commands from the socket and add them to the command queue, attempt to respawn if dead, update some "latent" values, and then execute as many AINodes as possible.

All Quagent behavior runs through an AINode. An AINode is a function assigned to the bs->ainode pointer in bot_state_t, as you can see in the large switch statement.

AINodes

All AINodes are functions that takes a bot_state_t* (which is defined in game/ai_main.h) and returns either qfalse or qtrue.

Adding an AINode

You will need to edit 3 files: game/ai_quagentsnodes.c, game/ai_quagentsnodes.h, and game/ai_main.c. First, in game/ai_quagentsnodes.h, declare your new AINode function (stick to the format, please), and make a #define for the opcode. Next, in game/ai_quagentsnodes.c, add the case for your opcode macro to AI_QuagentsOpCode (the first function in that file). This method is used to correctly print returns and response. You will also have to write your actual AINode function in game/ai_quagentsnodes.c. Finally, in game/ai_main.c, you need to add the case for your command in the large switch statement in BotQuagentAI, and then add a case for your node in BotAIQuagentsParseCommand. The cases are currently in alphabetical order by opcode to help the programmer recognize opcode collisions. All the case should do is call AIEnter_Quagents. Copy the first four parameters from any other call (but replace QCMD_?? with your opcode macro). The remainder of the parameters are what should be assigned into the command's val1, valf1, valf2, valf3, and so on slots. You can reference these from your AINode function by saying:

quagent_command_t* cmd=bs->commandqueue+bs->currentcommand;
float valf1=cmd->valf1;
float valf2=cmd->valf2;
//and so on...

in your AINode function. Remember that anything compiled inside the virtual machine must be in (a restricted form of) ANSI C90, so all variable declarations must be at the beginning of compound statements, etc.

ai_main.c

TODO: put text here.