q2wf-portable/dwm.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);
}