Author: Author Unkown ! (dwm ?)
This is a simple little hack which modifies the grenade and rocket explosions to look a little
more like grenade and rocket explosions and a little less like wads of flash paper going *poof*.
A modified sound is included which actually sounds about right,
although it is not nearly loud enough.
[Get the wav and source files here]
No substantive changes have been made. Damage, etc., are as originally programmed.
Just for kicks, the new explosions will also move items around a bit. Nothing fancy.
Header file : dwm.h
This function simply tells an exploding grenade to call other functions
to 1) make debris 2) deal damage 3) shock players 4) shock items 5) become
a new (improved, with 15% less fat!) explostion.
Exactly ditto for the rocket launcher, although in a slightly different
context. 'Normal stuff' that the rocket does anyway (like disappearing
if it touches the sky) from the original id function is at the very
top of this function.
Same sort of modification, barrels now shock players and other items
and spew out shrapnel.
Now the fun begins !
Excellent ! This function knocks items around within a certain radius.
Note that the mass of the item is used in the calculations, so lighter
items are thrown further than heavy ones !
These simply throw around bits of metal with different effects. Also, they
differ in 'persistence' - how long the item stays in the game. Items
which disappear after 1 second (rather than 6) are more friendly for
a heavily laden server !
Throws out 3 bits of shrapnel. Simple
Plays a new sound (mk33.wav)
Nice! very useful utility function here ! Great for quickly determining
line-of-sight.
This site, and all content and graphics displayed on it,
Difficulty: Medium but LONG
Source file : dwm.c
// dwm.h
/*-------------------------------------------------
include this file as the last line of local.h
and change the original function names so that
the replacement ones are used instead
--------------------------------------------------*/
// g_weapon.c replacements
void Grenade_Explode (edict_t *ent);
void rocket_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
// g_misc.c replacements
void barrel_explode (edict_t *self);
// g_target.c replacements
void target_explosion_explode (edict_t *self);
// new functions
void T_ShockWave (edict_t *inflictor, float damage, float radius);
void T_ShockItems (edict_t *inflictor);
void ThrowShrapnel (edict_t *self, char *modelname, float speed, vec3_t origin);
void ThrowShrapnel2 (edict_t *self, char *modelname, float speed, vec3_t origin);
void ThrowShrapnel3 (edict_t *self, char *modelname, float speed, vec3_t origin);
void ThrowShrapnel4 (edict_t *self, char *modelname, float speed, vec3_t origin);
void make_debris (edict_t *ent);
void BigBang (edict_t *ent);
qboolean isvisible (edict_t *self, edict_t *other);
SumFuka's Summary
// dwm.c
#include "g_local.h"
/*
=================
Grenade_Explode
New grenade explosion. Creates ~12 new entities (9 debris, 1 flash, 1 sound + 1 sound per client).
(Id barrel explosion creates 15)
=================
*/
static void Grenade_Explode (edict_t *ent)
{
// make some debris
make_debris (ent);
// do blast damage
T_RadiusDamage(ent, ent->owner, ent->dmg, NULL, ent->dmg_radius);
// shake view
T_ShockWave(ent, 255, 1024);
// let blast move items
T_ShockItems(ent);
// explode and destroy grenade
BecomeNewExplosion (ent);
}
/*
=================
rocket_touch
Grenade explosion + a few glowing trails. Creates ~15 new entities.
=================
*/
void rocket_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
int i;
vec3_t org;
float spd;
vec3_t origin;
// can't be hit by own rocket
if (other == ent->owner)
return;
// can't hit sky
if (surf && (surf->flags & SURF_SKY))
{
G_FreeEdict (ent);
return;
}
// noise if hits other player
if (ent->owner->client)
PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
// calculate position for the explosion entity
VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
// impact damage
if (other->takedamage)
{
T_Damage (other, ent, ent->owner, ent->velocity, ent->s.origin, plane->normal, ent->dmg, 0, 0);
}
// make some glowing shrapnel
spd = 15.0 * ent->dmg / 200;
for (i = 0; i < 3; i++)
{
org[0] = ent->s.origin[0] + crandom() * ent->size[0];
org[1] = ent->s.origin[1] + crandom() * ent->size[1];
org[2] = ent->s.origin[2] + crandom() * ent->size[2];
ThrowShrapnel4 (ent, "models/objects/debris2/tris.md2", spd, org);
}
make_debris (ent);
T_RadiusDamage(ent, ent->owner, ent->radius_dmg, other, ent->dmg_radius);
T_ShockItems(ent);
T_ShockWave(ent, 255, 1024);
BecomeNewExplosion (ent);
}
/*
=================
make_debris
=================
*/
void make_debris (edict_t *ent)
{
int i;
vec3_t org;
vec3_t origin;
float spd;
// calculate position for the explosion entity
VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
// make a few big chunks
spd = .5 * (float)ent->dmg / 200.0;
org[0] = ent->s.origin[0] + crandom() * ent->size[0];
org[1] = ent->s.origin[1] + crandom() * ent->size[1];
org[2] = ent->s.origin[2] + crandom() * ent->size[2];
ThrowShrapnel (ent, "models/objects/debris1/tris.md2", spd, org);
spd = 1.5 * (float)ent->dmg / 200.0;
VectorCopy (ent->absmin, org);
ThrowShrapnel (ent, "models/objects/debris2/tris.md2", spd, org);
spd = 1.5 * (float)ent->dmg / 200.0;
VectorCopy (ent->absmin, org);
ThrowShrapnel (ent, "models/objects/debris3/tris.md2", spd, org);
}
/*
============
T_ShockWave
Knocks view around a bit. Based on T_RadiusDamage.
============
*/
void T_ShockWave (edict_t *inflictor, float damage, float radius)
{
float points;
edict_t *ent = NULL;
vec3_t v;
vec3_t dir;
float SHOCK_TIME = 0.1;
while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL)
{
if (!ent->takedamage)
continue;
if (!ent->client)
continue;
VectorAdd (ent->mins, ent->maxs, v);
VectorMA (ent->s.origin, 0.5, v, v);
VectorSubtract (inflictor->s.origin, v, v);
points = .5*(damage - 0.5 * VectorLength (v));
if (points < .5)
points = .5;
if (points > 10)
points = 10;
if (points > 0)
{
VectorSubtract (ent->s.origin, inflictor->s.origin, dir);
ent->client->v_dmg_pitch = -points;
ent->client->v_dmg_roll = 0;
ent->client->v_dmg_time = level.time + SHOCK_TIME;
ent->client->kick_origin[2] = -points*4;
}
}
}
/*
============
T_ShockItems
Lets explosions move items. Based on T_RadiusDamage.
TODO: Reorient items after coming to rest?
============
*/
void T_ShockItems (edict_t *inflictor)
{
float points;
edict_t *ent = NULL;
vec3_t v;
vec3_t dir;
vec3_t kvel;
float mass;
float radius=255;
float damage=100;
while ((ent = findradius(ent, inflictor->s.origin, radius)) != NULL)
{
if (ent->item)
{
VectorAdd (ent->mins, ent->maxs, v);
VectorMA (ent->s.origin, 0.5, v, v);
VectorSubtract (inflictor->s.origin, v, v);
points = damage - 0.5 * VectorLength (v);
if (ent->mass < 25)
mass = 25;
else
mass = ent->mass;
if (points > 0)
{
VectorSubtract (ent->s.origin, inflictor->s.origin, dir);
ent->movetype = MOVETYPE_BOUNCE;
// any problem w/leaving this changed?
VectorScale (dir, 3.0 * (float)points / mass, kvel);
VectorAdd (ent->velocity, kvel, ent->velocity);
VectorAdd (ent->avelocity, 1.5*kvel, ent->avelocity);
//TODO: check groundentity & lower s.origin to keep objects from sticking to floor?
// ERRR... should we be calling linkentity here?
ent->velocity[2]+=10;
}
}
}
}
/*
=================
BecomeNewExplosion
=================
*/
void BecomeNewExplosion (edict_t *ent)
{
edict_t *chunk;
int i;
vec3_t org;
vec3_t origin;
float spd;
// calculate position for the explosion entity
VectorMA (ent->s.origin, -0.02, ent->velocity, origin);
// make smoke trails
spd = 7.0 * ent->dmg / 200;
for (i = 0; i < 2; i++)
{
org[0] = ent->s.origin[0] + crandom() * ent->size[0];
org[1] = ent->s.origin[1] + crandom() * ent->size[1];
org[2] = ent->s.origin[2] + crandom() * ent->size[2];
ThrowShrapnel3 (ent, "models/objects/debris2/tris.md2", spd, org);
}
spd = 10.0 * ent->dmg / 200;
for (i = 0; i < 2; i++)
{
org[0] = ent->s.origin[0]; // + crandom() * ent->size[0];
org[1] = ent->s.origin[1]; // + crandom() * ent->size[1];
org[2] = ent->s.origin[2]; // + crandom() * ent->size[2];
ThrowShrapnel2 (ent, "models/objects/debris2/tris.md2", spd, org);
}
spd = 15.0 * ent->dmg / 200;
for (i = 0; i < 2; i++)
{
org[0] = ent->s.origin[0] + crandom() * ent->size[0];
org[1] = ent->s.origin[1] + crandom() * ent->size[1];
org[2] = ent->s.origin[2] + crandom() * ent->size[2];
ThrowShrapnel3 (ent, "models/objects/debris2/tris.md2", spd, org);
}
// send flash & bang
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
// any way to get a mz flash without hearing the weapon?
gi.WriteByte (MZ_CHAINGUN2);
gi.multicast (ent->s.origin, MULTICAST_PVS);
// any other way to make this loud enough?
BigBang (ent);
// destroy object
G_FreeEdict (ent);
}
/*
=============
isvisible
This is the ai.c visible function
=============
*/
qboolean isvisible (edict_t *self, edict_t *other)
{
vec3_t spot1;
vec3_t spot2;
trace_t trace;
VectorCopy (self->s.origin, spot1);
spot1[2] += self->viewheight;
VectorCopy (other->s.origin, spot2);
spot2[2] += other->viewheight;
trace = gi.trace (spot1, vec3_origin, vec3_origin, spot2, self, MASK_OPAQUE);
if (trace.fraction == 1.0)
return true;
return false;
}
/*
=================
BigBang
Loud bang.
=================
*/
void BigBang (edict_t *ent)
{
int i;
edict_t *ear;
float radius=1024;
vec3_t d;
gi.sound (ent, CHAN_ITEM, gi.soundindex ("weapons/mk33.wav"), 1, ATTN_NORM, 0);
// Unfortunately, this sounds weak, so check each client to see if
// it is within the blast radius or in line of sight; if so,
// send each client a loud ATTN_STATIC bang
ear = &g_edicts[0];
for (i=0 ; i
Ok that's it... go frag your friends and have some fun ! Crank the damage up
on the rockets and grenades if you like, to suit the new atmosphere !
This function finds all entities within a certain radius. If the entity
is not a player (ent->client is NULL) then nothing happens. If the
entity IS a player, they are 'shocked'... less at further distances.
Note the variables used to kick the player's view.
void ThrowShrapnel2 (edict_t *self, char *modelname, float speed, vec3_t origin);
void ThrowShrapnel3 (edict_t *self, char *modelname, float speed, vec3_t origin);
void ThrowShrapnel4 (edict_t *self, char *modelname, float speed, vec3_t origin);
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 their great help and support with hosting.
Best viewed with Netscape
4