I am not actually posting this to attribute to a finished work. Yesterday I posted a tutorial oon how to disassemble qc to create custom ent definitions. I used my triggerable weather as example code. In that, I realized that some code written by others was not actually necessary. I also realized that I left unfinished ideas in my code AND I had 2 mistakes (mine).

I removed the unnecessary/unfinished code and corrected my mistakes. I also commented the code. If you start with the bottomest function and then cascade that scope up through all of the above functions, it becomes really clear how everything works. I also rewrote the ent definition to reflect the changes.

All that being said, I am posting this so others can learn stuff. These two codes hold a lot of different examples within them, like:

How to create a custom trigger
How to check and set variables
How to derive an ent definition from QC
How to set/create/use spawnflags

and I'm sure more. If you are using my modified np++ you will have a very easy time reading the code.


For those of you that actually want to use this code: First of all you will need DPExtensions.qc compiled into your progs.dat (as well as my code). You will also have to add my ent definition to your entities.ent. From there you would open up your map in radiant and draw a brush where you want weather to be. Then right click it (while it is selected) and select func/func_weather. From here you have options.

1) do nothing else and by default it will automatically rain
2) select the rain or snow spawnflag and by default it will automatically create that
3) give the weather a targetname, create a trigger and assign the targetname of the weather to the target of the trigger. The weather will start as off by default, but when you touch your trigger it will turn on. Depending on the type of trigger or how many triggers that you use, you can turn the weather on and off. Whatever the forecast is, it will be the opposite when you hit the trigger.

save as weather.qc, add to progs.src at the very bottom, compile
/*__________>  		TRIGGERABLE WEATHER - BUILD 20130419		 <__________*/
/*      		  modified from Lord Havoc's rain and snow       			*/
/*               Seven - sounds, thinks             						*/
/*__________>    Gypsy - activator, modified func_weather     	 <__________*/

float SPAWN_RAIN = 1;
float SPAWN_SNOW = 2;

float CLEAR = 0;
float FORECAST = 1;

.float weather;


void() regenton = 
{	if (random()> 0.94) 	// make rain sounds
		precache_sound ("ambience/rain.wav");		
		sound (self, CHAN_VOICE, "ambience/rain.wav", 1, ATTN_NORM); 

void() blitzton =  
{	if (random()> 0.997)	// maybe it will thunder
		precache_sound ("ambience/thunderrain.wav");	
		sound (self, CHAN_WEAPON, "ambience/thunderrain.wav", 1, ATTN_NORM);


void() snow_think =
{	self.nextthink = time + 0.1;				//just keep thinking about yourself, and every time you do...
	te_particlesnow(self.absmin, self.absmax, self.dest, self.count, self.cnt);		//...keep doing this (DP_EXTENSIONS)

void() rain_think =
{	self.nextthink = time + 0.1;				//just keep thinking about yourself, and every time you do...
	te_particlerain(self.absmin, self.absmax, self.dest, self.count, self.cnt);		//...keep doing this (DP_EXTENSIONS)
	blitzton();	//and this
	regenton();	//and this


void() weather_use =
{	if(!self.weather || self.weather == CLEAR)		//if the weather is clear
	{	self.weather = FORECAST;					//it's not anymore
		if (self.spawnflags & SPAWN_RAIN)			//is it raining
		{	precache_sound ("ambience/thunderrain.wav");
			sound (self, CHAN_WEAPON, "ambience/thunderrain.wav", 1, ATTN_NORM);
			self.think = rain_think;
		else if (self.spawnflags & SPAWN_SNOW)		//or snowing
		{	self.think = snow_think;
		self.nextthink = time + 0.1;				//whatever it is, do it in a 10th of a second
		return;										//stop this script here, before it can turn itself off (code below)
	//this applies to using triggers, as that is the only way this function could be called a second time
	self.weather = CLEAR;							//if the weather isn't clear, the script will get this far and clear it up
	self.think = SUB_Null;							//stop thinking about snow/rain

                 Mother Nature
void() func_weather =
{	//define self
	self.angles = '0 0 0';		//probably unnecessary
	self.velocity = '0 0 0';	//probably unnecessary
	self.movetype = MOVETYPE_NONE;
	self.solid = SOLID_NOT;
	//define the model
	setmodel(self, self.model);
	setorigin(self, self.origin);
	setsize(self, self.mins, self.maxs);
	self.model = ""; //????
	//correct missing flag error
	if( !( self.spawnflags & SPAWN_RAIN ) && !( self.spawnflags & SPAWN_SNOW ) ) 	//if niether flag is set
		self.spawnflags = self.spawnflags + ( self.spawnflags & SPAWN_RAIN );		//default to rain
	//set defaults if values are not already set
	if ( (!self.dest) && ( self.spawnflags & SPAWN_RAIN ) )
		self.dest = '0 0 -700';
	else if ( (!self.dest) && ( self.spawnflags & SPAWN_SNOW ) )
		self.dest = '0 0 -100';
	if (!self.cnt)
		self.cnt = 12;
	if (!self.count)
		self.count = ( self.absmax_x - self.absmin_x ) * ( self.absmax_y - self.absmin_y ) / 8192;
	if (self.count < 1)
	{	remove(self);
	self.count = ceil(self.count * 0.1);  //adjust
	if(!self.targetname)			//if self cannot be targeted, turn on weather
	else							//otherwise wait til a trigger has been tripped
		self.use = weather_use;
Add to q1.game/id1/entities.ent
<group name="func_weather" color="0.5 0.0 0.5">
	<targetname key="targetname" name="targetname">Triggering this name will turn the weather on/off. Including a targetname starts weather as off.</targetname>
	<flag key="SPAWN_RAIN" name="rain" bit="0">Spawns rain</flag>
	<flag key="SPAWN_SNOW" name="snow" bit="1">Spawns snow</flag>
	<real3 key="dest" name="fall speed">fallspeed 0 0 -700 is default in the QC</real3>
	<integer key="count" name="rain density">rain density</integer>
	<integer key="cnt" name="color(0-255)">alpha to white by 15, higher numbers bring colors - 12 is default in the QC</integer>
EDIT: I just realized that targetname isn't doing anything in my ent definition. No targetname field is showing up in the radiant entity inspector. I copied and pasted that code from somewhere else in the ent when it was in its default state. In other words, there is no mistake, it simply does not work. This is slightly annoying at the worst. All you have to do is manually type "targetname" in the key field and "whateverNameYouWant" in the value field, within the radiant entity inspector, and then press enter. I guess you can also remove the <targetname> line from my .ent definition.