Code along with RawShark #1

9 posts / 0 new
Last post
Code along with RawShark #1

So now that we know how to compile ioquake3, and we know what we want to acheive with the mod, we need to start trying things out. The ioquake3 wiki has a tutorial on Cloaking, which is great, 'cos we need that! We'll add this in and later on fix it so only players with the lowest score can use the command. Also, we don't want player health to deplete when cloaked, so we'll simply leave that bit out.

In directory code/game, open up g_local.h in your favourite editor and add the code after line 52 (note that in the latest codebase the line numbers are different than the original wiki tutorial. I will always use the latest line numbers, where possible)

#define FL_NO_HUMANS       0x00004000     // spawn point just for bots
#define FL_CLOAK               0x00010000     // RawShark 15/5/12 health cloaking

Now we need to create a new console command. Open up g_cmds.c and add the following around line 1026:


RawShark 15/5/12
void Cmd_Cloak_f( gentity_t *ent ) {

       char *msg; // message to player

       ent->flags ^= FL_CLOAK;

       if (!(ent->flags & FL_CLOAK)) {
               msg = "Cloaking OFF\n";
               ent->client->ps.powerups[PW_INVIS] = level.time;
               // Removes the invisible powerup from the player
       else {
               msg = "Cloaking ON\n";
               ent->client->ps.powerups[PW_INVIS] = level.time + 1000000000;
               // Gives the invisible powerup to the player

       trap_SendServerCommand( ent-g_entities, va("print \"%s\"", msg));

All we did here is create a new function that is called when you use the /cloak command that we will be adding below. This function will change the current state of FL_CLOAK, activate/deactivate the invisible powerup and print a relative on/off message to the player.

You'll notice I'm leaving my name and the date as a comment in each code modification. This makes it easier to find my own changes at a later date. For instance, we will certainly need to come back to this cloaking function again. To find files I had modified at the command line in Ubuntu, I would use fgrep -R -i "RawShark" * while in the source directory. So far this produces:

[email protected]:~/source/ioquake3$ fgrep -R -i "RawShark" *
code/game/g_local.h:#define FL_CLOAK    0x00010000     // RawShark 15/5/12 health cloaking
code/game/g_cmds.c:RawShark 15/5/12

What the hell is "level.time + 1000000000" ? What we are doing is making the invisible powerup last for 1666 minutes, which should be longer than any map duration should the player decide to never decloak. Later on we will fix it so if the player moves or fires his weapon, he will be automatically decloaked.

Now we must add the /cloak console command and get it to call the function we created. Goto line 1708 and add the code below:

else if (Q_stricmp (cmd, "setviewpos") == 0)
       Cmd_SetViewpos_f( ent );
else if (Q_stricmp (cmd, "cloak") == 0) //RawShark 15/5/12
       Cmd_Cloak_f( ent );

The next step is to remove the cloak powerup just before the normal powerups are dropped when the player dies. We need to do this because if a player died while he was cloaked, the invisible powerup will pop up and the next player who picks it up will have unlimited invisibility, without his health decrementing (bit unfair don't you think).

Open g_combat.c and goto line 126, now add the code below:

// drop all the powerups if not in teamplay
    if ( g_gametype.integer != GT_TEAM ) {
        angle = 45;
        for ( i = 1 ; i < PW_NUM_POWERUPS ; i++ ) {
            if ( self->client->ps.powerups[ i ] > level.time ) {
                item = BG_FindItemForPowerup( i );
                if ( !item ) {
                drop = Drop_Item( self, item, angle );
                // decide how many seconds it has left
                drop->count = ( self->client->ps.powerups[ i ] - level.time ) / 1000;
                if ( drop->count < 1 ) {
                    drop->count = 1;
                angle += 45;
        //RawShark 15/5/12
                if (self->flags & FL_CLOAK) {
               // remove the invisible powerup if the player is cloaked.
               self->client->ps.powerups[PW_INVIS] = level.time;

That's all for now, so we compile and test. At this point we'll move our mod files out into a sepetate directory (named "bbq") parallel to the baseq3 directory, to save confusion when compiling troubleshooting. You should do this each time you want to test the game in future (or you could script in along with the make command). What you do is copy the directory baseq3/vm to bbq/vm and the run the executable like so:

build/release-linux-x86_64/ioquake3.x86_64 +set fs_game bbq +map q3dm1

When it comes to distributing the mod later on we will package the VM files up inside a pk3 file, which is done simply by zipping it up and renaming to pak0.pk3.

Scroll up through the console using PAGEUP and you should see something like

Loading vm file vm/cgame.qvm...
File "vm/cgame.qvm" found at "build/release-linux-x86_64/bbq"
...which has vmMagic VM_MAGIC_VER2

indicating that our mod files were successfully loaded.

Tip: I usually run the excutable from the command line with ioquake3 in windowed mode, so I can ALWAYS see the output on the terminal, even after I quit the game.

Now type /cloak at the console to see if the new command works, fingers crossed! The outcome should be favourable.

If it doesn't work, go back through the above carefully, you did something wrong. If it DOES work, great. Bind the cloak command to a key from the console eg. /bind c cloak and congratulate yourself on a job well done! We are done coding for today.

It's worth pointing out at this early stage that if you want your mod to be compatible with older Quake III Arena servers, even if it evolves into a standalone game, you need to enable LEGACY_PROTOCOL in qcommon/qshared.h by uncommenting line 38, like so:

#define LEGACY_PROTOCOL    // RawShark - uncommented 15/5/12. You probably don't need this for your standalone game

otherwise you get that damned "protocol mismatch" error. Until next time....


  • Play a sound for cloak on and cloak off, as per original bbq mod
  • Check for lowest score before allowing cloak
  • Disable cloak when player moves or fires weapon
  • Disable cloak if player is hit by weapons fire


This is a crowdsource mod. If you want to check anything off the TODO list, submit your code below with filename and line number of where to add it.

Mod Menu

Your mod will never show up in the Quake 3 mods menu if there is no pak0.pk3 in the mod directory. You can either zip up and rename your VM each time, or do what I did and simply create a 0 byte pak0.pk3 using the touch command until we are done coding.

Command to do everything at once

This command will cleanup, recompile, copy the vm to the mod directory, and start the game so you can test. I'm on my 64 bit laptop here, so the binary name is different than before:

rm build/release-linux-x86_64/bbq/vm/*;make;cp build/release-linux-x86_64/baseq3/vm/* build/release-linux-x86_64/bbq/vm/;build/release-linux-x86_64/ioquake3.x86_64 +set fs_game bbq +map q3dm1

I've put this in an executable file called test, so now I just run that instead of make.


I've moved my ioquake3 source directory into my Dropbox account, so I can work on the same code from anywhere. Dropbox also lets you share directories publically, which might be useful for small development teams.

I added your function in g

I added your function in g_cmds.c, but at aorund line 1026, I was under #ifdef MISSIONPACK, so the function would not be compiled.

Finally I added your function around line 1192, after the #endif directive.

In your code, the function is after #endif, or inside de #ifdef? Also, how to enter that if cluase? Where is #define MISSIONPACK?

I've shared the source code

I've shared the source code with you via a dropbox collaboration. Check your email for details. Feel free to add any improvements you make to the files in that folder, and then I can compile on my machine here. Welcome to the project! BE SURE TO COMMENT YOUR CHANGES LIKE I HAVE DONE. eg.

#define FL_CLOAK               0x00010000     // RawShark 15/5/12 health cloaking

Also, I assume it's the ioquake3 source you are using?

Thanks! Yes my source is from

Thanks! Yes my source is from ioquake3, but I think my revision is newer than the one you sent me, so that explains the differences.

I don't know anything about the engine, I'm just learning from tutorials. I hope I can bring some aditions to the source code in time.

Look forward to seeing what

Look forward to seeing what you come up with. Be sure to comment here any new lines of code, let's use the same revision for clarity.



I hated hearing that while playing bots...