A floating point value.
Floats are also used to store booleans (TRUE, FALSE) or integer values linke counters, or bit flags.
Valid syntax: 12 1.6 0.5 -100 Invalid syntax: .5
A parsing ambiguity is present with negative constants. "a-5" will be parsed as "a", then "-5", causing an error. Separate the - from the digits with a space "a - 5" to get the proper behavior.
A vector, made of 3 float coordinates.
Used to represent positions or directions in 3D space.
Valid syntax: '0 0 0' or '20.5 -10 0.00001'
Note the simple quotes around the vector. Do not use double quotes, they are reserved for strings.
If you declare a vector foobar, then you can access it's x, y and z fields with: foobar_x, foobar_y,foobar_z.
Represents a character string.
Used to indicate file names, or messages to be broadcast to players.
Valid syntax: "maps/jrwiz1.bsp" or "ouch!\n"
Use \n for newline.
The reference of an entity in the game, like things, players, monsters.
For instance, this is the type of the entities self
and other.
The entity type is a structured type, made of fields.
A description of each field is available.
Countrary to the other types, the entity type is a reference to an instance of a structured object, that contains many informations of totally different kinds.
To access all these informations conveniently, they are stored as fields of the entity object, and each field is given a name and a type, that makes it distinct of the others.
Some of the fields do not store value, but instead they store the function to be executed in certain conditions. They are called the methods that can be aplied to the object.
If Quake-C was an object oriented programming language, those method functions and would be distinguished from the other fields. And, above all, you would be able to create new object types, with their own fields.
As Quake-C stands currently, all the field definitions are definitions of entity fields. So anywhere in your code you could add definition of new fields, and the compiler would interpret them as an extension of the entity definition.
Here are all the possible definitions of entity fields, with their types:
.float field_name; .string field_name; .vector field_name; .entity field_name;
In the first file read by the Quake-C compiler, defs.qc, there must be a definition for the entity fields, and world fields. This definition is hard coded. You had better not touch it, or you will have to recompile Quake itself.
The globals are defined before the special definition
void end_sys_globals;
The entity fields are defined before the special
definition void end_sys_fields;
It's not important if you don't understand the nonsense above. It's an ugly hack. Just don't modify defs.qc before those two tags, and you won't be in trouble.
The language is strongly typed and there are no casts.
Source files are processed sequentially without dumping any state, so if a defs file is the first one processed, the definitions will be available to all other files.
Error recovery during compilation is minimal. It will skip to the next global definition, so you will never see more than one error at a time in a given function. All compilation aborts after ten error messages.
Names can be defined multiple times until they are defined with an initialization, allowing functions to be prototyped before their definition.
// in headers void() MyFunction; // the prototype // later void() MyFunction = // the initialization { dprint ("we're here\n"); };
Here are some remarks by Adnan Zafar (zafar@hal-pc.org)
The compiler only catches syntax and other language-style errors. It will not warn you of things that generate run-time errors.. and definitely doesn't guarantee that things will work the way you want. It's been my experience that I have to compile and test something 6 or 8 times; the first few times it doesn't work at all, and the last few it doesn't work exactly right. [...] I just don't want you to think that all the code that compiles will have a good chance of working. In all likelihood, it won't.
Code execution is initiated by C code in quake from two main places: the timed think routines for periodic control, and the touch function when two objects impact each other.
Execution is also caused by a few uncommon events, like the addition of a new client to an existing server.
There is a runnaway counter that stops a program if 100000 statements are executed, assuming it is in an infinite loop.
It is acceptable to change the system set global variables. This is usually done to pose as another entity by changing self and calling a function.
The interpretation is fairly efficient, but it is still over an order of magnitude slower than compiled C code. All time consuming operations should be made into built in functions.
A profile counter is kept for each function, and incremented for each interpreted instruction inside that function. The "profile" console command in Quake will dump out the top 10 functions, then clear all the counters. The "profile all" command will dump sorted stats for every function that has been executed.