QuakeC Lessons for the Experienced Newb
Moderator: InsideQC Admins
15 posts
• Page 1 of 1
QuakeC Lessons for the Experienced Newb
Wherein I prostrate my shamefully relevant ignorance of all things QuakeC to ask completely random questions about the code I see, and what is going on. It may be grandiose, it may be a tiny detail, but the hope is that in illuminating myself, it may form a small archive of random tidbits for other newbs, my nescient brethren.
...and all around me was the chaos of battle and the reek of running blood.... and for the first time in my life I knew true happiness.
-

scar3crow - InsideQC Staff
- Posts: 1054
- Joined: Tue Jan 18, 2005 8:54 pm
- Location: Alabama
What is going on here?
What is CHAN_VOICE explicitly and what are the other CHANs?
What is normal attenuation, is there super attenuation? Paranormal attenuation?
What is the 1 being passed for?
- Code: Select all
sound (self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM);
What is CHAN_VOICE explicitly and what are the other CHANs?
What is normal attenuation, is there super attenuation? Paranormal attenuation?
What is the 1 being passed for?
...and all around me was the chaos of battle and the reek of running blood.... and for the first time in my life I knew true happiness.
-

scar3crow - InsideQC Staff
- Posts: 1054
- Joined: Tue Jan 18, 2005 8:54 pm
- Location: Alabama
- Code: Select all
ThrowHead ("progs/h_knight.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
...and all around me was the chaos of battle and the reek of running blood.... and for the first time in my life I knew true happiness.
-

scar3crow - InsideQC Staff
- Posts: 1054
- Joined: Tue Jan 18, 2005 8:54 pm
- Location: Alabama
scar3crow wrote:What is going on here?Why the self?
- Code: Select all
sound (self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM);
What is CHAN_VOICE explicitly and what are the other CHANs?
What is normal attenuation, is there super attenuation? Paranormal attenuation?
What is the 1 being passed for?
1. so the sound emits from the knight's ass, rather than the world or his attacker.
2. so his 'ouch' noises can interrupt the growls and stuff he makes, rather than the noise of his sword. localized channels is important
3. yes. the normal attenuation is normal. The lower the attenuation value the farther it goes (ATTN_NONE (0) is the whole level). Player's death uses ATTN_NONE. Why? hell if i know, i change that to ATTN_NORM in everything I do
4. Volume. from 0 to 1. This is not the same as attenuation.
scar3crow wrote:] Why the self.health? Why is it on each line and how would it be relevant to gibs, and does it matter between ThrowGib and ThrowHead that they both mention it?
so when the more overkilled player is gibbed, the gibs fly farther regarding the negative health value of the player. it makes quad rockets very fun
i should not be here
- leileilol
- Posts: 2783
- Joined: Fri Oct 15, 2004 3:23 am
I very much approve of this thread. Mainly as I've been doing this for years, but have massive gaps in my knowledge. The two examples so far being cases in point...
-

