
Quake DeveLS - Proximity mines
Author: Chris Hilton
Difficulty: Easy
Let's turn those boring
old grenades into proximity mines. For the most part this just requires a new
think function for the grenade that checks for passing targets and blows up
appropriately. However, we also want the proximity grenades to have a limited
life span. This is how we'll modify the fire_grenade() function 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->think = Grenade_Explode;++ // CCH: use our proximity think instead+ grenade->nextthink = level.time + .1;+ grenade->think = proxim_think;+ grenade->delay = level.time + 60;+ grenade->dmg = damage; grenade->dmg_radius = damage_radius; grenade->classname = "grenade";
We've
replaced the grenade's original think function to explode when the timer is
reached to call a new function proxim_think() in .1 seconds. Also, we've set
ent->delay to 60 seconds in the future to represent the end of the grenade's
lifespan and we'll check that value in our proxim_think() function for when to
explode the grenade. The delay field of the edict_t type is normally only used
by monster ai functions, not by grenades, so it's okay to grab it for our usage
here.
Also, we'll make similar
changes to the fire_grenade2() function.
grenade->s.modelindex = gi.modelindex ("models/objects/grenade2/tris.md2"); grenade->owner = self; grenade->touch = Grenade_Touch;- grenade->nextthink = level.time + timer;- grenade->think = Grenade_Explode;++ // CCH: use our proximity think instead+ grenade->nextthink = level.time + .1;+ grenade->think = proxim_think;+ grenade->delay = level.time + 60;+ grenade->dmg = damage; grenade->dmg_radius = damage_radius; grenade->classname = "grenade";
Incidentally,
fire_grenade() is called when firing the grenade launcher, fire_grenade2() is
called when throwing a grenade by hand.
Now we just need the new
think function, which I put before the fire_grenade functions in g_weapon.c
+// CCH: New think function for proximity grenades+static void proxim_think (edict_t *ent)+{+ edict_t *blip = NULL;++ if (level.time > ent->delay)+ {+ Grenade_Explode(ent);+ return;+ }+ + ent->think = proxim_think;+ while ((blip = findradius(blip, ent->s.origin, 100)) != NULL)+ {+ if (!(blip->svflags & SVF_MONSTER) && !blip->client)+ continue;+ if (blip == ent->owner)+ continue;+ if (!blip->takedamage)+ continue;+ if (blip->health <= 0)+ continue;+ if (!visible(ent, blip))+ continue;+ ent->think = Grenade_Explode;+ break;+ }++ ent->nextthink = level.time + .1;+}
First, we
check the delay to see if we've reached the end of our lifespan and should blow
up immediately. Then we check all edicts within 100 units and see if there is a
valid target. If there is, we stop searching and set ourselves to explode next
think. Valid targets are monsters and players (not our owner) that can take
damage, have health to lose, and are visible to us.
That's it. Have fun with
your new toy. 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, |