Quake Strogganoff Lesson: Custom defs

Sat, Jan 25, 2020 3-minute read

One very important thing to keep in mind when it comes to architecting any project is centralizing where to store all of your mod specific utility functions like additional traceline functions or vectors, ammo, armor and health values and other game balancing variables.

Make a new file called [modname]_defs.qc and add it to progs.src right after defs.qc.

Note: The file progs.src is where new files are added to be compiled into the main server gamecode. The order matters as you can think of this manifest as representing one long continuous file.

So as an example, inside [modname]_defs.qc, you would add something like this:

/*
============
WEAPONS
============
*/

#define ROCKET_SPEED 1000

Then in weapons.qc under the rocket firing code you would change:

missile.velocity = aim(self, 1000);
missile.velocity = missile.velocity * 1000;

To:

missile.velocity = aim(self, ROCKET_SPEED);
missile.velocity = missile.velocity * ROCKET_SPEED;

NOTE: A value so nice, you use it twice.

A define is really just a way to give a variable something readable that will be replaced by its value when the code is compile. This is also known as a preprocessor directive. Think of it as the compiler doing a find/replace of the value before its final compile.

By doing it this way it becomes really easy to change values everywhere within the source and it’s all located in one spot. This can be everything from ammo and damage values to the paths of sound files etc…

Ok, let’s try something a little more advanced. Here’s a few that may come in handy regarding logging. You’ll find you tend to spit out a lot of debug info to the console and there are many different ways. There’s dprint and bprint and sprint, probably others. Anyway, let’s stick with bprint.

So, say you wanted to send a bprint message to the console. You would typically put.

bprint ("some message\n");

The “\n” is the end of the line and is like hitting enter to help separate output messages to their own lines for easy reading.

But say you wanted to make it even easier to send a log message without all the dprint \n stuff? Well if you put the following into your modname_defs.qc:

#define LOG(x) bprint(x);bprint("\n")

And now when you want to output something to the console you can use the following instead:

LOG("some message");

This is also called a macro, it’s a way of defining custom code that will be rearranged by the preprocessor before it’s compiled. What the compiler end up with is this:

bprint("some message");bprint("\n");

It will behave the same way but look a bit cleaner. And you could also take it a step further for outputting different variable types to string. Like vectors and floats by integrating vtos() (vector to string) and ftos() (float to string):

#define VLOG(x) bprint(vtos(x));bprint("\n")
#define FLOG(x) bprint(ftos(x));bprint("\n")

And like before, you simply give it the right value. Paste the following at the bottom of PutClientInServer:

LOG("HELLO THIS IS THE CLIENT!");
FLOG(self.weaponframe);
VLOG(self.origin);

You may want to change the goofy names from FLOG and VLOG to something that makes more sense to you. But with any luck, you should see some output in the console after starting a map. Like:

HELLO THIS IS THE CLIENT!
0
'123 123 123'

NOTE: If you’re using this macro in an IF statement, you’ll need to use braces because the macro is multi-lined.

I.e:

if (something)
LOG("something happed!");

Won’t work, and you’ll have to do it like this:


if (something){
LOG("something happed!");
}

And that’s basically it. Hope this helps and as always, happy modding!