QuakeC from Scratch tutorials - Chapter 3: And all was quiet...
Created By: Ender
eMail: ender@admdev.com
Difficulty Scale: Hard

In the last two chapters, we've managed to load a map.. and light it. But arn't things a tad too quiet? Are you feeling... uneasy? Never fear, it's time for some more Atmosphere. Let's add in some Ambient sounds.
You may wonder at my last statement.. On some maps, indeed there ARE sounds. But these sounds are created by code inside the engine, 'Ambient' sounds are something quite different. Ambient sounds are inserted by the map designer, and are usually background sounds like the computer hum at the beginning of E1M1, and the swamp/crickets at the beginning of E1M2.
Also the flickering flame sound for lights, and other sounds added for Atmosphere. These are created by Entities.
In the last chapter, you created a new QuakeC file - lights.qc - in the Entities directory. Once again, we will be creating a new file in the Entities directory, this time called Ambient.QC
You might again wish to add a header with a short description at the top of this file, such as:

| Scratch                                      Http://www.admdev.com/scratch |
| Spawns and handles the 'Ambient' (background) sound effects for Quake.     |
Once again as in the previous tutorial, we will remove the spawn functions for the Ambient sound entities from dummys.qc, as we are about to redeclare these in out new Ambient.qc file.
Remove these lines:

// Ambients
void() ambient_suck_wind        = {remove(self);};
void() ambient_flouro_buzz      = {remove(self);};
void() ambient_drip             = {remove(self);};
void() ambient_comp_hum         = {remove(self);};
void() ambient_drone            = {remove(self);};
void() ambient_thunder          = {remove(self);};
void() ambient_light_buzz       = {remove(self);};
void() ambient_swamp1           = {remove(self);};
void() ambient_swamp2           = {remove(self);};
In Ambient.qc, we will improve on some of the 'wasted' code ID used in the standard QC. In the normal Quake 1.06 QuakeC, the ambient sounds all use the same lines:

void() ambient_suck_wind =
	precache_sound ("ambience/suck1.wav");
	ambientsound (self.origin, "ambience/suck1.wav", 1, ATTN_STATIC);
However, our ambient.qc file should look like this:

void(string soundfile, float volume) doambient; // Definition from Ambient.qc

void() ambient_suck_wind        = {doambient("ambience/suck1.wav",      1);};
void() ambient_flouro_buzz      = {doambient("ambience/buzz1.wav",      1);};
void() ambient_drip             = {doambient("ambience/drip1.wav",      1);};
void() ambient_comp_hum         = {doambient("ambience/comp1.wav",      1);};
void() ambient_drone            = {doambient("ambience/drone6.wav",   0.5);};
void() ambient_thunder          = {doambient("ambience/thunder1.wav", 0.5);};
void() ambient_light_buzz       = {doambient("ambience/fl_hum1.wav",  0.5);};
void() ambient_swamp1           = {doambient("ambience/swamp1.wav",   0.5);};
void() ambient_swamp2           = {doambient("ambience/swamp2.wav",   0.5);};

void(string soundfile, float volume) doambient =
 precache_sound (soundfile);
 ambientsound (self.origin, soundfile, volume, ATTN_STATIC);
As you can see, we have put those two lines into a function, and instead call that function for all the sounds. A bit pointless? Perhaps, but it saves just those few bytes of the size of progs.dat :)

If you want, you can now compile and run Quake. Enjoy the pretty sounds! (Note: Here I will recommend you use e2m1 for testing purposes, for these tutorials. This map contains most of the elements that we will be programming in, and includes lots of enforcers, which will be first monster we code)

But something is still missing. The hum of lights, and other noises emitted by the lights are absent. Let's open up Lights.QC and add these in.
Firstly, you will again be using the 'doambient' command from Ambient.QC here.
Because, if you look at the order of the progs.src, the compiler reads the Lights.QC file before Ambient.QC, it doesn't yet know about this function. So you will have to add a 'prototype' to the beginning of Lights.QC, so the compiler knows what sort of arguments to expect.
After the title comments in Lights.QC, add the line:

void(string soundfile, float volume) doambient; // Definition from Ambient.qc
The comments in my original code for Lights.QC should help you locate the lights that have Ambient noises with them.
Such as:
void() light_fluoro =                // Light with hum ambient
At the end of this function (eg, after Light_setup) add the line:
 doambient("ambience/fl_hum1.wav", 0.5); // Spawn Ambient hum sound
Likewise for light_fluorospark add:
 doambient("ambience/buzz1.wav", 0.5);   // Spawn ambient buzz sound
 doambient("ambience/fire1.wav", 0.5);   // Spawn fire ambient sound
 doambient("ambience/fire1.wav", 0.5);   // Spawn fire ambient sound
 doambient("ambience/fire1.wav", 0.5);   // Spawn fire ambient sound
And finally, light_flame_small_white:
 doambient("ambience/fire1.wav", 0.5);   // Spawn fire ambient sound

Now, wander around, and hear some swamp, wind and computer hum. Wow! You can download the source -I- have, at this point in the Tutorials, to compare your own and make sure it's the same. If you find any problems in this tutorial, or have a comment, suggestion, complaint - Hell, ANYTHING - Drop me a E-mail: Ender@admdev.com
(Note: Remember to unzip this archive -WITH DIRECTORYS-)

[Download Source: Chapters 1, 2 & 3]