.qc (dot qc) - the group for quake c coders of all denominations. If you make quake one mods and write code in quake c, join our group! I'll try to answer any quake c questions - please post your inquiry in the forums...

Post tutorial Report content RSS feed Quake c - .think() and .nextthink

The quake-c entity .think() function pointer is an engine managed timing concept that is used on nearly every entity in the game.

Posted by on - Basic Server Side Coding

What is .think() ?

The quake-c definition is found in "defs.qc":

.void() think;
.float nextthink;

If you peruse: Moddb.com , you realize ".think()" is a per-entity stored pointer to some function call and ".nextthink" is a float number.

What do they do?

These variables are set by quake-c code, and controlled by the engine. The concept is simple, however, the effect on quake-c coding is profound.

A function call value is assigned to ".think". Then ".nextthink" is assigned some time value in the future.
The server accumulates the current time in seconds as a global variable "time". Each iteration (server tick) every entities ".nextthink" value is compared to "time". While ".nextthink" is greater than "time" nothing occurs.

When ".nextthink" becomes less than or equal to time (since time is always accumulating value), the engine causes the function in ".think()" to be called during the next quake-c operation.

Three things are required to use this timer concept:

1. A valid entity.
2. A valid function pointer stored in ".think()"
3. A time value greater than the current global "time" stored in ".nextthink"

Here is an example from "misc.qc":

void () misc_fireball =
{
precache_model ("progs/lavaball.mdl");
self.classname = "fireball";
self.nextthink = time + (random() * 5);
self.think = fire_fly;
if (!self.speed)
self.speed = 1000; // Cataboligne 9.17.3 - fixed this compiler warning
};

"misc_fireball" is a map spawn function. It creates a lavaball launcher. These are often found in lava pools. The quake start map has a couple in the hall leading to episode 3.

What this code does is tells the server to make a function call to "fire_fly" with the launcher entity assigned to the "self" pointer in current "time" + 0 - 5 seconds. The launcher then fires off a lava ball and reloads ".nextthink" with some future time value. This think continues until the map is ended.

If you look through quake-c code you will find many instances of ".think()" used to control elements of game flow. It is not necessary to have an entity that is visible in game. Non model entities can be set up as timers (like the example above, the launcher is invisible, having no model assigned. The precache is so the lavaball model can be used for launches later.)

".think()" is used for monster ai, mega health rot, environmental effects, artifact countdown, and many other game elements.

The possibilities of this timer control method are almost limitless in quake-c. The brilliance of the ".think()" concept is code can be run exactly when needed and continuous loops and constant checks are not needed every quake-c operation.

The biggest code fault associated with ".think()" is failing to assign ".nextthink" a proper value:

self.nextthink = 10; // this will only happen at 10 seconds after map load. It does not add 10 seconds to "time"

self.nextthink = time + 10; // this will cause a ".think()" to happen every 10 seconds

You are now ready to code up some "thinking" entities!

Post a comment

You are not logged in, your comment will be anonymous unless you join the community. Or sign in with your social account:

Established
Privacy
Public
Subscription
Open to all members
Contact
Send Message
Homepage
Moddb.com
Membership
Join group
Group watch
Start tracking
Tutorial
Browse
Tutorials
Share
Related Games
Quake
Quake First Person Shooter
Related Engines
Quake Engine
Quake Engine GPL
Related Groups
Dark Places engine team
Dark Places engine team Developer with 15 members
id Software
id Software Developer & Publisher with 2 members
qc
qc Hardware & Tech with 31 members
QuakeDB
QuakeDB Fans & Clans with 151 members