Grenade Shockwave Enhancement

 

 

philip
profile | email

posted 11-20-98 11:37 AM CT (US)
Title: Grenade Shockwave Enhancement
Difficulty: Easy
By: Philip (aka Maj.Bitch)
Email: peblair@gv.net
Date: 11-03-98
Note: Please give credit where credit is due.
======================================================
This tutorial I put together because I had mentioned in
one of my previous tutorials that I had done a shockwave
grenade but hadn't bothered to put the tutorial together.
And, I've received a few emails requesting that I post
a tutorial on it. So, here it is!

ABOUT:

With a simple toggle of the aliased key, ALL the player's
grenades (upon explosion) produce a shockwave which will
blow all players within a 500 unit radius up and backwards.
No additional damage is sustained by the re-positioned players.
All that this function does is add a shockwave of a load of
additional kick to your grenade! You should adjust the kick
amount until you are satisfied with the amount of addition
shockwave kick which is appropriate for your mod. Although,
the way I've got it set now, those unlucky bastards that don't
get killed by the grenade blast get blown up and backward and I
mean up on tops of things they'd never have been able to get
to on their own.

The shockwave enhancement remains in effect until the player
toggles the shockwave effect OFF. Also, all other grenade
features remain the same. So, if you have made any other
enhancements to you grenades they remain unaffected..

GREAT for crowd control in large open areas!!

NOTE: Want to have some fun? Turn on the Shockwave enhancement
and then go out into a large open area. Toss out one of your
enhanced grenades (don't stand too close to the blast!) and
you'll get "BLOWN AWAY!"

Okay, let's get started..

============================================================
We need to add a new variable to your gclient_s struct. So,
at the bottom of that struct, add this:

int shockwave; // 1=ON, 0=OFF

This will be used to toggle the shockwave ON/OFF

============================================================
Lets open you g_weapons.c file and add these helper routines
to the top of the file.

NOTE: I've used these helper routines in many of my previous
tutorials so you may already have them someplace in your source.
If you already do have them, then you don't need them anymore.
Your compiler should warn you that you've already got these
functions previously defined..

//======================================================
// True if Ent is valid, has client, and edict_t inuse.
//======================================================
qboolean G_EntExists(edict_t *ent) {
return ((ent) && (ent->client) && (ent->inuse));
}

//======================================================
// True if ent is not DEAD or DEAD or DEAD (and BURIED!)
//======================================================
qboolean G_ClientNotDead(edict_t *ent) {
qboolean buried=true;
qboolean b1=ent->client->ps.pmove.pm_type!=PM_DEAD;
qboolean b2=ent->deadflag != DEAD_DEAD;
qboolean b3=ent->health > 0;
return (b3||b2||b1)&&(buried);
}

//======================================================
// True if ent is not DEAD and not just did a Respawn.
//======================================================
qboolean G_ClientInGame(edict_t *ent) {
if (!G_EntExists(ent)) return false;
if (!G_ClientNotDead(ent)) return false;
return (ent->client->respawn_time + 5.0 < level.time);
}

============================================================
============================================================
============================================================

============================================================

Okay, go into InitClientPersistant() function in your p_client.c
file and add this line near the bottom:

client->shockwave=0; // default to OFF.

This will set the default to OFF each time the player enters
the game..

============================================================

Open up your g_cmds.c file and go near the bottom of your
ClientCommand() function and add the following as shown
by example..

---------- IF-ELSE STATEMENTS --------
else if (Q_stricmp(cmd, "baton") == 0 )
Cmd_Baton_f(ent);
else if (Q_stricmp(cmd, "teleport") == 0)
Cmd_Teleport_f(ent);
----------- ADD THESE LINES ------
else if (Q_stricmp(cmd, "shockwave") == 0) {
ent->client->shockwave=abs(ent->client->shockwave-1);
gi.centerprintf(ent,"GRENADES SHOCKWAVE %s!\n",ent->client->shockwave<1?"DISABLED":_x0022_ENHANCED_x0022__x0029__x003b__x007d_>
else if .....

This will toggle the shockwave enhancement on/off with a
single stroke of the player's aliased key.

============================================================
Open up your g_weapons.c file and find your grenade_explode()
function and add the lines as shown..

void Grenade_Explode(edict_t *ent) {

--------- FIND YOUR T_RADIUSDAMAGE() LINE -------------------

T_RadiusDamage(ent, ent->owner, ent->dmg, ent->enemy, ent->dmg_radius, mod);

------------- ADD THESE LINES HERE ----------------------

// Generate Shockwave only if activated by real Player..
if ((G_EntExists(ent->owner)) && (ent->owner->client->shockwave))
ShockWave(ent);

============================================================

Lastly, in your g_weapons.c file, at a point just above the
grenade_explode() function, add this new function:

//======================================================
// True if start and end are within radius distance.
//======================================================
qboolean G_Within_Radius(vec3_t start, vec3_t end, float rad) {
vec3_t eorg={0,0,0};
int j;
for (j=0; j < 3; j++)
eorg[j]=abs(start[j]-end[j]);
return (VectorLength(eorg) < rad);
}

//======================================================
void ShockWave(edict_t *grenade) {
edict_t *ent=NULL;
trace_t tr;
vec3_t zvec=(0,0,0);
vec3_t start,end;
vec3_t kvelocity,dir;
float radius=500;
int i;

// Blow backward ALL ents within 500 units...
for(i=0;i < game.maxclients;i++) {
ent=g_edicts+i+1;
if (!G_ClientInGame(ent)) continue;
if (ent==grenade) continue;
if (!G_Within_Radius(grenade->s.origin, ent->s.origin, radius)) continue;
VectorCopy(grenade->s.origin, start);
VectorCopy(ent->s.origin, end);
tr=gi.trace(start, ent->mins, ent->maxs, end, NULL, MASK_SHOT);
// subtract ent's origin from grenade's origin to get direction..
VectorSubtract(tr.endpos, start, dir);
VectorScale(dir, 10, kvelocity);
kvelocity[2] += random()*10; // some upward component
// Scale new velocity into ent's velocity!
VectorMA(zvec, 10, kvelocity, ent->velocity);
} // end for
}

============================================================
Be sure to add the following to your Autoexec.cfg file as
shown by example..

bind s "shockwave"

That's it!!

BLOW THE BASTARDS OUT OF YOUR WAY!!

Have Fun!!

Philip