Quake3 modding quickstart
NOTE: WORK IN PROGRESS!
Install ioquake3
We are going to use the ioquake3 sourceport. And we’re going to compile it
ourselfes. You will need the development libraries for SDL2. Consult your package
manager how to install them onto your system.
Clone and install ioquake3:
git clone git@github.com:ioquake/ioq3.git
cd ioq3
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
We make a Debug build so that we can step through the code.
Note
For a release build type Release
instead of Debug
.
Then, compile and link the programs:
Done.
You should have a ioquake3 binary in ./build/Debug/
.
Notice the baseq3
folder. This folder contains all the
game-data (textures, models, …) of the Quake 3 Arena game.
If you make your stand-alone game some day you will have
another folder, such as myCoolGame
where all of the
gamedata specific to your game go into.
To test our compiled binary out, we can use the Demo-version
of Quake 3 Arena, so you don’t have to buy it (althout it
doesn’t hurt to do so).
Here ist the data for the Quake 3 Arena demo: Demo.
Notice the fileending of pak0.pk3
. This is just a regular zip
file in
disguise. You can inspect its contents with any ZIP tool on your OS.
Copy the pak0.pk3
into you repos’ ./build/Debug/baseq3
directory.
Now, we also need some more pk3
files, namely, the ones that id-Software
published as patches. You can get them from: https://ioquake3.org/extras/patch-data/.
Copy the extracted pk3
files and also place them into your ./build/Debug/baseq3
directory.
Now try to launch ioquake3
from the command line. If everything went well you should now be
able to play the demo version of Quake 3 Arena. Take some time and shoot some bots. You deserved it.
Map Editors
Netradiant Custom
Netradiant Custom is a derivative version of id Softwares original mapping tool, called Q3radiant.
It runs on all OSes. I had trouble getting the precompiled binary to run on my linux box (it could not load
a shared lib). Thankfully, compiling it yourself is not a big deal!
I did find it a bit hard to get used to NetRadiant’s userinterface.
GitHub: https://github.com/Garux/netradiant-custom
IMPORTANT
Even if you don’t want to use Netradiant Custom
and decide to use TrenchBroom (see below) instead, you still
need some tools that come with Netradiant Custom but not with
TrenchBroom. Thus, downloading it is required.
For the following steps the program q3map2 is needed. Make
sure it is in your system-path so it is callable from anywhere
within your terminal!
TrenchBroom
Trenchbroom is a joy to use as its UI is so clean and most of the functions can be
figured out by just guessing. However, there is a very good documentation available:
https://trenchbroom.github.io/manual/latest/
You can download it from: https://trenchbroom.github.io/.
You will need to tell TrenchBroom where your gamedata lives.
For now, point it to the repo’s directory that has the
baseq3
directory in it, that is the Game Path:

TrenchBroom reads all assets from the pk3
files inside
baseq3
. For now, ignore the other two paths you can set
(q3map2 and bspc).
If you navigate to the Face tab inside TrenchBroom you should
now see all the available textures inside the pk3
files that
lie in baseq3
.
IMPORTANT
If you are using TrenchBroom on Wayland then start it with:
QT_QPA_PLATFORM=xcb ./trenchbroom
Compiling the Map
Create a new folder called pak10.pk3dir
inside baseq3
.
Inside pak10.pk3dir
create a folder named maps
. Save
your map from TrenchBroom or Netradiant Custom inside
baseq3/pak10.pk3dir/maps/
and make it your cwd
in
your terminal. Type:
q3map2 -bsp <yourmapname>.map
q3map2 -vis <yourmapname>.bsp
q3map2 -light <yourmapname>.bsp
The first command compiles your map into BSP-tree. BSP
stands for Binary Space Partition. It is a nifty
datastructure that works really well for collision detection
and hidden-surface-removal determination of static geometry.
The second command calculates the PSV, which stands for
Potentially Visible Set. This is another optimization
pass that lets the engine discard all triangles that cannot
be seen from the current viewers camera position inside the
gameworld. Thus, those triangles never get passed to the renderer.
Quite frankly, if you just render Quake 3 Maps with relatively
new hardware (maybe 2014+) it probably is faster to just render
all of the world’s triangles every frame. GPUs have
just become so fast in rasterizing triangles that the cost
of figuring out if you can discard 50k triangles is higher
than just feeding them into your GPU and let it render them.
However, I do believe that the PSV is also used for spatial
Audio playback. But I am not sure yet, I will have to dig
into the code more to be sure.
The third command, finally, creates the lightmap. A lightmap
essentially is a texture that contains diffuse precomputed
illumination. It will get blended with the texture you
have assigned to geometry inside your Map-Editor.
Starting your Map
In order to start your map inside ioquake3 you go into your
build/debug/
folder and type:
./ioquake3 +devmap <yourmapname> +set sv_pure 0
+devmap
tells the engine you load your map in debug-mode. That
means you can issue console commands inside the engine (more
on that later) to make yourself invincible, fly around, etc.
+set sv_pure 0
sets the in-engine variable sv_pure to
0 (=false). That means that the engine loads maps, texture, models, etc.
from within folders. They don’t have to be inside a pk3
archive. It would be pretty annoying if you had to first
pack everything before testing it, wouldn’t it?
NOTE
In order for the engine to use a folder as an
assets-resource that folder must have the extension .pk3dir
!
+set sv_pure 0
is not enough!
Debugging the code with Visual Studio Code
It is straightforward to setup VSCode for debugging ioQuake3.
Install the CMake Tools from Microsoft:

NOTE
If you have created a build directory already like in the beginning of the
article, I recommend to delete the CMakeCache.txt
inside it as it
might confuse VSCode when configuring the project.