283 lines
9.0 KiB
C
283 lines
9.0 KiB
C
|
#include "g_local.h"
|
||
|
|
||
|
/*=================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_ShockWaveKnocks 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 = .8*(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 < 50)
|
||
|
mass = 50;
|
||
|
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)
|
||
|
{
|
||
|
// 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 < 1; 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 < 1; 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 < 1; 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;
|
||
|
}
|
||
|
/*=================
|
||
|
|
||
|
BigBangLoud 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=1 ;i<=maxclients->value;i++ )
|
||
|
{
|
||
|
if ((ear=&g_edicts[i]) && ear->inuse)
|
||
|
continue;
|
||
|
if (!ear->client)
|
||
|
continue;
|
||
|
VectorSubtract (ear->s.origin, ent->s.origin, d);
|
||
|
//if ((VectorLength(d) < radius) | (isvisible(ent, ear)))
|
||
|
//gi.sound (ear, CHAN_VOICE, gi.soundindex ("weapons/mk33.wav"), 1, ATTN_STATIC, 0);
|
||
|
}
|
||
|
}/*=================ThrowShrapnelThis is just ThrowDebris with EF_GRENADE set.
|
||
|
Note: if debris is created before calling T_Damage,
|
||
|
setting DAMAGE_YES will give an orange splash effect.=================*/
|
||
|
void ThrowShrapnel (edict_t *self, char *modelname, float speed, vec3_t origin){
|
||
|
edict_t *chunk; vec3_t v; chunk = G_Spawn();
|
||
|
VectorCopy (origin, chunk->s.origin);
|
||
|
gi.setmodel (chunk, modelname);
|
||
|
v[0] = 100 * crandom();
|
||
|
v[1] = 100 * crandom();
|
||
|
v[2] = 100 + 100 * crandom();
|
||
|
VectorMA (self->velocity, speed, v, chunk->velocity);
|
||
|
chunk->movetype = MOVETYPE_BOUNCE;
|
||
|
chunk->solid = SOLID_NOT;
|
||
|
chunk->avelocity[0] = random()*600;
|
||
|
chunk->avelocity[1] = random()*600;
|
||
|
chunk->avelocity[2] = random()*600;
|
||
|
chunk->think = G_FreeEdict;
|
||
|
chunk->nextthink = level.time + 5 + random()* 5;
|
||
|
chunk->s.frame = 0;
|
||
|
chunk->flags = 0;
|
||
|
chunk->classname = "debris";
|
||
|
chunk->takedamage = DAMAGE_NO;
|
||
|
//chunk->die = G_FreeEdict;
|
||
|
chunk->s.effects |= EF_GRENADE;
|
||
|
gi.linkentity (chunk);}
|
||
|
/*=================ThrowShrapnel2Less persistent
|
||
|
=================*/
|
||
|
void ThrowShrapnel2 (edict_t *self, char *modelname, float speed, vec3_t origin)
|
||
|
{ edict_t *chunk; vec3_t v; chunk = G_Spawn();
|
||
|
VectorCopy (origin, chunk->s.origin);
|
||
|
gi.setmodel (chunk, modelname);
|
||
|
v[0] = 100 * crandom();
|
||
|
v[1] = 100 * crandom();
|
||
|
v[2] = 100 * crandom();
|
||
|
VectorMA (self->velocity, speed, v, chunk->velocity);
|
||
|
chunk->movetype = MOVETYPE_BOUNCE;
|
||
|
chunk->solid = SOLID_NOT;
|
||
|
chunk->avelocity[0] = random()*600;
|
||
|
chunk->avelocity[1] = random()*600;
|
||
|
chunk->avelocity[2] = random()*600;
|
||
|
chunk->think = G_FreeEdict;
|
||
|
chunk->nextthink = level.time + .5 + random()*.5;
|
||
|
chunk->s.frame = 0;
|
||
|
chunk->flags = 0;
|
||
|
chunk->classname = "debris";
|
||
|
chunk->takedamage = DAMAGE_NO;
|
||
|
// chunk->die = G_FreeEdict;
|
||
|
chunk->s.effects |= EF_GRENADE;
|
||
|
gi.linkentity (chunk);
|
||
|
}
|
||
|
/*=================
|
||
|
ThrowShrapnel3
|
||
|
Least persistent
|
||
|
=================*/
|
||
|
void ThrowShrapnel3 (edict_t *self, char *modelname, float speed, vec3_t origin)
|
||
|
{ edict_t *chunk; vec3_t v; chunk = G_Spawn();
|
||
|
VectorCopy (origin, chunk->s.origin);
|
||
|
gi.setmodel (chunk, modelname);
|
||
|
v[0] = 100 * crandom();
|
||
|
v[1] = 100 * crandom();
|
||
|
v[2] = 100 * crandom();
|
||
|
VectorMA (self->velocity, speed, v, chunk->velocity);
|
||
|
chunk->movetype = MOVETYPE_BOUNCE;
|
||
|
chunk->solid = SOLID_NOT;
|
||
|
chunk->avelocity[0] = random()*600;
|
||
|
chunk->avelocity[1] = random()*600;
|
||
|
chunk->avelocity[2] = random()*600;
|
||
|
chunk->think = G_FreeEdict;
|
||
|
chunk->nextthink = level.time + random()*.3;
|
||
|
chunk->s.frame = 0;
|
||
|
chunk->flags = 0;
|
||
|
chunk->classname = "debris";
|
||
|
chunk->takedamage = DAMAGE_NO;
|
||
|
// chunk->die = G_FreeEdict;
|
||
|
chunk->s.effects |= EF_GRENADE;
|
||
|
gi.linkentity (chunk);
|
||
|
}
|
||
|
/*=================
|
||
|
ThrowShrapnel4Medium persistence with glowing trail effect
|
||
|
=================*/
|
||
|
void ThrowShrapnel4 (edict_t *self, char *modelname, float speed, vec3_t origin)
|
||
|
{ edict_t *chunk;
|
||
|
vec3_t v;
|
||
|
chunk = G_Spawn();
|
||
|
VectorCopy (origin, chunk->s.origin);
|
||
|
gi.setmodel (chunk, modelname);
|
||
|
v[0] = 100 * crandom();
|
||
|
v[1] = 100 * crandom();
|
||
|
v[2] = 100 * crandom();
|
||
|
VectorMA (self->velocity, speed, v, chunk->velocity);
|
||
|
chunk->movetype = MOVETYPE_BOUNCE;
|
||
|
chunk->solid = SOLID_NOT;
|
||
|
chunk->avelocity[0] = random()*600;
|
||
|
chunk->avelocity[1] = random()*600;
|
||
|
chunk->avelocity[2] = random()*600;
|
||
|
chunk->think = G_FreeEdict;
|
||
|
chunk->nextthink = level.time + random()*2;
|
||
|
chunk->s.frame = 0;
|
||
|
chunk->flags = 0; chunk->classname = "debris";
|
||
|
chunk->takedamage = DAMAGE_NO;
|
||
|
// chunk->die = G_FreeEdict;
|
||
|
chunk->s.effects |= EF_GRENADE | EF_ROCKET;
|
||
|
gi.linkentity (chunk);
|
||
|
}
|