View previous topic :: View next topic |
Author |
Message |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Wed Apr 01, 2009 6:34 pm Post subject: Confused Newbie needs help w basic Quake C concepts |
|
|
[DISCLAIMER: If there's a site you recommend that already explains all this, please let me know.]
Hi people.
I've been reading, and reading and reading about Quake C. I can't help but use my current knowledge of C (the only language I'm familiar with) to 'grasp' Quake C, but much if the descriptions (as well as the code itself) is confusing to me. Normally, I'd look at main(), and look up the headers, and decipher what was going on that way. But here there IS no 'main' so I have no idea the order in which instructions are followed, I cant 'watch' the code execute, and so I have to 'guess' what happens and when. The tutorials help, but they still have left me confused as to HOW exactly the code works.
What's the best site which explains Quake C? I've been reading http://www.gamers.org/dEngine/quake/spec/quake-spec34/qc-lang.htm, but the explanations just confuse me. The guy seems to be freely intermixing jargon from C around in a very confusing way.
eg: "As Quake-C stands currently, all the field definitions are definitions of entity fields." (???)
I STILL don't understand exactly what an 'entity' is. Rather than asking the question 'what is an entity' which I've read many descriptions which seem 'sloppy', please allow me to give you rough bits and pieces of my current 'understanding', which I invite people to correct, or confirm.
1. A Quake C 'Entity' = a C 'Structure', ie a collection of variables, of different types, stored as a 'record' eg 'self' contains a bunch of variables which relate to 'self'. Just like C.
2. A 'field' = 'field variable' = a member variable of an entity. eg 'self.health'. Just like C.
3. In Quake C you can't make new Entities. But you can add new variables to existing Entities (?)
4. But every time you add a variable ('field') to an Entity (Structure), ALL entities in the game get that field added to them.(?) Eg, if we're defining
.float fooamount
Does that mean that EVERY ENTITY IN THE GAME has just been assigned a new variable .fooamount? there is now a 'self.fooamount'?
5. To quote from http://www.gamers.org/dEngine/quake/spec/quake-spec34/qc-types.htm#QC-TFLD
"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."
So we're storing functions ('methods') inside entities (structures?). That sounds EXACTLY like C++. So do we call them functions, or methods?
When I started C, once I learned the language, I could (slowly) decipher what was going on, by following the 'flow' of the code. With Quake C, I'm copying and modifying bits and pieces, but without understanding wtf I'm doing, it's really easy to get stuck. It's like I'm in a foreign country with a little phrase book, and whilst I can ask for a coffee, what the time is and where the toilets are, I can't really have a proper conversation.
OneManClan |
|
Back to top |
|
 |
Spike
Joined: 05 Nov 2004 Posts: 944 Location: UK
|
Posted: Wed Apr 01, 2009 7:43 pm Post subject: |
|
|
in c++, an entity is a class (you only get one actual class type) and a field is a member of that class.
Internally (in unmodified quake) the entities are stored in an single lump of memory with offsets counted by (fieldscount*4+internalheadersize)*entnum.
adding a new field adds that field to every entity, whatever sort of entity they are. unmodified quake has a limit of 600 entities. thus a new field takes 600*4 bytes (*12 if its a vector).
function fields (ie .void() think) would be called function pointers in any other language. treat them as member functions, but be aware that you have to assign them.
.classname is just a string that names the function that sets up the initial fields. It does nothing special other than that. The QC code uses it in a few places but other than spawning its purely an identifier for the qc code.
Every entity is identical to every other entity, except: player entities receive additional events (via named functions) and cannot be spawned/removed, a couple of builtins also accept only player entities (purely for their entity index, eg sprint/centerprint/infokey). Entity 0 (world) cannot be written to after entities have spawned, and the engine mostly ignores it.
Other than that, the only differences between entity types are the contents of their fields.
QuakeC revolves around storing stuff in entity fields. By storing function pointers in entity fields, you can change the entity how you want at a given future event.
Rockets, for instance. They have movetype FLYMISSILE so they move in a regular direction, they have a velocity so they do actually move, they have a touch function, so they know when to explode, they have a model, so they actually look like a rocket, and they have an owner, so they don't explode in the player's face. Really that's about all there is to them. I missed a few fields, but that's the general idea.
The engine does the moving/touch triggering/think processing.
All the QC does (for the most part) is set state.
Set movetype bounce and it'll fall to gravity and bounce off stuff (nades). Hopefully you get the idea. _________________ What's a signature? |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Fri Apr 03, 2009 3:31 am Post subject: |
|
|
Spike wrote: | in c++, an entity is a class (you only get one actual
<snip>
Hopefully you get the idea. |
Thanks heaps, Spike.
FYI, I've been reading your post over and over letting it all sink in before I respond!
OneManClan |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Fri Apr 10, 2009 5:43 am Post subject: |
|
|
I have SO many questions about Quake C, but I'd like to read up first, and do my homework before I bother the Gurus. Is there a proper 'manual' for Quake C? A proper 'guide'? I've found *descriptions* of the language, but no reference to what all the Entities are, how to use them, and how the code all fits together.
A Class in C++ is always defined somewhere. A Class in Quake C seems to be defined everywhere, and nowhere.
The cut and paste tutorials help, but the guys who do them don't explain HOW they figured it all out. How they knew which function did what. They all leave me thinkin "wow, how the hell did u figure that out!?".
Maybe it would be better if the Gurus *assumed* people already knew C, and geared all jargon and Quake C descriptions to people who already can program C - since there are clearly defined terms C programmers use (mostly), and already many many books on C, and there's no excuse to not understand the language. Having said that, too many use Jargon to explain Jargon. Or they explain 'how', without explaining 'what'. A rare exception was "The absolute beginners Guide to C" by Greg Perry, a joy to read, and the only programming book I know which explains jargon BEFORE it is used.
I can do 'simple adjustments' in Quake C, but when it comes to anything new or innovative, I get stuck. If I didn't have access to Gurus such as yourselves, I'd NEVER be able to figure out this stuff just by 'looking at the code'.
OneManClan |
|
Back to top |
|
 |
Error Inside3D Staff

Joined: 05 Nov 2004 Posts: 558 Location: VA, USA
|
Posted: Fri Apr 10, 2009 5:56 am Post subject: |
|
|
the way I learned QC was simply staring REALLY REALLY hard at other peoples' code. this doesn't work for everyone, but that's how I did it
more complicated stuff is harder to figure out, but quake has things mapped out pretty well in QC files, I think. a bunch of the code is slightly commented too, so that helps. defs.qc is a goldmine for learning simple engine built-in functions. I learned my syntax from id1's source and admiring FrikaC's code  _________________ Inside3D : Knowledge Is Power
Darkplaces Documentation Wiki |
|
Back to top |
|
 |
Error Inside3D Staff

Joined: 05 Nov 2004 Posts: 558 Location: VA, USA
|
|
Back to top |
|
 |
Urre

Joined: 05 Nov 2004 Posts: 1073 Location: Sweden
|
Posted: Fri Apr 10, 2009 9:56 am Post subject: |
|
|
Feel free to post questions, there are lots of people here who are willing to help people who really try to learn and understand things.
A lot of QuakeC functions are called on demand by the engine, which is why there is no beginning and end to QuakeC. Say, the StartFrame function is called at the beginning of every server tick. ClientConnect happens when a player joins a server. Remember that even singleplayer games use a server in Quake, so all code has to be written with this in mind. It's a multiplayer game with just one player, when you run singleplayer.
Another good example of called on demand are .touch field functions. Those are run when an entity moves into another entity. However, if entity A stands still and entity B bumps into it, the touch function of A will not be called, only the touch function of entity B.
Imagine entities as containers of information. Certain fields give them properties which affect how they interact with other entities, or their representation in the world. A good example is the rocket entity, which has a .movetype == MOVETYPE_FLYMISSILE and a .velocity vector, which in combination will make it appear as moving in the world of Quake. Add a .touch function which makes the rocket explode on impact, and it's all set for action.
Note that there's nothing that stops you from coding all the behaviors of these read-by-engine fields yourself, and make them behave differently, or hacking their use in other ways, such as making an accelerating rocket by adding some extra speed to the .velocity vector in the .think function of the rocket, every frame.
The possibilities are endless! _________________ Look out for Twigboy |
|
Back to top |
|
 |
catalyst
Joined: 17 Feb 2009 Posts: 26
|
Posted: Sat Apr 25, 2009 9:31 pm Post subject: Re: Confused Newbie needs help w basic Quake C concepts |
|
|
OneManClan wrote: |
I'd look at main(), and look up the headers, and decipher what was going on that way. But here there IS no 'main' so I have no idea the order in which instructions are followed, I cant 'watch' the code execute, and so I have to 'guess' what happens and when.
|
You might look into progs.src to see the order in which the qc files are compiled if that helps (but you probably already know this). |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Sun Apr 26, 2009 4:07 am Post subject: Re: Confused Newbie needs help w basic Quake C concepts |
|
|
catalyst wrote: | OneManClan wrote: |
I'd look at main(), and look up the headers, and decipher what was going on that way. But here there IS no 'main' so I have no idea the order in which instructions are followed, I cant 'watch' the code execute, and so I have to 'guess' what happens and when.
|
You might look into progs.src to see the order in which the qc files are compiled if that helps (but you probably already know this). |
No, I didn't know this, thanks. There's a preprogs.src, and a progs.src. And I FOUND a 'main ()' somewhere, but it said it's for 'testing purposes only'.
Anyway, here's a few concepts I'm slowly grasping. I invite people to correct, or confirm my 'understanding':
1. PROGRAM FLOW
Being a newbie I've only experienced programs which are 'linear'. ie start here, do this, then do that, if that happens go here, else go there, continue, etc. Quake is NOT like this. The server / game engine perpetually waits for information about whatever random thing may happen. The 'main' exists in the server. The .dat file contains the 'extra information', and instructions are performed 'as necessary'. I suppose this is why the OO style 'entity' concept was invented. It's easier to say "heres this thing, if this happens it does this, if that happens it does that. and then let it loose in the world, and hope you have every situation covered. If not, add another condition ('if') covering any contingency. Hence all the 'if' in Quake C.
[EDIT: the following descriptions contain sloppiness and inaccuracies. I encourage other newbies to read the responses that followed for a more correct and precise information - OMC]
2. ENTITIES (global and local)
Everyone said you shouldn't make new entities because Quake can only handle so many, but as long as you declare them locally, and 'destroy them', you can use as many as you like; the memory will be released for other entities.
3. ENTITIES have 'types'
I think I may have misunderstood Entities. I got confused when descriptions of Quake C said 'Entities all share the same attributes', but they should have specified "all entities OF THE SAME TYPE" share attributes"(?) ie I make a new global entity, it has NO attributes, unless I say it's of type foo, and then (if a foo entity has been defined) it gets foo's attributes. Otoh, in defs we have the line:
.float movetype;
Since this is global, does this mean every entity has an attribute 'movetype'? I can declare
Code: |
local entity foo;
foo = spawn ();
foo.movetype = 200 // Since foo is of type 'entity', it has already been given an attribute 'float movetype' |
These are general concepts. I do have specific question, but I'll put it in a separate post.
OneManClan
ps. Is there a definitive source for the correct jargon we should all be using? ie I refer to 'attribute', but someone else can call it a 'value', 'variable', 'member' etc etc etc This gets confusing.
Last edited by OneManClan on Mon Apr 27, 2009 8:23 am; edited 1 time in total |
|
Back to top |
|
 |
catalyst
Joined: 17 Feb 2009 Posts: 26
|
Posted: Sun Apr 26, 2009 11:12 am Post subject: Re: Confused Newbie needs help w basic Quake C concepts |
|
|
I've never looked into the engine's C code, only the qc files, but as far as I understood...
all entities share the same attributes (because in the C code there must be a class Entity), but not every entity subclass (doors, elevators, the player, a trigger, a monster, a weapon...) uses all of those attributes - only the ones that were meant for them. Ie, you're not gonna use the movedir attribute for a monster and, otoh, you're not gonna use netname for a door. Well... unless you really want to.
BUT... you might also create local variables (just to calculate an entity's accuracy of shooting for example, or store other data) and they are actually also attributes.
You don't really need/want to know the workflow of the main function in the C code. Just think of all those functions in the qc code as of if statements. when you see:
Code: | void() button_touch = {... |
this means:
Code: | if the button is touched by somebody (who is able to touch), do this {... |
Also, the C code doesn't seem to care about the difference between attributes and functions. When it calls an attribute/function name, it doesn't care if the "subthread" has to calculate the value before returning it, or it just returns it instantly (yes, there also are functions that dont return values, just modify other things).
If you want to see the main's workflow, you should probably refer to the engine's C code.
Guys, correct me if I'm wrong :) |
|
Back to top |
|
 |
Lardarse

Joined: 05 Nov 2005 Posts: 243 Location: Bristol, UK
|
Posted: Sun Apr 26, 2009 1:17 pm Post subject: |
|
|
QuakeC is pretty much completely event driven. There are very few functions that have to exist within the game code (the progs.dat), and for everything else the engine just lets it get on with it.
The functions that have to exist are:
main - I have no idea when this is called by the engine, but one of Id's tools used it to build the .pak files
StartFrame - Called at the start of each frame
ClientConnect - Called when a client connected to the server
ClientDisconnect - Called when a client disconnects from the server
ClientKill - Called when a client issues the 'kill' command
PutClientInServer - Called to spawn the clients player entity
PlayerPreThink - Each client calls this every frame, before physics
PlayerPostThink - Each client calls this every frame, AFTER physics
SetNewParms - Called when a new game is started
SetChangeParms - Called just before a level change happens, for each client in turn
The function prototypes for these 10 functions are in defs.qc above the void end_sys_globals; line.
In addition, each entity that exists in the map when it loads has to have a "spawn function". This is one of the main event types that the progs.dat has to handle (although it's not classically thought of as an event). The name of the spawn function is the same as the classname of the entity, and as all maps have one guaranteed entity (worldspawn), a spawn function for it must also appear.
There are a few special events that happen, mostly relating to the functions mentioned above (StartFrame is called exactly once each frame, for example). All of the other events fall into two basic types: think events and touch events.
Think events are called by the engine, based on an entity's .think and .nextthink values. .think is a pointer to a function, and .nextthink is the absolute time (meaning a specific point in time, counting from when the map was loaded) at which the think function should be called. At some point during each frame (I'm not entirely sure what order the engine does things within a frame), the engine does this:
Code: | for each entity that exists {
if(entity.nextthink != 0 && time >= entity.nextthink) { // If it is time for the entity to do something
entity.nextthink = 0; // So that the think function will not be automatically called again next frame
self = entity; // Assigns the global pointer 'self' to the entity
// so that the function knows which entity is thinking
entity.think(); // Do the think function
}
} |
The lesson here is that the think events are like alarm clocks. You set when you want the entity to do something next, and what it to do, and it will happen at that time unless its alarm clock is changed before then. The only other thing to say here is that quite often, it is desireable to have something happen a fixed length of time in the future. This is done with a line such as self.nextthink = time + 3;
Touch events are only slightly more complicated to explain in terms of what they do, but rather more complicated to explain the backend of. In simple terms, the engine works out which entities are touching other entities, and for each pair of touching entities, calls their .touch functions, with self set to the entity whose touch function is happening and other set to the other entity. There are some exceptions, for which only one touch function (or neither) is called, but you would have to wait for an engine coder to come along and tell you what they are.
Client entities have some exceptions to the above. Instead of going through the normal think process, they have 2 functions that they do each frame, one before physics, and one after. I think that most of the exceptions mentioned above involve one of the entities being a client as well.
Everything that you want to happen within the QuakeC must happen via one of these methods, or it doesn't happen at all. |
|
Back to top |
|
 |
Lardarse

Joined: 05 Nov 2005 Posts: 243 Location: Bristol, UK
|
Posted: Tue May 05, 2009 5:34 pm Post subject: |
|
|
Did anyone ever check this? |
|
Back to top |
|
 |
OneManClan
Joined: 28 Feb 2009 Posts: 62
|
Posted: Wed May 06, 2009 6:01 am Post subject: |
|
|
Lardarse wrote: | Did anyone ever check this? |
If by ‘check this’ you mean ‘did anyone read my very helpful and detailed post’, the answer is YES. I’ve read it multiple times, and I've been referring to this thread constantly.
Detailed, intelligent explanations, with helpful metaphors, definitely help newbies like myself get a better understanding of what exactly is going on.
…still letting it all sink in.
Thanks guys,
OneManClan
ps, and it's not just theoretical either. I'm currently (successfully) coding something I couldn't have imagined doing a few weeks ago. |
|
Back to top |
|
 |
Lardarse

Joined: 05 Nov 2005 Posts: 243 Location: Bristol, UK
|
Posted: Wed May 06, 2009 7:22 pm Post subject: |
|
|
I was more hoping that the local experts would check it for any mistakes. Glad you found it useful. |
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2004 phpBB Group
|