TUTORIAL 3 - HELLO, QWORLD !
"Booyakasha !". Ok, now it's a pre-requisite that you're able to compile
the qagamex86.dll - if you haven't managed that, then have a look at the
In this tutorial we're not actually going to print "Hello, qworld!" on the
console (Boring!), we're going to modify the speed of rockets (as
suggested in the id readme file). We're also going to learn a thing or
two about rockets along the way. Now let's get into it.
1. MAKE A COPY OF THE CODEBASE
It's good to always keep a pristine copy of the original codebase.
Imagine if you fuck up one of your source files (delete crucial lines,
whatever), you'll need a backup right ? Rather than re-install
Q3aGameSource.exe every time, let's keep quake3\source as our 'pristine'
codebase. NEVER MAKE MODS in quake3\source !! We'll make mods in
individual mod directories... let's start by creating quake3\mymod.
Ok then, we simply copy quake3\source to quake3\mymod. Double click on
quake3\mymod\q3agame.dsw - from now on, follow all the tutorials using
this codebase (I made a shortcut to this .dsw file on my desktop). If
you modified the "Output file name" setting correctly in the first
tutorial, the .dll for mymod should compile to the quake3\mymod
directory - compile the 'game' project and check this.
Whenever we've finished messing around with a tutorial and want to
refresh the codebase back to the original, simply copy quake3\source to
quake3\mymod. You can have as many mod directories as you want... I
often have more than one mod in progress at any one time... quake3\rail,
quake3\cts, etc... your hard drive's the limit!
2. FIND SOMETHING INTERESTING
Let's load up the quake3\mymod\q3agame.dsw project in MSVC. Maximize
MSVC - you'll need all the real estate your desktop can give you. Make
sure 'game' is the active project. Select "File View" on the left hand
pane, and find the source file 'g_missile.c' in the tree. Double click
on 'g_missile.c' - the source file should open up in the editor window.
Go to line 362 (hit Ctrl+G for an easy shortcut) and find the fire_rocket function :
gentity_t *fire_rocket (gentity_t *self, vec3_t start, vec3_t dir)
bolt = G_Spawn();
bolt->classname = "rocket";
bolt->nextthink = level.time + 10000;
bolt->think = G_ExplodeMissile;
bolt->s.eType = ET_MISSILE;
bolt->r.svFlags = SVF_USE_CURRENT_ORIGIN;
bolt->s.weapon = WP_ROCKET_LAUNCHER;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 100;
bolt->splashDamage = 100;
bolt->splashRadius = 120;
bolt->methodOfDeath = MOD_ROCKET;
bolt->splashMethodOfDeath = MOD_ROCKET_SPLASH;
bolt->clipmask = MASK_SHOT;
bolt->s.pos.trType = TR_LINEAR;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit
on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, 900, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
If you like, go and have a read thru our first article on quake entities...
Back already ? Great ! Line 372 is creates a new entity (called bolt).
The G_Spawn() function creates a 'blank' entity... then next job is to
flesh out all the details (what sort of entity is it ? what are the
characteristics ? etc). The next 20 or so lines of code define all this
Line 373-375 define the bolt to be a "rocket", and it will 'think' again
in 10 seconds (time is measured in 1000'ths of a second in the quake
world, thus 10000 equates to 1 second). When the rocket 'thinks' it will
call the function G_ExplodeMissile. In other words, if it hasn't touched
anything already, our rocket will explode after 10 seconds. This
prevents our rockets flying off into outer space forever.
Neat, we've discovered something about the game from looking thru the
code! Let's see what else we can figure out about rockets...
We can see that the rocket deals 100 damage (direct OR splash), and that
the splash damage radius is 120 units. Line 391 tells us that the rocket
moves at a speed of 900 units/second. There's also a whole load of
constants used in this function (constants are usually in CAPS)... we
can guess what most of them mean. 'ET_MISSILE' for example means
'Entitry Type: Missile' (as opposed to an item or a player).
3. OUR FIRST CODE CHANGE
Let's modify line 391 so that it looks like this :
Hit F7 to compile our .dll. Fire up quake (Run "quake3\quake3.exe +set
fs_game mymod +map q3dm1") and see if it worked - you rockets should be
VectorScale( dir, 300, bolt->s.pos.trDelta );
Done! That's our first tutorial. Let's keep blazing onwards...