Quake DeveLS - Detpipes!

Author: Chris Hilton
Difficulty: Easy

Now for the infamous detpipes. Rather than just throw our grenades out and wait for them to blow up, we want remote control! We'll extend the life of the grenades to 60 seconds and add a new command to detonate them remotely.

First, let's change our fire_grenade() functions to throw out detpipes. Make the following change to fire_grenade() in g_weapon.c ('+' signs indicate lines added, '-' signs indicate lines removed)

	grenade->s.modelindex = gi.modelindex ("models/objects/grenade/tris.md2");
 	grenade->owner = self;
 	grenade->touch = Grenade_Touch;
-	grenade->nextthink = level.time + timer;
+	grenade->nextthink = level.time + 60;
 	grenade->think = Grenade_Explode;
 	grenade->dmg = damage;
 	grenade->dmg_radius = damage_radius;
-	grenade->classname = "grenade";
+	grenade->classname = "detpipe";
 
 	gi.linkentity (grenade);
 }

Basically, we've just extended the life of the grenades to 60 seconds and changed their classname from 'grenade' to 'detpipe'. We'll use this new classname later for our remote control detonation command.

Make the same changes to fire_grenade2(), like so:

 	grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2");
 	grenade->owner = self;
 	grenade->touch = Grenade_Touch;
-	grenade->nextthink = level.time + timer;
+	grenade->nextthink = level.time + 60;
 	grenade->think = Grenade_Explode;
 	grenade->dmg = damage;
 	grenade->dmg_radius = damage_radius;
-	grenade->classname = "grenade";
+	grenade->classname = "detpipe";
 	grenade->spawnflags = 1;
 	grenade->s.sound = gi.soundindex("weapons/hgrenc1b.wav");

Now, we'll add our remote control command. We'll need to add a 'detpipes' command to ClientCommand() in g_cmds.c.
 		Cmd_PutAway_f (ent);
 	else if (Q_stricmp (cmd, "wave") == 0)
 		Cmd_Wave_f (ent);
+
+	// CCH: new detpipes command
+	else if (Q_stricmp (cmd, "detpipes") == 0)
+		Cmd_DetPipes_f (ent);
+
 	else if (Q_stricmp (cmd, "gameversion") == 0)
 	{
 		gi.cprintf (ent, PRINT_HIGH, "%s : %s\n", GAMEVERSION, __DATE__);

We now have a new console command 'detpipes' that will call Cmd_DetPipes_f(). Here is that new function, also place in g_cmds.c, before the ClientCommand() function.
+/*
+=================
+Cmd_DetPipes_f
+CCH: new function to detonate all detpipes within 1000 units
+=================
+*/
+void Cmd_DetPipes_f (edict_t *ent)
+{
+	edict_t	*blip = NULL;
+
+	while ((blip = findradius(blip, ent->s.origin, 1000)) != NULL)
+	{
+		if (!strcmp(blip->classname, "detpipe") && blip->owner == ent)
+		{
+			blip->think = Grenade_Explode;
+			blip->nextthink = level.time + .1;
+		}
+	}
+}

When we call this function, we search all edicts within 1000 units. If it's a detpipe and we own it, we set it explode next frame.

Simple, right? If you were to compile at this point, you'd find when trying to compile g_cmds.c that it doesn't know what Grenade_Explode() function you're talking about. Grenade_Explode() was a static void function, meaning only other functions in the same file could call it. We'll rectify that by going back to the g_weapon.c file and making this small change.

 fire_grenade
 =================
 */
-static void Grenade_Explode (edict_t *ent)
+void Grenade_Explode (edict_t *ent)
 {
 	vec3_t		origin;

Okay, now it can be called outside the file, but we still need a function prototype, which we put in our g_local.h file that happens to be '#include'd in every c file. Here's the change at line 632, g_local.h:
 void fire_bullet (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread);
 void fire_shotgun (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count);
 void fire_blaster (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect);
+void Grenade_Explode (edict_t *ent);
 void fire_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius);
 void fire_grenade2 (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius);
 void fire_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage);


When using this mod, bind a key to 'cmd detpipes' and use that key to set off your detpipes remotely, but your transmitter only has a range of 1000 units! Have fun. Full source and patch file at http://www.jump.net/~dctank.

Tutorial by Chris Hilton


This site, and all content and graphics displayed on it,
are ©opyrighted to the Quake DeveLS team. All rights received.
Got a suggestion? Comment? Question? Hate mail? Send it to us!
Oh yeah, this site is best viewed in 16 Bit or higher, with the resolution on 800*600.
Thanks to Planet Quake for there great help and support with hosting.
Best viewed with Netscape 4 or IE 3