ajay - Posts: 559
- Joined: Fri Oct 29, 2004 6:44 am
- Location: Swindon, UK
scar3crow wrote:Why the self.health? Why is it on each line and how would it be relevant to gibs, and does it matter between ThrowGib and ThrowHead that they both mention it?
- Code: Select all
ThrowHead ("progs/h_knight.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
self.health is passed into the ThrowGib (as the parameter "dm") code to determine the velocity with which to throw the gibs. So say after damaging the entity's health is around -40, that's the minimum most characters have for gibbing.
The function VelocityForDamage in player.qc converts the remaining (negative) health of the character into a velocity. At -50 and above the random vector will be scaled by 0.7 making the gibs not go as far. The comment says "level 1". Below -50 and above -200 the random vector will be scaled by 2, making the gibs fly twice as far. Beyond that, which is probably only quad rocket/ telefrag damage, the gibs will go 10 times as far.
Function parameters need to be repeated for each call to the function. There's no way to omit parameters in QuakeC and ThrowGib / ThrowHead have no way of knowing what the previous passed in variable was. ThrowHead is basically a clone of ThrowGib with one important difference, instead of spawning a new bouncing entity, it converts self into something that is essentially a gib. So that when you gib a character, they literally become a head and toss out a handful of gibs. The reason for this is so that anything pointing at that particular entity doesn't break. It will still be pointing at the head.
A helpful thing to do when you see some identifier you don't understand is to search the code for it and find its definition. So in this case searching would have found the ThrowGib function in player.qc, and looking at what it does with the "dm" variable passed in would have led you down to VelocityForDamage, searching again for that function you would have found its definition also in player.qc, and reading again what it does with dm would lead you to the above information.
There's no guide for QuakeC. Everything anyone outside of id has ever learned of this language has been accomplished by searching and reading the code.
- FrikaC
- Site Admin
- Posts: 1026
- Joined: Fri Oct 08, 2004 11:19 pm
FrikaC wrote:There's no guide for QuakeC. Everything anyone outside of id has ever learned of this language has been accomplished by searching and reading the code.
... and fortunately all those people are gathering at inside3D.com
Happy to help others in need.
Thank you for your detailed description leileilol & FrikaC.
I learned a lot from it.
Last thing I dont understand is, why is the head-gib always lying/positioned on the floor like it is modelled/visible in QME. (example: soldiers head is looking upwards)
And all 3 other gibs are lying in a random position/condition.
I couldnt find the code that is responsible for this.
Kind regards,
Seven
- Seven
- Posts: 301
- Joined: Sat Oct 06, 2007 8:49 pm
- Location: Germany
Last thing I dont understand is, why is the head-gib always lying/positioned on the floor like it is modelled/visible in QME. (example: soldiers head is looking upwards)
And all 3 other gibs are lying in a random position/condition.
I couldnt find the code that is responsible for this.
There's a few other minor differences between ThrowHead and ThrowGib one is this:
ThrowGib:
- Code: Select all
new.avelocity_x = random()*600;
new.avelocity_y = random()*600;
new.avelocity_z = random()*600;
ThrowHead:
- Code: Select all
self.avelocity = crandom() * '0 600 0';
The ThrowGib version sets the avelocity (angular velocity) on all three elements independently: pitch (_x), yaw (_y) and roll (_z). The ThrowHead code multiplies a crandom call (which is a random number between -1 and 1) with '0 600 0'. Where the ThrowGib code will use a new random number for each component, this code only uses one random number and only applied to the _y component.
Zero times any number equals zero. So the avelocity_x and avelocity_z are set to zero, meaning that the head will never pitch or roll, only spin around the yaw.
- FrikaC
- Site Admin
- Posts: 1026
- Joined: Fri Oct 08, 2004 11:19 pm
Like FrikaC alluded to, knowing how to learn things on your own is something you'll really need if you're going to make it in software development. You'd have a hard time looking for any (*decent*) dev who isn't an autodidact of some level. Regarding builtins, two good starting points for finding more info would be the prvm_*.h files in the engine source (plus protocol.h for EF_* bits and others) and the archive of the old Quake Wiki included with the GUI version of FrikQCC 2.7
Two things I want to note is that each sound channel isn't reserved for anything in particular - nothing will bite your head off if you play a weapon sound on CHAN_BODY, it just uses up that channel 'slot' for the duration of the sound - and that CHAN_AUTO (0) will take up the first free channel slot for that entity it can find every time you use it. I can't remember if CHAN_AUTO looks for slots incrementing from 1 or decrementing from the maximum (7 in NQ, DP's is probably higher), so you'd have to find out on your own. :)
Also, regarding the entity parameter you need to keep in mind that you need to spawn a (temporary) entity to play a sound in the first place, you can't just play the sound at a specific origin vector. So if you just want to play a sound at vector xyz (like a music loop played at two opposite points in the level for a stereo effect) you'll need to spawn *something* at that point and pass it along as the sound origin entity - though nothing will stop you from removing it on the next server frame. Also note that DP will make the sound follow whatever entity you pass it to, which allows you to do things like playing a rocket motor loop on rockets in order to emulate the Q3 rocket flyby sound effect.
It's only really important in teamplay or FFA games, as it serves as a feedback cue to help intuit where your teammates and other players are dying.
scar3crow wrote:what are the other CHANs?
Two things I want to note is that each sound channel isn't reserved for anything in particular - nothing will bite your head off if you play a weapon sound on CHAN_BODY, it just uses up that channel 'slot' for the duration of the sound - and that CHAN_AUTO (0) will take up the first free channel slot for that entity it can find every time you use it. I can't remember if CHAN_AUTO looks for slots incrementing from 1 or decrementing from the maximum (7 in NQ, DP's is probably higher), so you'd have to find out on your own. :)
Also, regarding the entity parameter you need to keep in mind that you need to spawn a (temporary) entity to play a sound in the first place, you can't just play the sound at a specific origin vector. So if you just want to play a sound at vector xyz (like a music loop played at two opposite points in the level for a stereo effect) you'll need to spawn *something* at that point and pass it along as the sound origin entity - though nothing will stop you from removing it on the next server frame. Also note that DP will make the sound follow whatever entity you pass it to, which allows you to do things like playing a rocket motor loop on rockets in order to emulate the Q3 rocket flyby sound effect.
leileilol wrote:Player's death uses ATTN_NONE. Why?
It's only really important in teamplay or FFA games, as it serves as a feedback cue to help intuit where your teammates and other players are dying.
-

Supa - Posts: 164
- Joined: Tue Oct 26, 2004 8:10 am
scar3crow wrote:Why the self.health? Why is it on each line and how would it be relevant to gibs, and does it matter between ThrowGib and ThrowHead that they both mention it?
- Code: Select all
ThrowHead ("progs/h_knight.mdl", self.health);
ThrowGib ("progs/gib1.mdl", self.health);
ThrowGib ("progs/gib2.mdl", self.health);
ThrowGib ("progs/gib3.mdl", self.health);
Something that hasn't been mentioned is self becomes the ThrowHead, in this case the knight becomes h_knight.mdl, where as the ThrowGib are new entities that are spawned like when firing a rocket.
- silverjoel
- Posts: 51
- Joined: Thu Sep 30, 2010 6:46 am
silverjoel wrote:Something that hasn't been mentioned is self becomes the ThrowHead, in this case the knight becomes h_knight.mdl, where as the ThrowGib are new entities that are spawned like when firing a rocket.
I kinda did when I said
ThrowHead is basically a clone of ThrowGib with one important difference, instead of spawning a new bouncing entity, it converts self into something that is essentially a gib.
But yeah, it's an important thing to note and I'm glad you further called it out.
- FrikaC
- Site Admin
- Posts: 1026
- Joined: Fri Oct 08, 2004 11:19 pm
I for one welcome our elder QuakeC overlords. 
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC
(LordHavoc)
-

frag.machine - Posts: 2090
- Joined: Sat Nov 25, 2006 1:49 pm
Supa wrote:leileilol wrote:Player's death uses ATTN_NONE. Why?
It's only really important in teamplay or FFA games, as it serves as a feedback cue to help intuit where your teammates and other players are dying.
In some engines such as Darkplaces that remove the panning out of ATTN_NONE for music use, this becomes less useful.
i should not be here
- leileilol
- Posts: 2783
- Joined: Fri Oct 15, 2004 3:23 am
scar3crow wrote:What is going on here?Why the self?
- Code: Select all
sound (self, CHAN_VOICE, "knight/kdeath.wav", 1, ATTN_NORM);
What is CHAN_VOICE explicitly and what are the other CHANs?
What is normal attenuation, is there super attenuation? Paranormal attenuation?
What is the 1 being passed for?
Taken from defs.qc...
- Code: Select all
// sound channels
// channel 0 never willingly overrides
// other channels (1-7) allways override a playing sound on that channel
float CHAN_AUTO = 0;
float CHAN_WEAPON = 1;
float CHAN_VOICE = 2;
float CHAN_ITEM = 3;
float CHAN_BODY = 4;
Here is also the other attenuations, also taken from defs.qc...
- Code: Select all
float ATTN_NONE = 0;
float ATTN_NORM = 1;
float ATTN_IDLE = 2;
float ATTN_STATIC = 3;
-

Mexicouger - Posts: 514
- Joined: Sat May 01, 2010 10:12 pm
From a sound guy's perspective, the channels are like a crude mixing desk with a really poor interface.
Imagine adding constant footsteps for example, their sound will need to play on a different channel from the gunfire/grunting etc so they are not cut out during combat.
Not to mention stuff like taunts and cheers and heartbeats.
Imagine adding constant footsteps for example, their sound will need to play on a different channel from the gunfire/grunting etc so they are not cut out during combat.
Not to mention stuff like taunts and cheers and heartbeats.
-

goldenboy - Posts: 924
- Joined: Fri Sep 05, 2008 11:04 pm
- Location: Kiel
15 posts
• Page 1 of 1
Who is online
Users browsing this forum: No registered users and 1 guest