Creating a Dynamically-Sized Bodyque

From Quake Wiki

In Quake, there is a limit of four player corpses being displayed at once, but what if you want to be able to easily change that?

Posted by Sajt on Sep 25th, 2004 - Basic Server Side Coding

If you've played Quake online, you may have noticed that while you do see player corpses occasionally, the level never seems to get cluttered with them no matter how many times people die. This is because in the code there is a bodyque, a list of four entities that are used as a 'queue' for corpses. It will hold the four most recently killed corpses.

Perhaps you don't want only four corpses. The way the bodyque list is hardcoded makes it ugly and hard to change. This is why we are going to change it to simply construct its own bodyque based on a constant value you give it.

Open up world.qc. Scroll down near the bottom until you find the function InitBodyQue. It looks like this:

void() InitBodyQue = {

local entity    e;

bodyque_head = spawn();
bodyque_head.classname = "bodyque";
bodyque_head.owner = spawn();
bodyque_head.owner.classname = "bodyque";
bodyque_head.owner.owner = spawn();
bodyque_head.owner.owner.classname = "bodyque";
bodyque_head.owner.owner.owner = spawn();
bodyque_head.owner.owner.owner.classname = "bodyque";
bodyque_head.owner.owner.owner.owner = bodyque_head;

};

To be honest, this is rather ugly. It works, but we are going to replace it with something much better :)

Simply replace that function with this new one:

void() InitBodyQue {

local entity e;
local float i;
e = spawn ();
e.classname = "bodyque";
bodyque_head = e;
i = 0;
while (i < (BODYQUE_SIZE - 1))
{
 e.owner = spawn ();
 e.classname = "bodyque";
 e = e.owner;
 i = i + 1;
}
e.owner = bodyque_head;

}

Now add the following constant definition anywhere in your code before this function (I recommend defs.qc):

float BODYQUE_SIZE = 4;

You can change the size to anything you want. Be reasonable, however ;)

It was that simple! You now can dynamically change the size of your bodyque.

[page=Explanation & Conclusion] You now can dynamically change the size of your bodyque. But this wouldn't be a tutorial if it was just that. Let's examine what we changed.

Explanatian First of all, the bodyque is a linked list. A linked list contains items that contain pointers to the next item in the list. The main advantage of using a linked list is that it is not statically sized: you can add, remove or modify items from the list whenever you want.

In QuakeC the items in a linked list are entities, and the pointers are just that: entity pointers in the form of QuakeC fields (in this case we use 'owner').

Linked lists must have a head, which is either the first item in the list or a pointer to it. Without this, the linked list would be lost and you wouldn't be able to reach it! The bodyque linked list is a looping linked list. This means that the last item in the list points back to the first (You can observe this by the 'e.owner = bodyque_head;' line in the code).

The bodyque is created at the start of the level, with empty spaces to put corpses in. Each time someone dies, the CopyToBodyQue function (under InitBodyQue) is called, which changes the bodyque_head entity to look like the player's corpse. It then changes bodyque_head to point to bodyque_head.owner, the next in the list. Eventually, bodyque_head.owner will equal the first corpse entered, and that one will be replaced! Simple, is it not? Even if not, you still got the job done ;)

Conclusion Whether you simple cut-and-pasted the code, or actually read through my poor explanation, you have hopefully gotten something from this tutorial. Linked lists are an essential programming tool, and it's best off to start simple. Before you know it, you'll be getting into dually-linked lists that have to be modified on the fly!