diff --git a/src/g_newweap.c b/src/g_newweap.c index 04f937a..e52e865 100644 --- a/src/g_newweap.c +++ b/src/g_newweap.c @@ -1,153 +1,203 @@ -#include "header/local.h" - -#define INCLUDE_ETF_RIFLE 1 -#define INCLUDE_PROX 1 -#define INCLUDE_NUKE 1 -#define INCLUDE_MELEE 1 -#define INCLUDE_TESLA 1 -#define INCLUDE_BEAMS 1 - -extern void check_dodge (edict_t *self, vec3_t start, vec3_t dir, int speed); -extern void hurt_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); -extern void droptofloor (edict_t *ent); -extern void Grenade_Explode (edict_t *ent); - -extern void drawbbox (edict_t *ent); - -#ifdef INCLUDE_ETF_RIFLE /* -======================== -fire_flechette -======================== -*/ -void flechette_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - vec3_t dir; + * ======================================================================= + * + * Rogue specific weapons. + * + * ======================================================================= + */ - if (other == self->owner) +#include "header/local.h" + +#define NUKE_DELAY 4 +#define NUKE_TIME_TO_LIVE 6 +#define NUKE_RADIUS 512 +#define NUKE_DAMAGE 400 +#define NUKE_QUAKE_TIME 3 +#define NUKE_QUAKE_STRENGTH 100 + +#define PROX_TIME_TO_LIVE 45 +#define PROX_TIME_DELAY 0.5 +#define PROX_BOUND_SIZE 96 +#define PROX_DAMAGE_RADIUS 192 +#define PROX_HEALTH 20 +#define PROX_DAMAGE 90 + +#define TESLA_TIME_TO_LIVE 30 +#define TESLA_DAMAGE_RADIUS 128 +#define TESLA_DAMAGE 3 +#define TESLA_KNOCKBACK 8 +#define TESLA_ACTIVATE_TIME 3 +#define TESLA_EXPLOSION_DAMAGE_MULT 50 +#define TESLA_EXPLOSION_RADIUS 200 + +#define TRACKER_DAMAGE_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY | DAMAGE_NO_KNOCKBACK) +#define TRACKER_IMPACT_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY) +#define TRACKER_DAMAGE_TIME 0.5 + +extern byte P_DamageModifier(edict_t *ent); +extern void check_dodge(edict_t *self, vec3_t start, vec3_t dir, int speed); +extern void hurt_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf); +extern void droptofloor(edict_t *ent); +extern void Grenade_Explode(edict_t *ent); +extern void drawbbox(edict_t *ent); + +void +flechette_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + vec3_t dir; + + if (!self || !other || !plane || !surf) + { return; + } + + if (other == self->owner) + { + return; + } if (surf && (surf->flags & SURF_SKY)) { - G_FreeEdict (self); + G_FreeEdict(self); return; } if (self->client) + { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + } if (other->takedamage) { - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, - self->dmg, self->dmg_radius, DAMAGE_NO_REG_ARMOR, MOD_ETF_RIFLE); + T_Damage(other, self, self->owner, self->velocity, self->s.origin, + plane->normal, self->dmg, self->dmg_radius, DAMAGE_NO_REG_ARMOR, + MOD_ETF_RIFLE); } else { - if(!plane) - VectorClear (dir); + if (!plane) + { + VectorClear(dir); + } else - VectorScale (plane->normal, 256, dir); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_FLECHETTE); - gi.WritePosition (self->s.origin); - gi.WriteDir (dir); - gi.multicast (self->s.origin, MULTICAST_PVS); + { + VectorScale(plane->normal, 256, dir); + } + + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_FLECHETTE); + gi.WritePosition(self->s.origin); + gi.WriteDir(dir); + gi.multicast(self->s.origin, MULTICAST_PVS); } - G_FreeEdict (self); + G_FreeEdict(self); } -void fire_flechette (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int kick) +void +fire_flechette(edict_t *self, vec3_t start, vec3_t dir, int damage, + int speed, int kick) { edict_t *flechette; - - VectorNormalize (dir); + + if (!self) + { + return; + } + + VectorNormalize(dir); flechette = G_Spawn(); - VectorCopy (start, flechette->s.origin); - VectorCopy (start, flechette->s.old_origin); - vectoangles2 (dir, flechette->s.angles); + VectorCopy(start, flechette->s.origin); + VectorCopy(start, flechette->s.old_origin); + vectoangles2(dir, flechette->s.angles); - VectorScale (dir, speed, flechette->velocity); + VectorScale(dir, speed, flechette->velocity); flechette->movetype = MOVETYPE_FLYMISSILE; flechette->clipmask = MASK_SHOT; flechette->solid = SOLID_BBOX; flechette->s.renderfx = RF_FULLBRIGHT; - VectorClear (flechette->mins); - VectorClear (flechette->maxs); - - flechette->s.modelindex = gi.modelindex ("models/proj/flechette/tris.md2"); + VectorClear(flechette->mins); + VectorClear(flechette->maxs); + + flechette->s.modelindex = gi.modelindex("models/proj/flechette/tris.md2"); flechette->owner = self; flechette->touch = flechette_touch; - flechette->nextthink = level.time + 8000/speed; + flechette->nextthink = level.time + 8000 / speed; flechette->think = G_FreeEdict; flechette->dmg = damage; flechette->dmg_radius = kick; - gi.linkentity (flechette); - + gi.linkentity(flechette); + if (self->client) - check_dodge (self, flechette->s.origin, dir, speed); + { + check_dodge(self, flechette->s.origin, dir, speed); + } } -#endif -// ************************** -// PROX -// ************************** - -#ifdef INCLUDE_PROX -#define PROX_TIME_TO_LIVE 45 // 45, 30, 15, 10 -#define PROX_TIME_DELAY 0.5 -#define PROX_BOUND_SIZE 96 -#define PROX_DAMAGE_RADIUS 192 -#define PROX_HEALTH 20 -#define PROX_DAMAGE 90 - -//=============== -//=============== -void Prox_Explode (edict_t *ent) +void +Prox_Explode(edict_t *ent) { - vec3_t origin; - edict_t *owner; - - // free the trigger field - - //PMM - changed teammaster to "mover" .. owner of the field is the prox - if(ent->teamchain && ent->teamchain->owner == ent) + vec3_t origin; + edict_t *owner; + + if (!ent) + { + return; + } + + /* free the trigger field */ + if (ent->teamchain && (ent->teamchain->owner == ent)) + { G_FreeEdict(ent->teamchain); + } owner = ent; - if(ent->teammaster) + + if (ent->teammaster) { owner = ent->teammaster; PlayerNoise(owner, ent->s.origin, PNOISE_IMPACT); } - // play quad sound if appopriate + /* play quad sound if appopriate */ if (ent->dmg > PROX_DAMAGE) + { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + } ent->takedamage = DAMAGE_NO; T_RadiusDamage(ent, owner, ent->dmg, ent, PROX_DAMAGE_RADIUS, MOD_PROX); - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - gi.WriteByte (svc_temp_entity); - if (ent->groundentity) - gi.WriteByte (TE_GRENADE_EXPLOSION); - else - gi.WriteByte (TE_ROCKET_EXPLOSION); - gi.WritePosition (origin); - gi.multicast (ent->s.origin, MULTICAST_PVS); + VectorMA(ent->s.origin, -0.02, ent->velocity, origin); + gi.WriteByte(svc_temp_entity); - G_FreeEdict (ent); + if (ent->groundentity) + { + gi.WriteByte(TE_GRENADE_EXPLOSION); + } + else + { + gi.WriteByte(TE_ROCKET_EXPLOSION); + } + + gi.WritePosition(origin); + gi.multicast(ent->s.origin, MULTICAST_PVS); + + G_FreeEdict(ent); } -//=============== -void prox_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ -// gi.dprintf("prox_die\n"); - // if set off by another prox, delay a little (chained explosions) +void +prox_die(edict_t *self, edict_t *inflictor, edict_t *attacker /* unused */, + int damage, vec3_t point) +{ + if (!self || !inflictor) + { + return; + } + if (strcmp(inflictor->classname, "prox")) { self->takedamage = DAMAGE_NO; @@ -161,28 +211,38 @@ void prox_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, } } -//=============== -void Prox_Field_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +void +Prox_Field_Touch(edict_t *ent, edict_t *other, cplane_t *plane /* unused */, + csurface_t *surf /* unused */) { edict_t *prox; - + + if (!ent || !other) + { + return; + } + if (!(other->svflags & SVF_MONSTER) && !other->client) - return; - - // trigger the prox mine if it's still there, and still mine. - prox = ent->owner; - - if (other == prox) // don't set self off - return; - - if (prox->think == Prox_Explode) // we're set to blow! { return; } - if(prox->teamchain == ent) + /* trigger the prox mine if it's still there, and still mine. */ + prox = ent->owner; + + if (other == prox) /* don't set self off */ { - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); + return; + } + + if (prox->think == Prox_Explode) /* we're set to blow! */ + { + return; + } + + if (prox->teamchain == ent) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); prox->think = Prox_Explode; prox->nextthink = level.time + PROX_TIME_DELAY; return; @@ -192,73 +252,88 @@ void Prox_Field_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t G_FreeEdict(ent); } -//=============== -void prox_seek (edict_t *ent) -{ - if(level.time > ent->wait) +void +prox_seek(edict_t *ent) +{ + if (!ent) + { + return; + } + + if (level.time > ent->wait) { Prox_Explode(ent); } else { ent->s.frame++; - if(ent->s.frame > 13) + + if (ent->s.frame > 13) + { ent->s.frame = 9; + } + ent->think = prox_seek; ent->nextthink = level.time + 0.1; } } -//=============== -void prox_open (edict_t *ent) +void +prox_open(edict_t *ent) { edict_t *search; - - search = NULL; - if(ent->s.frame == 9) // end of opening animation + + if (!ent) { - // set the owner to NULL so the owner can shoot it, etc. needs to be done here so the owner - // doesn't get stuck on it while it's opening if fired at point blank wall + return; + } + + search = NULL; + + if (ent->s.frame == 9) /* end of opening animation */ + { + /* set the owner to NULL so the owner can shoot it, etc. + needs to be done here so the owner doesn't get stuck on + it while it's opening if fired at point blank wall */ ent->s.sound = 0; ent->owner = NULL; - if(ent->teamchain) - ent->teamchain->touch = Prox_Field_Touch; - while ((search = findradius(search, ent->s.origin, PROX_DAMAGE_RADIUS+10)) != NULL) - { - if (!search->classname) // tag token and other weird shit - continue; - // if it's a monster or player with health > 0 - // or it's a player start point - // and we can see it - // blow up - if ( - ( - (((search->svflags & SVF_MONSTER) || (search->client)) && (search->health > 0)) || - ( - (deathmatch->value) && - ( - (!strcmp(search->classname, "info_player_deathmatch")) || - (!strcmp(search->classname, "info_player_start")) || - (!strcmp(search->classname, "info_player_coop")) || - (!strcmp(search->classname, "misc_teleporter_dest")) - ) - ) - ) - && (visible (search, ent)) - ) + if (ent->teamchain) + { + ent->teamchain->touch = Prox_Field_Touch; + } + + while ((search = findradius(search, ent->s.origin, PROX_DAMAGE_RADIUS + 10)) != NULL) + { + if (!search->classname) /* tag token and other weird shit */ { - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); - Prox_Explode (ent); + continue; + } + + /* if it's a monster or player with health > 0 + or it's a player start point and we can see it + blow up */ + if (((((search->svflags & SVF_MONSTER) || + (search->client)) && (search->health > 0)) || + ((deathmatch->value) &&((!strcmp(search->classname, "info_player_deathmatch")) || + (!strcmp(search->classname, "info_player_start")) || + (!strcmp(search->classname, "info_player_coop")) || + (!strcmp(search->classname, "misc_teleporter_dest"))))) && + (visible(search, ent))) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxwarn.wav"), 1, ATTN_NORM, 0); + Prox_Explode(ent); return; } } if (strong_mines && (strong_mines->value)) + { ent->wait = level.time + PROX_TIME_TO_LIVE; + } else { - switch (ent->dmg/PROX_DAMAGE) + switch (ent->dmg / PROX_DAMAGE) { case 1: ent->wait = level.time + PROX_TIME_TO_LIVE; @@ -284,27 +359,34 @@ void prox_open (edict_t *ent) else { if (ent->s.frame == 0) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/proxopen.wav"), 1, ATTN_NORM, 0); + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/proxopen.wav"), 1, ATTN_NORM, 0); + } + ent->s.frame++; ent->think = prox_open; - ent->nextthink = level.time + 0.05; + ent->nextthink = level.time + 0.05; } } -//=============== -//=============== -void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +void +prox_land(edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) { - edict_t *field; - vec3_t dir; - vec3_t forward, right, up; - int movetype = MOVETYPE_NONE; - int stick_ok = 0; - vec3_t land_point; - - // must turn off owner so owner can shoot it and set it off - // moved to prox_open so owner can get away from it if fired at pointblank range into - // wall + edict_t *field; + vec3_t dir; + vec3_t forward, right, up; + int movetype = MOVETYPE_NONE; + int stick_ok = 0; + vec3_t land_point; + + if (!ent || !other || !plane || !surf) + { + return; + } + + /* must turn off owner so owner can shoot it and set it off + moved to prox_open so owner can get away from it if fired + at pointblank range into wall */ if (surf && (surf->flags & SURF_SKY)) { G_FreeEdict(ent); @@ -312,94 +394,111 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) } if (plane == NULL) + { return; + } if (plane->normal != 0) { - VectorMA (ent->s.origin, -10.0, plane->normal, land_point); - if (gi.pointcontents (land_point) & (CONTENTS_SLIME|CONTENTS_LAVA)) + VectorMA(ent->s.origin, -10.0, plane->normal, land_point); + + if (gi.pointcontents(land_point) & (CONTENTS_SLIME | CONTENTS_LAVA)) { - Prox_Explode (ent); + Prox_Explode(ent); return; } } - if ((other->svflags & SVF_MONSTER) || other->client || (other->svflags & SVF_DAMAGEABLE)) + if ((other->svflags & SVF_MONSTER) || other->client || + (other->svflags & SVF_DAMAGEABLE)) { - if(other != ent->teammaster) + if (other != ent->teammaster) + { Prox_Explode(ent); + } return; } -#define STOP_EPSILON 0.1 +#define STOP_EPSILON 0.1 else if (other != world) { - //Here we need to check to see if we can stop on this entity. - //Note that plane can be NULL - - //PMM - code stolen from g_phys (ClipVelocity) + /* Here we need to check to see if we can stop on this entity. */ vec3_t out; float backoff, change; int i; - if (!plane->normal) // this happens if you hit a point object, maybe other cases + if (!plane->normal) /* this happens if you hit a point object, maybe other cases */ { Prox_Explode(ent); return; } if ((other->movetype == MOVETYPE_PUSH) && (plane->normal[2] > 0.7)) - stick_ok = 1; - else - stick_ok = 0; - - backoff = DotProduct (ent->velocity, plane->normal) * 1.5; - for (i=0 ; i<3 ; i++) { - change = plane->normal[i]*backoff; + stick_ok = 1; + } + else + { + stick_ok = 0; + } + + backoff = DotProduct(ent->velocity, plane->normal) * 1.5; + + for (i = 0; i < 3; i++) + { + change = plane->normal[i] * backoff; out[i] = ent->velocity[i] - change; - if (out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON) + + if ((out[i] > -STOP_EPSILON) && (out[i] < STOP_EPSILON)) + { out[i] = 0; + } } if (out[2] > 60) + { return; + } movetype = MOVETYPE_BOUNCE; - // if we're here, we're going to stop on an entity + /* if we're here, we're going to stop on an entity */ if (stick_ok) - { // it's a happy entity - VectorCopy (vec3_origin, ent->velocity); - VectorCopy (vec3_origin, ent->avelocity); + { + /* it's a happy entity */ + VectorCopy(vec3_origin, ent->velocity); + VectorCopy(vec3_origin, ent->avelocity); } - else // no-stick. teflon time + else /* no-stick. teflon time */ { if (plane->normal[2] > 0.7) { Prox_Explode(ent); return; } + return; } } else if (other->s.modelindex != 1) - return; - - vectoangles2 (plane->normal, dir); - AngleVectors (dir, forward, right, up); - - if (gi.pointcontents (ent->s.origin) & (CONTENTS_LAVA|CONTENTS_SLIME)) { - Prox_Explode (ent); + return; + } + + vectoangles2(plane->normal, dir); + AngleVectors(dir, forward, right, up); + + if (gi.pointcontents(ent->s.origin) & (CONTENTS_LAVA | CONTENTS_SLIME)) + { + Prox_Explode(ent); return; } field = G_Spawn(); - VectorCopy (ent->s.origin, field->s.origin); + VectorCopy(ent->s.origin, field->s.origin); VectorClear(field->velocity); VectorClear(field->avelocity); VectorSet(field->mins, -PROX_BOUND_SIZE, -PROX_BOUND_SIZE, -PROX_BOUND_SIZE); @@ -409,15 +508,16 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) field->owner = ent; field->classname = "prox_field"; field->teammaster = ent; - gi.linkentity (field); + gi.linkentity(field); VectorClear(ent->velocity); VectorClear(ent->avelocity); - // rotate to vertical + + /* rotate to vertical */ dir[PITCH] = dir[PITCH] + 90; - VectorCopy (dir, ent->s.angles); + VectorCopy(dir, ent->s.angles); ent->takedamage = DAMAGE_AIM; - ent->movetype = movetype; // either bounce or none, depending on whether we stuck to something + ent->movetype = movetype; /* either bounce or none, depending on whether we stuck to something */ ent->die = prox_die; ent->teamchain = field; ent->health = PROX_HEALTH; @@ -425,740 +525,231 @@ void prox_land (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) ent->think = prox_open; ent->touch = NULL; ent->solid = SOLID_BBOX; - // record who we're attached to + /* record who we're attached to */ gi.linkentity(ent); } -//=============== -//=============== -void fire_prox (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed) +void +fire_prox(edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed) { - edict_t *prox; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); + edict_t *prox; + vec3_t dir; + vec3_t forward, right, up; + + if (!self) + { + return; + } + + vectoangles2(aimdir, dir); + AngleVectors(dir, forward, right, up); prox = G_Spawn(); - VectorCopy (start, prox->s.origin); - VectorScale (aimdir, speed, prox->velocity); - VectorMA (prox->velocity, 200 + crandom() * 10.0, up, prox->velocity); - VectorMA (prox->velocity, crandom() * 10.0, right, prox->velocity); - VectorCopy (dir, prox->s.angles); - prox->s.angles[PITCH]-=90; + VectorCopy(start, prox->s.origin); + VectorScale(aimdir, speed, prox->velocity); + VectorMA(prox->velocity, 200 + crandom() * 10.0, up, prox->velocity); + VectorMA(prox->velocity, crandom() * 10.0, right, prox->velocity); + VectorCopy(dir, prox->s.angles); + prox->s.angles[PITCH] -= 90; prox->movetype = MOVETYPE_BOUNCE; - prox->solid = SOLID_BBOX; + prox->solid = SOLID_BBOX; prox->s.effects |= EF_GRENADE; - prox->clipmask = MASK_SHOT|CONTENTS_LAVA|CONTENTS_SLIME; + prox->clipmask = MASK_SHOT | CONTENTS_LAVA | CONTENTS_SLIME; prox->s.renderfx |= RF_IR_VISIBLE; - //FIXME - this needs to be bigger. Has other effects, though. Maybe have to change origin to compensate - // so it sinks in correctly. Also in lavacheck, might have to up the distance - VectorSet (prox->mins, -6, -6, -6); - VectorSet (prox->maxs, 6, 6, 6); - prox->s.modelindex = gi.modelindex ("models/weapons/g_prox/tris.md2"); + VectorSet(prox->mins, -6, -6, -6); + VectorSet(prox->maxs, 6, 6, 6); + prox->s.modelindex = gi.modelindex("models/weapons/g_prox/tris.md2"); prox->owner = self; prox->teammaster = self; prox->touch = prox_land; prox->think = Prox_Explode; - prox->dmg = PROX_DAMAGE*damage_multiplier; + prox->dmg = PROX_DAMAGE * damage_multiplier; prox->classname = "prox"; prox->svflags |= SVF_DAMAGEABLE; prox->flags |= FL_MECHANICAL; switch (damage_multiplier) { - case 1: - prox->nextthink = level.time + PROX_TIME_TO_LIVE; - break; - case 2: - prox->nextthink = level.time + 30; - break; - case 4: - prox->nextthink = level.time + 15; - break; - case 8: - prox->nextthink = level.time + 10; - break; - default: - prox->nextthink = level.time + PROX_TIME_TO_LIVE; - break; + case 1: + prox->nextthink = level.time + PROX_TIME_TO_LIVE; + break; + case 2: + prox->nextthink = level.time + 30; + break; + case 4: + prox->nextthink = level.time + 15; + break; + case 8: + prox->nextthink = level.time + 10; + break; + default: + prox->nextthink = level.time + PROX_TIME_TO_LIVE; + break; } - gi.linkentity (prox); -} -#endif - -// ************************* -// FLAMETHROWER -// ************************* - -#ifdef INCLUDE_FLAMETHROWER -#define FLAMETHROWER_RADIUS 8 - -void fire_remove (edict_t *ent) -{ - if(ent == ent->owner->teamchain) - ent->owner->teamchain = NULL; - - G_FreeEdict(ent); + gi.linkentity(prox); } -void fire_flame (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed) +void +fire_player_melee(edict_t *self, vec3_t start, vec3_t aim, int reach, + int damage, int kick, int quiet, int mod) { - edict_t *flame; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); - - flame = G_Spawn(); - - // the origin is the first control point, put it speed forward. - VectorMA(start, speed, forward, flame->s.origin); - - // record that velocity - VectorScale (aimdir, speed, flame->velocity); - - VectorCopy (dir, flame->s.angles); - flame->movetype = MOVETYPE_NONE; - flame->solid = SOLID_NOT; - - VectorSet(flame->mins, -FLAMETHROWER_RADIUS, -FLAMETHROWER_RADIUS, -FLAMETHROWER_RADIUS); - VectorSet(flame->maxs, FLAMETHROWER_RADIUS, FLAMETHROWER_RADIUS, FLAMETHROWER_RADIUS); - - flame->s.sound = gi.soundindex ("weapons/flame.wav"); - flame->owner = self; - flame->dmg = damage; - flame->classname = "flame"; - - // clear control points and velocities - VectorCopy (flame->s.origin, flame->flameinfo.pos1); - VectorCopy (flame->velocity, flame->flameinfo.vel1); - VectorCopy (flame->s.origin, flame->flameinfo.pos2); - VectorCopy (flame->velocity, flame->flameinfo.vel2); - VectorCopy (flame->s.origin, flame->flameinfo.pos3); - VectorCopy (flame->velocity, flame->flameinfo.vel3); - VectorCopy (flame->s.origin, flame->flameinfo.pos4); - - // hook flame stream to owner - self->teamchain = flame; - - gi.linkentity (flame); -} - -// fixme - change to use start location, not entity origin -void fire_maintain (edict_t *ent, edict_t *flame, vec3_t start, vec3_t aimdir, int damage, int speed) -{ - trace_t tr; - - // move the control points out the appropriate direction and velocity - VectorAdd(flame->flameinfo.pos3, flame->flameinfo.vel3, flame->flameinfo.pos4); - VectorAdd(flame->flameinfo.pos2, flame->flameinfo.vel2, flame->flameinfo.pos3); - VectorAdd(flame->flameinfo.pos1, flame->flameinfo.vel1, flame->flameinfo.pos2); - VectorAdd(flame->s.origin, flame->velocity, flame->flameinfo.pos1); - - // move the velocities for the control points - VectorCopy(flame->flameinfo.vel2, flame->flameinfo.vel3); - VectorCopy(flame->flameinfo.vel1, flame->flameinfo.vel2); - VectorCopy(flame->velocity, flame->flameinfo.vel1); - - // set velocity and location for new control point 0. - VectorMA(start, speed, aimdir, flame->s.origin); - VectorScale(aimdir, speed, flame->velocity); - - // - // does it hit a wall? if so, when? - // - - // player fire point to flame origin. - tr = gi.trace(start, flame->mins, flame->maxs, - flame->s.origin, flame, MASK_SHOT); - if(tr.fraction == 1.0) + vec3_t forward, right, up; + vec3_t v; + vec3_t point; + trace_t tr; + + if (!self) { - // origin to point 1 - tr = gi.trace(flame->s.origin, flame->mins, flame->maxs, - flame->flameinfo.pos1, flame, MASK_SHOT); - if(tr.fraction == 1.0) - { - // point 1 to point 2 - tr = gi.trace(flame->flameinfo.pos1, flame->mins, flame->maxs, - flame->flameinfo.pos2, flame, MASK_SHOT); - if(tr.fraction == 1.0) - { - // point 2 to point 3 - tr = gi.trace(flame->flameinfo.pos2, flame->mins, flame->maxs, - flame->flameinfo.pos3, flame, MASK_SHOT); - if(tr.fraction == 1.0) - { - // point 3 to point 4, point 3 valid - tr = gi.trace(flame->flameinfo.pos3, flame->mins, flame->maxs, - flame->flameinfo.pos4, flame, MASK_SHOT); - if(tr.fraction < 1.0) // point 4 blocked - { - VectorCopy(tr.endpos, flame->flameinfo.pos4); - } - } - else // point 3 blocked, point 2 valid - { - VectorCopy(flame->flameinfo.vel2, flame->flameinfo.vel3); - VectorCopy(tr.endpos, flame->flameinfo.pos3); - VectorCopy(tr.endpos, flame->flameinfo.pos4); - } - } - else // point 2 blocked, point 1 valid - { - VectorCopy(flame->flameinfo.vel1, flame->flameinfo.vel2); - VectorCopy(flame->flameinfo.vel1, flame->flameinfo.vel3); - VectorCopy(tr.endpos, flame->flameinfo.pos2); - VectorCopy(tr.endpos, flame->flameinfo.pos3); - VectorCopy(tr.endpos, flame->flameinfo.pos4); - } - } - else // point 1 blocked, origin valid - { - VectorCopy(flame->velocity, flame->flameinfo.vel1); - VectorCopy(flame->velocity, flame->flameinfo.vel2); - VectorCopy(flame->velocity, flame->flameinfo.vel3); - VectorCopy(tr.endpos, flame->flameinfo.pos1); - VectorCopy(tr.endpos, flame->flameinfo.pos2); - VectorCopy(tr.endpos, flame->flameinfo.pos3); - VectorCopy(tr.endpos, flame->flameinfo.pos4); - } - } - else // origin blocked! - { - VectorCopy(flame->velocity, flame->flameinfo.vel1); - VectorCopy(flame->velocity, flame->flameinfo.vel2); - VectorCopy(flame->velocity, flame->flameinfo.vel3); - VectorCopy(tr.endpos, flame->s.origin); - VectorCopy(tr.endpos, flame->flameinfo.pos1); - VectorCopy(tr.endpos, flame->flameinfo.pos2); - VectorCopy(tr.endpos, flame->flameinfo.pos3); - VectorCopy(tr.endpos, flame->flameinfo.pos4); - } - - if(tr.fraction < 1.0 && tr.ent->takedamage) - { - T_Damage (tr.ent, flame, ent, flame->velocity, tr.endpos, tr.plane.normal, - damage, 0, DAMAGE_NO_KNOCKBACK | DAMAGE_ENERGY | DAMAGE_FIRE); - } - - gi.linkentity(flame); - - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_FLAME); - gi.WriteShort(ent - g_edicts); - gi.WriteShort(6); - gi.WritePosition (start); - gi.WritePosition (flame->s.origin); - gi.WritePosition (flame->flameinfo.pos1); - gi.WritePosition (flame->flameinfo.pos2); - gi.WritePosition (flame->flameinfo.pos3); - gi.WritePosition (flame->flameinfo.pos4); - gi.multicast (flame->s.origin, MULTICAST_PVS); -} - -/*QUAKED trap_flameshooter (1 0 0) (-8 -8 -8) (8 8 8) -*/ -#define FLAMESHOOTER_VELOCITY 50 -#define FLAMESHOOTER_DAMAGE 20 -#define FLAMESHOOTER_BURST_VELOCITY 300 -#define FLAMESHOOTER_BURST_DAMAGE 30 - -//#define FLAMESHOOTER_PUFF 1 -#define FLAMESHOOTER_STREAM 1 - -void flameshooter_think (edict_t *self) -{ - vec3_t forward, right, up; - edict_t *flame; - - if(self->delay) - { - if(self->teamchain) - fire_remove (self->teamchain); return; } + + vectoangles2(aim, v); + AngleVectors(v, forward, right, up); + VectorNormalize(forward); + VectorMA(start, reach, forward, point); - self->s.angles[1] += self->speed; - if(self->s.angles[1] > 135 || self->s.angles[1] < 45) - self->speed = -self->speed; - - AngleVectors (self->s.angles, forward, right, up); - -#ifdef FLAMESHOOTER_STREAM - flame = self->teamchain; - if(!self->teamchain) - fire_flame (self, self->s.origin, forward, FLAMESHOOTER_DAMAGE, FLAMESHOOTER_VELOCITY); - else - fire_maintain (self, flame, self->s.origin, forward, FLAMESHOOTER_DAMAGE, FLAMESHOOTER_VELOCITY); - - self->think = flameshooter_think; - self->nextthink = level.time + 0.05; -#else - fire_burst (self, self->s.origin, forward, FLAMESHOOTER_BURST_DAMAGE, FLAMESHOOTER_BURST_VELOCITY); - - self->think = flameshooter_think; - self->nextthink = level.time + 0.1; -#endif -} - -void flameshooter_use (edict_t *self, edict_t *other, edict_t *activator) -{ - if(self->delay) - { - self->delay = 0; - self->think = flameshooter_think; - self->nextthink = level.time + 0.1; - } - else - self->delay = 1; -} - -void SP_trap_flameshooter(edict_t *self) -{ - vec3_t tempAngles; - - self->solid = SOLID_NOT; - self->movetype = MOVETYPE_NONE; - - self->delay = 0; - - self->use = flameshooter_use; - if(self->delay == 0) - { - self->think = flameshooter_think; - self->nextthink = level.time + 0.1; - } - - self->speed = 10; - - VectorCopy(self->s.angles, tempAngles); - - if (!VectorCompare(self->s.angles, vec3_origin)) - G_SetMovedir (self->s.angles, self->movedir); - - VectorCopy(tempAngles, self->s.angles); - - gi.linkentity (self); -} - -// ************************* -// fire_burst -// ************************* - -#define FLAME_BURST_MAX_SIZE 64 -#define FLAME_BURST_FRAMES 20 -#define FLAME_BURST_MIDPOINT 10 - -void fire_burst_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - int powerunits; - int damage, radius; - vec3_t origin; - - if (surf && (surf->flags & SURF_SKY)) - { - G_FreeEdict (ent); - return; - } - - if(other == ent->owner || ent == other) - return; - - // don't let flame puffs blow each other up - if(other->classname && !strcmp(other->classname, ent->classname)) - return; - - if(ent->waterlevel) - { - G_FreeEdict(ent); - } - - if(!(other->svflags & SVF_MONSTER) && !other->client) - { - powerunits = FLAME_BURST_FRAMES - ent->s.frame; - damage = powerunits * 6; - radius = powerunits * 4; - - T_RadiusDamage(ent, ent->owner, damage, ent, radius, DAMAGE_FIRE); - - // calculate position for the explosion entity - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_PLAIN_EXPLOSION); - gi.WritePosition (origin); - gi.multicast (ent->s.origin, MULTICAST_PVS); - - G_FreeEdict (ent); - } -} - -void fire_burst_think (edict_t *self) -{ - int current_radius; - - if(self->waterlevel) - { - G_FreeEdict(self); - return; - } - - self->s.frame++; - if(self->s.frame >= FLAME_BURST_FRAMES) - { - G_FreeEdict(self); - return; - } - - else if(self->s.frame < FLAME_BURST_MIDPOINT) - { - current_radius = (FLAME_BURST_MAX_SIZE / FLAME_BURST_MIDPOINT) * self->s.frame; - } - else - { - current_radius = (FLAME_BURST_MAX_SIZE / FLAME_BURST_MIDPOINT) * (FLAME_BURST_FRAMES - self->s.frame); - } - - if(self->s.frame == 3) - self->s.skinnum = 1; - else if (self->s.frame == 7) - self->s.skinnum = 2; - else if (self->s.frame == 10) - self->s.skinnum = 3; - else if (self->s.frame == 13) - self->s.skinnum = 4; - else if (self->s.frame == 16) - self->s.skinnum = 5; - else if (self->s.frame == 19) - self->s.skinnum = 6; - - if(current_radius < 8) - current_radius = 8; - else if(current_radius > FLAME_BURST_MAX_SIZE) - current_radius = FLAME_BURST_MAX_SIZE; - - T_RadiusDamage(self, self->owner, self->dmg, self, current_radius, DAMAGE_FIRE); - - self->think = fire_burst_think; - self->nextthink = level.time + 0.1; -} - -void fire_burst (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed) -{ - edict_t *flame; - vec3_t dir; - vec3_t baseVel; - vec3_t forward, right, up; - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); - - flame = G_Spawn(); - VectorCopy(start, flame->s.origin); - - // scale down so only 30% of player's velocity is taken into account. - VectorScale (self->velocity, 0.3, baseVel); - VectorMA(baseVel, speed, aimdir, flame->velocity); - - VectorCopy (dir, flame->s.angles); - flame->movetype = MOVETYPE_FLY; - flame->solid = SOLID_TRIGGER; - - VectorSet(flame->mins, -FLAMETHROWER_RADIUS, -FLAMETHROWER_RADIUS, -FLAMETHROWER_RADIUS); - VectorSet(flame->maxs, FLAMETHROWER_RADIUS, FLAMETHROWER_RADIUS, FLAMETHROWER_RADIUS); - - flame->s.sound = gi.soundindex ("weapons/flame.wav"); - flame->s.modelindex = gi.modelindex ("models/projectiles/puff/tris.md2"); - flame->owner = self; - flame->touch = fire_burst_touch; - flame->think = fire_burst_think; - flame->nextthink = level.time + 0.1; - flame->dmg = damage; - flame->classname = "flameburst"; - flame->s.effects = EF_FIRE_PUFF; - - gi.linkentity (flame); -} -#endif - -// ************************* -// INCENDIARY GRENADES -// ************************* - -#ifdef INCLUDE_INCENDIARY -void FireThink (edict_t *ent) -{ - if(level.time > ent->wait) - G_FreeEdict(ent); - else - { - ent->s.frame++; - if(ent->s.frame>10) - ent->s.frame = 0; - ent->nextthink = level.time + 0.05; - ent->think = FireThink; - } -} - -#define FIRE_HEIGHT 64 -#define FIRE_RADIUS 64 -#define FIRE_DAMAGE 3 -#define FIRE_DURATION 15 - -edict_t *StartFire(edict_t *fireOwner, vec3_t fireOrigin, float fireDuration, float fireDamage) -{ - edict_t *fire; - - fire = G_Spawn(); - VectorCopy (fireOrigin, fire->s.origin); - fire->movetype = MOVETYPE_TOSS; - fire->solid = SOLID_TRIGGER; - VectorSet(fire->mins, -FIRE_RADIUS, -FIRE_RADIUS, 0); - VectorSet(fire->maxs, FIRE_RADIUS, FIRE_RADIUS, FIRE_HEIGHT); - - fire->s.sound = gi.soundindex ("weapons/incend.wav"); - fire->s.modelindex = gi.modelindex ("models/objects/fire/tris.md2"); - - fire->owner = fireOwner; - fire->touch = hurt_touch; - fire->nextthink = level.time + 0.05; - fire->wait = level.time + fireDuration; - fire->think = FireThink; - fire->dmg = fireDamage; - fire->classname = "incendiary_fire"; - - gi.linkentity (fire); - - return fire; -} - -void Incendiary_Explode (edict_t *ent) -{ - vec3_t origin; - - if (ent->owner->client) - PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT); - - //FIXME: if we are onground then raise our Z just a bit since we are a point? - T_RadiusDamage(ent, ent->owner, ent->dmg, NULL, ent->dmg_radius, DAMAGE_FIRE); - - VectorMA (ent->s.origin, -0.02, ent->velocity, origin); - gi.WriteByte (svc_temp_entity); - if (ent->groundentity) - gi.WriteByte (TE_GRENADE_EXPLOSION); - else - gi.WriteByte (TE_ROCKET_EXPLOSION); - gi.WritePosition (origin); - gi.multicast (ent->s.origin, MULTICAST_PVS); - - StartFire(ent->owner, ent->s.origin, FIRE_DURATION, FIRE_DAMAGE); - - G_FreeEdict (ent); - -} - -void Incendiary_Touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - if (other == ent->owner) - return; - - if (surf && (surf->flags & SURF_SKY)) - { - G_FreeEdict (ent); - return; - } - - if (!(other->svflags & SVF_MONSTER) && !(ent->client)) - { - if (ent->spawnflags & 1) - { - if (random() > 0.5) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); - else - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); - } - else - { - if (random() > 0.5) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/grenlb1b.wav"), 1, ATTN_NORM, 0); - else - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/grenlb2b.wav"), 1, ATTN_NORM, 0); - } - return; - } - - Incendiary_Explode (ent); -} - -void fire_incendiary_grenade (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius) -{ - edict_t *grenade; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); - - grenade = G_Spawn(); - VectorCopy (start, grenade->s.origin); - VectorScale (aimdir, speed, grenade->velocity); - VectorMA (grenade->velocity, 200 + crandom() * 10.0, up, grenade->velocity); - VectorMA (grenade->velocity, crandom() * 10.0, right, grenade->velocity); - VectorSet (grenade->avelocity, 300, 300, 300); - grenade->movetype = MOVETYPE_BOUNCE; - grenade->clipmask = MASK_SHOT; - grenade->solid = SOLID_BBOX; - grenade->s.effects |= EF_GRENADE; - VectorClear (grenade->mins); - VectorClear (grenade->maxs); - grenade->s.modelindex = gi.modelindex ("models/projectiles/incend/tris.md2"); - grenade->owner = self; - grenade->touch = Incendiary_Touch; - grenade->nextthink = level.time + timer; - grenade->think = Incendiary_Explode; - grenade->dmg = damage; - grenade->dmg_radius = damage_radius; - grenade->classname = "incendiary_grenade"; - - gi.linkentity (grenade); -} -#endif - -// ************************* -// MELEE WEAPONS -// ************************* - -#ifdef INCLUDE_MELEE -void fire_player_melee (edict_t *self, vec3_t start, vec3_t aim, int reach, int damage, int kick, int quiet, int mod) -{ - vec3_t forward, right, up; - vec3_t v; - vec3_t point; - trace_t tr; - - vectoangles2 (aim, v); - AngleVectors (v, forward, right, up); - VectorNormalize (forward); - VectorMA( start, reach, forward, point); - - //see if the hit connects + /* see if the hit connects */ tr = gi.trace(start, NULL, NULL, point, self, MASK_SHOT); - if(tr.fraction == 1.0) + + if (tr.fraction == 1.0) { - if(!quiet) - gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/swish.wav"), 1, ATTN_NORM, 0); - //FIXME some sound here? + if (!quiet) + { + gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/swish.wav"), 1, ATTN_NORM, 0); + } + return; } - if(tr.ent->takedamage == DAMAGE_YES || tr.ent->takedamage == DAMAGE_AIM) + if ((tr.ent->takedamage == DAMAGE_YES) || + (tr.ent->takedamage == DAMAGE_AIM)) { - // pull the player forward if you do damage + /* pull the player forward if you do damage */ VectorMA(self->velocity, 75, forward, self->velocity); VectorMA(self->velocity, 75, up, self->velocity); - // do the damage - // FIXME - make the damage appear at right spot and direction - if(mod == MOD_CHAINFIST) - T_Damage (tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, damage, kick/2, - DAMAGE_DESTROY_ARMOR | DAMAGE_NO_KNOCKBACK, mod); + /* do the damage */ + if (mod == MOD_CHAINFIST) + { + T_Damage(tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, + damage, kick / 2, DAMAGE_DESTROY_ARMOR | DAMAGE_NO_KNOCKBACK, mod); + } else - T_Damage (tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, damage, kick/2, DAMAGE_NO_KNOCKBACK, mod); + { + T_Damage(tr.ent, self, self, vec3_origin, tr.ent->s.origin, vec3_origin, + damage, kick / 2, DAMAGE_NO_KNOCKBACK, mod); + } - if(!quiet) - gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/meatht.wav"), 1, ATTN_NORM, 0); + if (!quiet) + { + gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/meatht.wav"), 1, ATTN_NORM, 0); + } } else { - if(!quiet) - gi.sound (self, CHAN_WEAPON, gi.soundindex ("weapons/tink1.wav"), 1, ATTN_NORM, 0); + if (!quiet) + { + gi.sound(self, CHAN_WEAPON, gi.soundindex("weapons/tink1.wav"), 1, ATTN_NORM, 0); + } - VectorScale (tr.plane.normal, 256, point); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_GUNSHOT); - gi.WritePosition (tr.endpos); - gi.WriteDir (point); - gi.multicast (tr.endpos, MULTICAST_PVS); + VectorScale(tr.plane.normal, 256, point); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_GUNSHOT); + gi.WritePosition(tr.endpos); + gi.WriteDir(point); + gi.multicast(tr.endpos, MULTICAST_PVS); } } -#endif -// ************************* -// NUKE -// ************************* - -#ifdef INCLUDE_NUKE -#define NUKE_DELAY 4 -#define NUKE_TIME_TO_LIVE 6 -//#define NUKE_TIME_TO_LIVE 40 -#define NUKE_RADIUS 512 -#define NUKE_DAMAGE 400 -#define NUKE_QUAKE_TIME 3 -#define NUKE_QUAKE_STRENGTH 100 - -void Nuke_Quake (edict_t *self) +void +Nuke_Quake(edict_t *self) { - int i; - edict_t *e; - + int i; + edict_t *e; + + if (!self) + { + return; + } + if (self->last_move_time < level.time) { - gi.positioned_sound (self->s.origin, self, CHAN_AUTO, self->noise_index, 0.75, ATTN_NONE, 0); + gi.positioned_sound(self->s.origin, self, CHAN_AUTO, self->noise_index, + 0.75, ATTN_NONE, 0); self->last_move_time = level.time + 0.5; } - for (i=1, e=g_edicts+i; i < globals.num_edicts; i++,e++) + for (i = 1, e = g_edicts + i; i < globals.num_edicts; i++, e++) { if (!e->inuse) + { continue; + } + if (!e->client) + { continue; + } + if (!e->groundentity) + { continue; + } e->groundentity = NULL; - e->velocity[0] += crandom()* 150; - e->velocity[1] += crandom()* 150; + e->velocity[0] += crandom() * 150; + e->velocity[1] += crandom() * 150; e->velocity[2] = self->speed * (100.0 / e->mass); } if (level.time < self->timestamp) + { self->nextthink = level.time + FRAMETIME; + } else - G_FreeEdict (self); + { + G_FreeEdict(self); + } } - -void Nuke_Explode (edict_t *ent) -{ +void +Nuke_Explode(edict_t *ent) +{ + if (!ent) + { + return; + } + if (ent->teammaster->client) + { PlayerNoise(ent->teammaster, ent->s.origin, PNOISE_IMPACT); + } - T_RadiusNukeDamage(ent, ent->teammaster, ent->dmg, ent, ent->dmg_radius, MOD_NUKE); + T_RadiusNukeDamage(ent, ent->teammaster, ent->dmg, + ent, ent->dmg_radius, MOD_NUKE); if (ent->dmg > NUKE_DAMAGE) + { gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + } - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, gi.soundindex ("weapons/grenlx1a.wav"), 1, ATTN_NONE, 0); + gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/grenlx1a.wav"), 1, ATTN_NONE, 0); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_EXPLOSION1_BIG); - gi.WritePosition (ent->s.origin); - gi.multicast (ent->s.origin, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_EXPLOSION1_BIG); + gi.WritePosition(ent->s.origin); + gi.multicast(ent->s.origin, MULTICAST_PVS); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_NUKEBLAST); - gi.WritePosition (ent->s.origin); - gi.multicast (ent->s.origin, MULTICAST_ALL); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_NUKEBLAST); + gi.WritePosition(ent->s.origin); + gi.multicast(ent->s.origin, MULTICAST_ALL); - // become a quake + /* become a quake */ ent->svflags |= SVF_NOCLIENT; - ent->noise_index = gi.soundindex ("world/rumble.wav"); + ent->noise_index = gi.soundindex("world/rumble.wav"); ent->think = Nuke_Quake; ent->speed = NUKE_QUAKE_STRENGTH; ent->timestamp = level.time + NUKE_QUAKE_TIME; @@ -1166,58 +757,79 @@ void Nuke_Explode (edict_t *ent) ent->last_move_time = 0; } -void nuke_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ - self->takedamage = DAMAGE_NO; - if ((attacker) && !(strcmp(attacker->classname, "nuke"))) +void +nuke_die(edict_t *self, edict_t *inflictor /* unused */, + edict_t *attacker, int damage, vec3_t point) +{ + if (!self || !attacker) { - G_FreeEdict (self); return; } + + self->takedamage = DAMAGE_NO; + + if ((attacker) && !(strcmp(attacker->classname, "nuke"))) + { + G_FreeEdict(self); + return; + } + Nuke_Explode(self); } -void Nuke_Think(edict_t *ent) +void +Nuke_Think(edict_t *ent) { float attenuation, default_atten = 1.8; - int damage_multiplier, muzzleflash; + int damage_multiplier, muzzleflash; + + if (!ent) + { + return; + } + + damage_multiplier = ent->dmg / NUKE_DAMAGE; - damage_multiplier = ent->dmg/NUKE_DAMAGE; switch (damage_multiplier) { - case 1: - attenuation = default_atten/1.4; - muzzleflash = MZ_NUKE1; - break; - case 2: - attenuation = default_atten/2.0; - muzzleflash = MZ_NUKE2; - break; - case 4: - attenuation = default_atten/3.0; - muzzleflash = MZ_NUKE4; - break; - case 8: - attenuation = default_atten/5.0; - muzzleflash = MZ_NUKE8; - break; - default: - attenuation = default_atten; - muzzleflash = MZ_NUKE1; - break; + case 1: + attenuation = default_atten / 1.4; + muzzleflash = MZ_NUKE1; + break; + case 2: + attenuation = default_atten / 2.0; + muzzleflash = MZ_NUKE2; + break; + case 4: + attenuation = default_atten / 3.0; + muzzleflash = MZ_NUKE4; + break; + case 8: + attenuation = default_atten / 5.0; + muzzleflash = MZ_NUKE8; + break; + default: + attenuation = default_atten; + muzzleflash = MZ_NUKE1; + break; } - if(ent->wait < level.time) + if (ent->wait < level.time) + { Nuke_Explode(ent); + } else if (level.time >= (ent->wait - NUKE_TIME_TO_LIVE)) { ent->s.frame++; - if(ent->s.frame > 11) - ent->s.frame = 6; - if (gi.pointcontents (ent->s.origin) & (CONTENTS_SLIME|CONTENTS_LAVA)) + if (ent->s.frame > 11) { - Nuke_Explode (ent); + ent->s.frame = 6; + } + + if (gi.pointcontents(ent->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA)) + { + Nuke_Explode(ent); return; } @@ -1226,22 +838,21 @@ void Nuke_Think(edict_t *ent) ent->health = 1; ent->owner = NULL; - gi.WriteByte (svc_muzzleflash); - gi.WriteShort (ent-g_edicts); - gi.WriteByte (muzzleflash); - gi.multicast (ent->s.origin, MULTICAST_PVS); + gi.WriteByte(svc_muzzleflash); + gi.WriteShort(ent - g_edicts); + gi.WriteByte(muzzleflash); + gi.multicast(ent->s.origin, MULTICAST_PVS); if (ent->timestamp <= level.time) { - - if ((ent->wait - level.time) <= (NUKE_TIME_TO_LIVE/2.0)) + if ((ent->wait - level.time) <= (NUKE_TIME_TO_LIVE / 2.0)) { - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, gi.soundindex ("weapons/nukewarn2.wav"), 1, attenuation, 0); + gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 0.3; } else { - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, gi.soundindex ("weapons/nukewarn2.wav"), 1, attenuation, 0); + gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 0.5; } } @@ -1250,52 +861,67 @@ void Nuke_Think(edict_t *ent) { if (ent->timestamp <= level.time) { - gi.sound (ent, CHAN_NO_PHS_ADD+CHAN_VOICE, gi.soundindex ("weapons/nukewarn2.wav"), 1, attenuation, 0); + gi.sound(ent, CHAN_NO_PHS_ADD + CHAN_VOICE, gi.soundindex("weapons/nukewarn2.wav"), 1, attenuation, 0); ent->timestamp = level.time + 1.0; } + ent->nextthink = level.time + FRAMETIME; } } -void nuke_bounce (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) -{ +void +nuke_bounce(edict_t *ent, edict_t *other /* unused */, cplane_t *plane /* unused */, + csurface_t *surf /* unused */) +{ + if (!ent) + { + return; + } + if (random() > 0.5) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); + } else - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); + } } - -extern byte P_DamageModifier(edict_t *ent); - -void fire_nuke (edict_t *self, vec3_t start, vec3_t aimdir, int speed) +void +fire_nuke(edict_t *self, vec3_t start, vec3_t aimdir, int speed) { - edict_t *nuke; - vec3_t dir; - vec3_t forward, right, up; - int damage_modifier; + edict_t *nuke; + vec3_t dir; + vec3_t forward, right, up; + int damage_modifier; + + if (!self) + { + return; + } + + damage_modifier = (int)P_DamageModifier(self); - damage_modifier = (int) P_DamageModifier (self); - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); + vectoangles2(aimdir, dir); + AngleVectors(dir, forward, right, up); nuke = G_Spawn(); - VectorCopy (start, nuke->s.origin); - VectorScale (aimdir, speed, nuke->velocity); + VectorCopy(start, nuke->s.origin); + VectorScale(aimdir, speed, nuke->velocity); - VectorMA (nuke->velocity, 200 + crandom() * 10.0, up, nuke->velocity); - VectorMA (nuke->velocity, crandom() * 10.0, right, nuke->velocity); - VectorClear (nuke->avelocity); - VectorClear (nuke->s.angles); + VectorMA(nuke->velocity, 200 + crandom() * 10.0, up, nuke->velocity); + VectorMA(nuke->velocity, crandom() * 10.0, right, nuke->velocity); + VectorClear(nuke->avelocity); + VectorClear(nuke->s.angles); nuke->movetype = MOVETYPE_BOUNCE; nuke->clipmask = MASK_SHOT; nuke->solid = SOLID_BBOX; nuke->s.effects |= EF_GRENADE; nuke->s.renderfx |= RF_IR_VISIBLE; - VectorSet (nuke->mins, -8, -8, 0); - VectorSet (nuke->maxs, 8, 8, 16); - nuke->s.modelindex = gi.modelindex ("models/weapons/g_nuke/tris.md2"); + VectorSet(nuke->mins, -8, -8, 0); + VectorSet(nuke->maxs, 8, 8, 16); + nuke->s.modelindex = gi.modelindex("models/weapons/g_nuke/tris.md2"); nuke->owner = self; nuke->teammaster = self; nuke->nextthink = level.time + FRAMETIME; @@ -1307,87 +933,105 @@ void fire_nuke (edict_t *self, vec3_t start, vec3_t aimdir, int speed) nuke->takedamage = DAMAGE_YES; nuke->svflags |= SVF_DAMAGEABLE; nuke->dmg = NUKE_DAMAGE * damage_modifier; + if (damage_modifier == 1) + { nuke->dmg_radius = NUKE_RADIUS; + } else - nuke->dmg_radius = NUKE_RADIUS + NUKE_RADIUS*(0.25*(float)damage_modifier); + { + nuke->dmg_radius = NUKE_RADIUS + NUKE_RADIUS * (0.25 * (float)damage_modifier); + } nuke->classname = "nuke"; nuke->die = nuke_die; - gi.linkentity (nuke); + gi.linkentity(nuke); } -#endif - -// ************************* -// TESLA -// ************************* - -#ifdef INCLUDE_TESLA -#define TESLA_TIME_TO_LIVE 30 -#define TESLA_DAMAGE_RADIUS 128 -#define TESLA_DAMAGE 3 // 3 -#define TESLA_KNOCKBACK 8 - -#define TESLA_ACTIVATE_TIME 3 - -#define TESLA_EXPLOSION_DAMAGE_MULT 50 // this is the amount the damage is multiplied by for underwater explosions -#define TESLA_EXPLOSION_RADIUS 200 - -void tesla_remove (edict_t *self) +void +tesla_remove(edict_t *self) { - edict_t *cur, *next; - + edict_t *cur, *next; + + if (!self) + { + return; + } + self->takedamage = DAMAGE_NO; - if(self->teamchain) + + if (self->teamchain) { cur = self->teamchain; - while(cur) + + while (cur) { next = cur->teamchain; - G_FreeEdict ( cur ); + G_FreeEdict(cur); cur = next; } } else if (self->air_finished) - gi.dprintf ("tesla without a field!\n"); + { + gi.dprintf("tesla without a field!\n"); + } - self->owner = self->teammaster; // Going away, set the owner correctly. - // PGM - grenade explode does damage to self->enemy + self->owner = self->teammaster; /* Going away, set the owner correctly. */ self->enemy = NULL; - // play quad sound if quadded and an underwater explosion - if ((self->dmg_radius) && (self->dmg > (TESLA_DAMAGE*TESLA_EXPLOSION_DAMAGE_MULT))) + /* play quad sound if quadded and an underwater explosion */ + if ((self->dmg_radius) && (self->dmg > (TESLA_DAMAGE * TESLA_EXPLOSION_DAMAGE_MULT))) + { gi.sound(self, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + } Grenade_Explode(self); } -void tesla_die(edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point) -{ +void +tesla_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker /* unused */, + int damage /* unused */, vec3_t point /* unused */) +{ + if (!self) + { + return; + } + tesla_remove(self); } -void tesla_blow (edict_t *self) -{ +void +tesla_blow(edict_t *self) +{ + if (!self) + { + return; + } + self->dmg = self->dmg * TESLA_EXPLOSION_DAMAGE_MULT; self->dmg_radius = TESLA_EXPLOSION_RADIUS; tesla_remove(self); } - -void tesla_zap (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +void +tesla_zap(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { } -void tesla_think_active (edict_t *self) +void +tesla_think_active(edict_t *self) { - int i,num; - edict_t *touch[MAX_EDICTS], *hit; - vec3_t dir, start; - trace_t tr; - - if(level.time > self->air_finished) + int i, num; + edict_t *touch[MAX_EDICTS], *hit; + vec3_t dir, start; + trace_t tr; + + if (!self) + { + return; + } + + if (level.time > self->air_finished) { tesla_remove(self); return; @@ -1396,95 +1040,124 @@ void tesla_think_active (edict_t *self) VectorCopy(self->s.origin, start); start[2] += 16; - num = gi.BoxEdicts(self->teamchain->absmin, self->teamchain->absmax, touch, MAX_EDICTS, AREA_SOLID); - for(i=0;iinuse)) - break; + num = gi.BoxEdicts(self->teamchain->absmin, self->teamchain->absmax, + touch, MAX_EDICTS, AREA_SOLID); - hit=touch[i]; - if(!hit->inuse) + for (i = 0; i < num; i++) + { + /* if the tesla died while zapping things, stop zapping. */ + if (!(self->inuse)) + { + break; + } + + hit = touch[i]; + + if (!hit->inuse) + { continue; - if(hit == self) + } + + if (hit == self) + { continue; - if(hit->health < 1) + } + + if (hit->health < 1) + { continue; - // don't hit clients in single-player or coop - if(hit->client) + } + + /* don't hit clients in single-player or coop */ + if (hit->client) + { if (coop->value || !deathmatch->value) + { continue; - if(!(hit->svflags & (SVF_MONSTER | SVF_DAMAGEABLE)) && !hit->client) + } + } + + if (!(hit->svflags & (SVF_MONSTER | SVF_DAMAGEABLE)) && !hit->client) + { continue; - - tr = gi.trace(start, vec3_origin, vec3_origin, hit->s.origin, self, MASK_SHOT); - if(tr.fraction==1 || tr.ent==hit)// || tr.ent->client || (tr.ent->svflags & (SVF_MONSTER | SVF_DAMAGEABLE))) + } + + tr = gi.trace(start, vec3_origin, vec3_origin, hit->s.origin, + self, MASK_SHOT); + + if ((tr.fraction == 1) || (tr.ent == hit)) { VectorSubtract(hit->s.origin, start, dir); - - // PMM - play quad sound if it's above the "normal" damage + + /* play quad sound if it's above the "normal" damage */ if (self->dmg > TESLA_DAMAGE) + { gi.sound(self, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); + } - // PGM - don't do knockback to walking monsters - if((hit->svflags & SVF_MONSTER) && !(hit->flags & (FL_FLY|FL_SWIM))) - T_Damage (hit, self, self->teammaster, dir, tr.endpos, tr.plane.normal, - self->dmg, 0, 0, MOD_TESLA); + /* don't do knockback to walking monsters */ + if ((hit->svflags & SVF_MONSTER) && + !(hit->flags & (FL_FLY | FL_SWIM))) + { + T_Damage(hit, self, self->teammaster, dir, tr.endpos, + tr.plane.normal, self->dmg, 0, 0, MOD_TESLA); + } else - T_Damage (hit, self, self->teammaster, dir, tr.endpos, tr.plane.normal, - self->dmg, TESLA_KNOCKBACK, 0, MOD_TESLA); + { + T_Damage(hit, self, self->teammaster, dir, tr.endpos, tr.plane.normal, + self->dmg, TESLA_KNOCKBACK, 0, MOD_TESLA); + } - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_LIGHTNING); - gi.WriteShort (hit - g_edicts); // destination entity - gi.WriteShort (self - g_edicts); // source entity - gi.WritePosition (tr.endpos); - gi.WritePosition (start); - gi.multicast (start, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_LIGHTNING); + gi.WriteShort(hit - g_edicts); /* destination entity */ + gi.WriteShort(self - g_edicts); /* source entity */ + gi.WritePosition(tr.endpos); + gi.WritePosition(start); + gi.multicast(start, MULTICAST_PVS); } } - if(self->inuse) + if (self->inuse) { self->think = tesla_think_active; self->nextthink = level.time + FRAMETIME; } } -void tesla_activate (edict_t *self) +void +tesla_activate(edict_t *self) { - edict_t *trigger; - edict_t *search; - - if (gi.pointcontents (self->s.origin) & (CONTENTS_SLIME|CONTENTS_LAVA|CONTENTS_WATER)) + edict_t *trigger; + edict_t *search; + + if (!self) { - tesla_blow (self); + return; + } + + if (gi.pointcontents(self->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_WATER)) + { + tesla_blow(self); return; } - // only check for spawn points in deathmatch + /* only check for spawn points in deathmatch */ if (deathmatch->value) { search = NULL; - while ((search = findradius(search, self->s.origin, 1.5*TESLA_DAMAGE_RADIUS)) != NULL) + + while ((search = findradius(search, self->s.origin, 1.5 * TESLA_DAMAGE_RADIUS)) != NULL) { - //if (!search->takedamage) - // continue; - // if it's a monster or player with health > 0 - // or it's a deathmatch start point - // and we can see it - // blow up - if(search->classname) + if (search->classname) { - if ( ( (!strcmp(search->classname, "info_player_deathmatch")) - || (!strcmp(search->classname, "info_player_start")) - || (!strcmp(search->classname, "info_player_coop")) - || (!strcmp(search->classname, "misc_teleporter_dest")) - ) - && (visible (search, self)) - ) + if (((!strcmp(search->classname, "info_player_deathmatch")) || + (!strcmp(search->classname, "info_player_start")) || + (!strcmp(search->classname, "info_player_coop")) || + (!strcmp(search->classname, "misc_teleporter_dest"))) && + (visible(search, self))) { - tesla_remove (self); + tesla_remove(self); return; } } @@ -1492,41 +1165,56 @@ void tesla_activate (edict_t *self) } trigger = G_Spawn(); - VectorCopy (self->s.origin, trigger->s.origin); - VectorSet (trigger->mins, -TESLA_DAMAGE_RADIUS, -TESLA_DAMAGE_RADIUS, self->mins[2]); - VectorSet (trigger->maxs, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS); + VectorCopy(self->s.origin, trigger->s.origin); + VectorSet(trigger->mins, -TESLA_DAMAGE_RADIUS, -TESLA_DAMAGE_RADIUS, self->mins[2]); + VectorSet(trigger->maxs, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS, TESLA_DAMAGE_RADIUS); trigger->movetype = MOVETYPE_NONE; trigger->solid = SOLID_TRIGGER; trigger->owner = self; trigger->touch = tesla_zap; trigger->classname = "tesla trigger"; - // doesn't need to be marked as a teamslave since the move code for bounce looks for teamchains - gi.linkentity (trigger); - VectorClear (self->s.angles); - // clear the owner if in deathmatch + /* doesn't need to be marked as a teamslave since the move code for bounce looks for teamchains */ + gi.linkentity(trigger); + + VectorClear(self->s.angles); + + /* clear the owner if in deathmatch */ if (deathmatch->value) + { self->owner = NULL; + } + self->teamchain = trigger; self->think = tesla_think_active; self->nextthink = level.time + FRAMETIME; self->air_finished = level.time + TESLA_TIME_TO_LIVE; } -void tesla_think (edict_t *ent) -{ - if (gi.pointcontents (ent->s.origin) & (CONTENTS_SLIME|CONTENTS_LAVA)) +void +tesla_think(edict_t *ent) +{ + if (!ent) { - tesla_remove (ent); return; } - VectorClear (ent->s.angles); + + if (gi.pointcontents(ent->s.origin) & (CONTENTS_SLIME | CONTENTS_LAVA)) + { + tesla_remove(ent); + return; + } - if(!(ent->s.frame)) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/teslaopen.wav"), 1, ATTN_NORM, 0); + VectorClear(ent->s.angles); + + if (!(ent->s.frame)) + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/teslaopen.wav"), 1, ATTN_NORM, 0); + } ent->s.frame++; - if(ent->s.frame > 14) + + if (ent->s.frame > 14) { ent->s.frame = 14; ent->think = tesla_activate; @@ -1534,421 +1222,516 @@ void tesla_think (edict_t *ent) } else { - if(ent->s.frame > 9) + if (ent->s.frame > 9) { - if(ent->s.frame == 10) + if (ent->s.frame == 10) { if (ent->owner && ent->owner->client) { - PlayerNoise(ent->owner, ent->s.origin, PNOISE_WEAPON); // PGM + PlayerNoise(ent->owner, ent->s.origin, PNOISE_WEAPON); /* PGM */ } + ent->s.skinnum = 1; } - else if(ent->s.frame == 12) + else if (ent->s.frame == 12) + { ent->s.skinnum = 2; - else if(ent->s.frame == 14) + } + else if (ent->s.frame == 14) + { ent->s.skinnum = 3; + } } + ent->think = tesla_think; ent->nextthink = level.time + 0.1; } } -void tesla_lava (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf) +void +tesla_lava(edict_t *ent, edict_t *other /* unused */, cplane_t *plane, csurface_t *surf /* unused */) { - vec3_t land_point; - + vec3_t land_point; + + if (!ent || !plane) + { + return; + } + if (plane->normal != 0) { - VectorMA (ent->s.origin, -20.0, plane->normal, land_point); - if (gi.pointcontents (land_point) & (CONTENTS_SLIME|CONTENTS_LAVA)) + VectorMA(ent->s.origin, -20.0, plane->normal, land_point); + + if (gi.pointcontents(land_point) & (CONTENTS_SLIME | CONTENTS_LAVA)) { - tesla_blow (ent); + tesla_blow(ent); return; } } + if (random() > 0.5) - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb1a.wav"), 1, ATTN_NORM, 0); + } else - gi.sound (ent, CHAN_VOICE, gi.soundindex ("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); + { + gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hgrenb2a.wav"), 1, ATTN_NORM, 0); + } } -void fire_tesla (edict_t *self, vec3_t start, vec3_t aimdir, int damage_multiplier, int speed) +void +fire_tesla(edict_t *self, vec3_t start, vec3_t aimdir, + int damage_multiplier, int speed) { - edict_t *tesla; - vec3_t dir; - vec3_t forward, right, up; - - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); + edict_t *tesla; + vec3_t dir; + vec3_t forward, right, up; + + if (!self) + { + return; + } + + vectoangles2(aimdir, dir); + AngleVectors(dir, forward, right, up); tesla = G_Spawn(); - VectorCopy (start, tesla->s.origin); - VectorScale (aimdir, speed, tesla->velocity); - VectorMA (tesla->velocity, 200 + crandom() * 10.0, up, tesla->velocity); - VectorMA (tesla->velocity, crandom() * 10.0, right, tesla->velocity); - VectorClear (tesla->s.angles); + VectorCopy(start, tesla->s.origin); + VectorScale(aimdir, speed, tesla->velocity); + VectorMA(tesla->velocity, 200 + crandom() * 10.0, up, tesla->velocity); + VectorMA(tesla->velocity, crandom() * 10.0, right, tesla->velocity); + VectorClear(tesla->s.angles); tesla->movetype = MOVETYPE_BOUNCE; tesla->solid = SOLID_BBOX; tesla->s.effects |= EF_GRENADE; tesla->s.renderfx |= RF_IR_VISIBLE; - VectorSet (tesla->mins, -12, -12, 0); - VectorSet (tesla->maxs, 12, 12, 20); - tesla->s.modelindex = gi.modelindex ("models/weapons/g_tesla/tris.md2"); - - tesla->owner = self; // PGM - we don't want it owned by self YET. + VectorSet(tesla->mins, -12, -12, 0); + VectorSet(tesla->maxs, 12, 12, 20); + tesla->s.modelindex = gi.modelindex("models/weapons/g_tesla/tris.md2"); + + tesla->owner = self; tesla->teammaster = self; tesla->wait = level.time + TESLA_TIME_TO_LIVE; tesla->think = tesla_think; tesla->nextthink = level.time + TESLA_ACTIVATE_TIME; - // blow up on contact with lava & slime code + /* blow up on contact with lava & slime code */ tesla->touch = tesla_lava; - if(deathmatch->value) - // PMM - lowered from 50 - 7/29/1998 + if (deathmatch->value) + { tesla->health = 20; + } else - tesla->health = 30; // FIXME - change depending on skill? + { + tesla->health = 30; + } tesla->takedamage = DAMAGE_YES; tesla->die = tesla_die; - tesla->dmg = TESLA_DAMAGE*damage_multiplier; + tesla->dmg = TESLA_DAMAGE * damage_multiplier; tesla->classname = "tesla"; tesla->svflags |= SVF_DAMAGEABLE; - tesla->clipmask = MASK_SHOT|CONTENTS_SLIME|CONTENTS_LAVA; + tesla->clipmask = MASK_SHOT | CONTENTS_SLIME | CONTENTS_LAVA; tesla->flags |= FL_MECHANICAL; - gi.linkentity (tesla); + gi.linkentity(tesla); } -#endif -// ************************* -// HEATBEAM -// ************************* - -#ifdef INCLUDE_BEAMS -void fire_beams (edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, int damage, int kick, int te_beam, int te_impact, int mod) +void +fire_beams(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, + int damage, int kick, int te_beam, int te_impact, int mod) { - trace_t tr; - vec3_t dir; - vec3_t forward, right, up; - vec3_t end; - vec3_t water_start, endpoint; - qboolean water = false, underwater = false; - int content_mask = MASK_SHOT | MASK_WATER; - vec3_t beam_endpt; + trace_t tr; + vec3_t dir; + vec3_t forward, right, up; + vec3_t end; + vec3_t water_start, endpoint; + qboolean water = false, underwater = false; + int content_mask = MASK_SHOT | MASK_WATER; + vec3_t beam_endpt; + + if (!self) + { + return; + } + + vectoangles2(aimdir, dir); + AngleVectors(dir, forward, right, up); - vectoangles2 (aimdir, dir); - AngleVectors (dir, forward, right, up); + VectorMA(start, 8192, forward, end); - VectorMA (start, 8192, forward, end); - - if (gi.pointcontents (start) & MASK_WATER) + if (gi.pointcontents(start) & MASK_WATER) { underwater = true; - VectorCopy (start, water_start); + VectorCopy(start, water_start); content_mask &= ~MASK_WATER; } - tr = gi.trace (start, NULL, NULL, end, self, content_mask); + tr = gi.trace(start, NULL, NULL, end, self, content_mask); - // see if we hit water + /* see if we hit water */ if (tr.contents & MASK_WATER) { water = true; - VectorCopy (tr.endpos, water_start); + VectorCopy(tr.endpos, water_start); - if (!VectorCompare (start, tr.endpos)) + if (!VectorCompare(start, tr.endpos)) { - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_HEATBEAM_SPARKS); - gi.WritePosition (water_start); - gi.WriteDir (tr.plane.normal); - gi.multicast (tr.endpos, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_HEATBEAM_SPARKS); + gi.WritePosition(water_start); + gi.WriteDir(tr.plane.normal); + gi.multicast(tr.endpos, MULTICAST_PVS); } - // re-trace ignoring water this time - tr = gi.trace (water_start, NULL, NULL, end, self, MASK_SHOT); - } - VectorCopy (tr.endpos, endpoint); - // halve the damage if target underwater + /* re-trace ignoring water this time */ + tr = gi.trace(water_start, NULL, NULL, end, self, MASK_SHOT); + } + + VectorCopy(tr.endpos, endpoint); + + /* halve the damage if target underwater */ if (water) { - damage = damage /2; + damage = damage / 2; } - // send gun puff / flash + /* send gun puff / flash */ if (!((tr.surface) && (tr.surface->flags & SURF_SKY))) { if (tr.fraction < 1.0) { if (tr.ent->takedamage) { - T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, DAMAGE_ENERGY, mod); + T_Damage(tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, + damage, kick, DAMAGE_ENERGY, mod); } else { - if ((!water) && (strncmp (tr.surface->name, "sky", 3))) + if ((!water) && (strncmp(tr.surface->name, "sky", 3))) { - // This is the truncated steam entry - uses 1+1+2 extra bytes of data - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_HEATBEAM_STEAM); - gi.WritePosition (tr.endpos); - gi.WriteDir (tr.plane.normal); - gi.multicast (tr.endpos, MULTICAST_PVS); + /* This is the truncated steam entry - uses 1+1+2 extra bytes of data */ + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_HEATBEAM_STEAM); + gi.WritePosition(tr.endpos); + gi.WriteDir(tr.plane.normal); + gi.multicast(tr.endpos, MULTICAST_PVS); if (self->client) + { PlayerNoise(self, tr.endpos, PNOISE_IMPACT); + } } } } } - // if went through water, determine where the end and make a bubble trail + /* if went through water, determine where the end and make a bubble trail */ if ((water) || (underwater)) { - vec3_t pos; + vec3_t pos; - VectorSubtract (tr.endpos, water_start, dir); - VectorNormalize (dir); - VectorMA (tr.endpos, -2, dir, pos); - if (gi.pointcontents (pos) & MASK_WATER) - VectorCopy (pos, tr.endpos); + VectorSubtract(tr.endpos, water_start, dir); + VectorNormalize(dir); + VectorMA(tr.endpos, -2, dir, pos); + + if (gi.pointcontents(pos) & MASK_WATER) + { + VectorCopy(pos, tr.endpos); + } else - tr = gi.trace (pos, NULL, NULL, water_start, tr.ent, MASK_WATER); + { + tr = gi.trace(pos, NULL, NULL, water_start, tr.ent, MASK_WATER); + } - VectorAdd (water_start, tr.endpos, pos); - VectorScale (pos, 0.5, pos); + VectorAdd(water_start, tr.endpos, pos); + VectorScale(pos, 0.5, pos); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_BUBBLETRAIL2); - gi.WritePosition (water_start); - gi.WritePosition (tr.endpos); - gi.multicast (pos, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_BUBBLETRAIL2); + gi.WritePosition(water_start); + gi.WritePosition(tr.endpos); + gi.multicast(pos, MULTICAST_PVS); } if ((!underwater) && (!water)) { - VectorCopy (tr.endpos, beam_endpt); + VectorCopy(tr.endpos, beam_endpt); } else { - VectorCopy (endpoint, beam_endpt); + VectorCopy(endpoint, beam_endpt); } - - gi.WriteByte (svc_temp_entity); - gi.WriteByte (te_beam); - gi.WriteShort (self - g_edicts); - gi.WritePosition (start); - gi.WritePosition (beam_endpt); - gi.multicast (self->s.origin, MULTICAST_ALL); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(te_beam); + gi.WriteShort(self - g_edicts); + gi.WritePosition(start); + gi.WritePosition(beam_endpt); + gi.multicast(self->s.origin, MULTICAST_ALL); } - -/* -================= -fire_heat - -Fires a single heat beam. Zap. -================= -*/ -void fire_heat (edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, int damage, int kick, qboolean monster) -{ - if (monster) - fire_beams (self, start, aimdir, offset, damage, kick, TE_MONSTER_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); - else - fire_beams (self, start, aimdir, offset, damage, kick, TE_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); -} - -#endif - - -// ************************* -// BLASTER 2 -// ************************* - -/* -================= -fire_blaster2 - -Fires a single green blaster bolt. Used by monsters, generally. -================= -*/ -void blaster2_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) -{ - int mod; - int damagestat; - - if (other == self->owner) +void +fire_heat(edict_t *self, vec3_t start, vec3_t aimdir, vec3_t offset, + int damage, int kick, qboolean monster) +{ + if (!self) + { return; + } + + if (monster) + { + fire_beams(self, start, aimdir, offset, damage, kick, + TE_MONSTER_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); + } + else + { + fire_beams(self, start, aimdir, offset, damage, + kick, TE_HEATBEAM, TE_HEATBEAM_SPARKS, MOD_HEATBEAM); + } +} + +/* + * Fires a single green blaster bolt. Used by monsters, generally. + */ +void +blaster2_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +{ + int mod; + int damagestat; + + if (!self || !other || !plane || !surf) + { + return; + } + + if (other == self->owner) + { + return; + } if (surf && (surf->flags & SURF_SKY)) { - G_FreeEdict (self); + G_FreeEdict(self); return; } if (self->owner && self->owner->client) + { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + } if (other->takedamage) { - // the only time players will be firing blaster2 bolts will be from the - // defender sphere. - if(self->owner->client) + /* the only time players will be firing blaster2 + bolts will be from the defender sphere. */ + if (self->owner->client) + { mod = MOD_DEFENDER_SPHERE; + } else + { mod = MOD_BLASTER2; + } if (self->owner) { damagestat = self->owner->takedamage; self->owner->takedamage = DAMAGE_NO; + if (self->dmg >= 5) - T_RadiusDamage(self, self->owner, self->dmg*3, other, self->dmg_radius, 0); - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); + { + T_RadiusDamage(self, self->owner, self->dmg * 3, other, + self->dmg_radius, 0); + } + + T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, + self->dmg, 1, DAMAGE_ENERGY, mod); self->owner->takedamage = damagestat; } else { if (self->dmg >= 5) - T_RadiusDamage(self, self->owner, self->dmg*3, other, self->dmg_radius, 0); - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); + { + T_RadiusDamage(self, self->owner, self->dmg * 3, other, + self->dmg_radius, 0); + } + + T_Damage(other, self, self->owner, self->velocity, self->s.origin, + plane->normal, self->dmg, 1, DAMAGE_ENERGY, mod); } } else { - //PMM - yeowch this will get expensive + /* yeowch this will get expensive */ if (self->dmg >= 5) - T_RadiusDamage(self, self->owner, self->dmg*3, self->owner, self->dmg_radius, 0); + { + T_RadiusDamage(self, self->owner, self->dmg * 3, self->owner, + self->dmg_radius, 0); + } + + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_BLASTER2); + gi.WritePosition(self->s.origin); - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_BLASTER2); - gi.WritePosition (self->s.origin); if (!plane) - gi.WriteDir (vec3_origin); + { + gi.WriteDir(vec3_origin); + } else - gi.WriteDir (plane->normal); - gi.multicast (self->s.origin, MULTICAST_PVS); + { + gi.WriteDir(plane->normal); + } + + gi.multicast(self->s.origin, MULTICAST_PVS); } - G_FreeEdict (self); + G_FreeEdict(self); } -void fire_blaster2 (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, int effect, qboolean hyper) +void +fire_blaster2(edict_t *self, vec3_t start, vec3_t dir, int damage, + int speed, int effect, qboolean hyper) { - edict_t *bolt; - trace_t tr; - - VectorNormalize (dir); + edict_t *bolt; + trace_t tr; + + if (!self) + { + return; + } + + VectorNormalize(dir); bolt = G_Spawn(); - VectorCopy (start, bolt->s.origin); - VectorCopy (start, bolt->s.old_origin); - vectoangles2 (dir, bolt->s.angles); - VectorScale (dir, speed, bolt->velocity); + VectorCopy(start, bolt->s.origin); + VectorCopy(start, bolt->s.old_origin); + vectoangles2(dir, bolt->s.angles); + VectorScale(dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->s.effects |= effect; - VectorClear (bolt->mins); - VectorClear (bolt->maxs); - - if (effect) - bolt->s.effects |= EF_TRACKER; - bolt->dmg_radius = 128; - bolt->s.modelindex = gi.modelindex ("models/proj/laser2/tris.md2"); - bolt->touch = blaster2_touch; + VectorClear(bolt->mins); + VectorClear(bolt->maxs); + + if (effect) + { + bolt->s.effects |= EF_TRACKER; + } + + bolt->dmg_radius = 128; + bolt->s.modelindex = gi.modelindex("models/proj/laser2/tris.md2"); + bolt->touch = blaster2_touch; bolt->owner = self; bolt->nextthink = level.time + 2; bolt->think = G_FreeEdict; bolt->dmg = damage; bolt->classname = "bolt"; - gi.linkentity (bolt); + gi.linkentity(bolt); if (self->client) - check_dodge (self, bolt->s.origin, dir, speed); + { + check_dodge(self, bolt->s.origin, dir, speed); + } + + tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); - tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); if (tr.fraction < 1.0) { - VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); - bolt->touch (bolt, tr.ent, NULL, NULL); + VectorMA(bolt->s.origin, -10, dir, bolt->s.origin); + bolt->touch(bolt, tr.ent, NULL, NULL); } -} +} -// ************************* -// tracker -// ************************* - -#define TRACKER_DAMAGE_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY | DAMAGE_NO_KNOCKBACK) -#define TRACKER_IMPACT_FLAGS (DAMAGE_NO_POWER_ARMOR | DAMAGE_ENERGY) - -#define TRACKER_DAMAGE_TIME 0.5 // seconds - -void tracker_pain_daemon_think (edict_t *self) +void +tracker_pain_daemon_think(edict_t *self) { - static vec3_t pain_normal = { 0, 0, 1 }; - int hurt; - - if(!self->inuse) - return; - - if((level.time - self->timestamp) > TRACKER_DAMAGE_TIME) + static vec3_t pain_normal = {0, 0, 1}; + int hurt; + + if (!self) { - if(!self->enemy->client) + return; + } + + if (!self->inuse) + { + return; + } + + if ((level.time - self->timestamp) > TRACKER_DAMAGE_TIME) + { + if (!self->enemy->client) + { self->enemy->s.effects &= ~EF_TRACKERTRAIL; - G_FreeEdict (self); + } + + G_FreeEdict(self); } else { - if(self->enemy->health > 0) + if (self->enemy->health > 0) { - T_Damage (self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, pain_normal, - self->dmg, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); - - // if we kill the player, we'll be removed. - if(self->inuse) + T_Damage(self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, + pain_normal, self->dmg, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); + + /* if we kill the player, we'll be removed. */ + if (self->inuse) { - // if we killed a monster, gib them. + /* if we killed a monster, gib them. */ if (self->enemy->health < 1) { - if(self->enemy->gib_health) - hurt = - self->enemy->gib_health; + if (self->enemy->gib_health) + { + hurt = -self->enemy->gib_health; + } else + { hurt = 500; + } - T_Damage (self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, - pain_normal, hurt, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); + T_Damage(self->enemy, self, self->owner, vec3_origin, self->enemy->s.origin, + pain_normal, hurt, 0, TRACKER_DAMAGE_FLAGS, MOD_TRACKER); } - if(self->enemy->client) + if (self->enemy->client) + { self->enemy->client->tracker_pain_framenum = level.framenum + 1; + } else + { self->enemy->s.effects |= EF_TRACKERTRAIL; - + } + self->nextthink = level.time + FRAMETIME; } } else { - if(!self->enemy->client) + if (!self->enemy->client) + { self->enemy->s.effects &= ~EF_TRACKERTRAIL; - G_FreeEdict (self); + } + + G_FreeEdict(self); } } } -void tracker_pain_daemon_spawn (edict_t *owner, edict_t *enemy, int damage) +void +tracker_pain_daemon_spawn(edict_t *owner, edict_t *enemy, int damage) { - edict_t *daemon; + edict_t *daemon; - if(enemy == NULL) + if (!owner || !enemy) + { return; + } daemon = G_Spawn(); daemon->classname = "pain daemon"; @@ -1960,144 +1743,178 @@ void tracker_pain_daemon_spawn (edict_t *owner, edict_t *enemy, int damage) daemon->dmg = damage; } -void tracker_explode (edict_t *self, cplane_t *plane) +void +tracker_explode(edict_t *self, cplane_t *plane) { - vec3_t dir; - - if(!plane) - VectorClear (dir); + vec3_t dir; + + if (!self) + { + return; + } + + if (!plane) + { + VectorClear(dir); + } else - VectorScale (plane->normal, 256, dir); + { + VectorScale(plane->normal, 256, dir); + } - gi.WriteByte (svc_temp_entity); - gi.WriteByte (TE_TRACKER_EXPLOSION); - gi.WritePosition (self->s.origin); - gi.multicast (self->s.origin, MULTICAST_PVS); + gi.WriteByte(svc_temp_entity); + gi.WriteByte(TE_TRACKER_EXPLOSION); + gi.WritePosition(self->s.origin); + gi.multicast(self->s.origin, MULTICAST_PVS); - G_FreeEdict (self); + G_FreeEdict(self); } -void tracker_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) +void +tracker_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf) { - float damagetime; - - if (other == self->owner) + float damagetime; + + if (!self || !other || !surf || !plane) + { return; + } + + if (other == self->owner) + { + return; + } if (surf && (surf->flags & SURF_SKY)) { - G_FreeEdict (self); + G_FreeEdict(self); return; } if (self->client) + { PlayerNoise(self->owner, self->s.origin, PNOISE_IMPACT); + } if (other->takedamage) { - if((other->svflags & SVF_MONSTER) || other->client) + if ((other->svflags & SVF_MONSTER) || other->client) { - if(other->health > 0) // knockback only for living creatures + if (other->health > 0) /* knockback only for living creatures */ { - // PMM - kickback was times 4 .. reduced to 3 - // now this does no damage, just knockback - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, - /* self->dmg */ 0, (self->dmg*3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); - - if (!(other->flags & (FL_FLY|FL_SWIM))) + T_Damage(other, self, self->owner, self->velocity, self->s.origin, + plane->normal, 0, (self->dmg * 3), TRACKER_IMPACT_FLAGS, + MOD_TRACKER); + + if (!(other->flags & (FL_FLY | FL_SWIM))) + { other->velocity[2] += 140; - - damagetime = ((float)self->dmg)*FRAMETIME; + } + + damagetime = ((float)self->dmg) * FRAMETIME; damagetime = damagetime / TRACKER_DAMAGE_TIME; - tracker_pain_daemon_spawn (self->owner, other, (int)damagetime); + tracker_pain_daemon_spawn(self->owner, other, (int)damagetime); } - else // lots of damage (almost autogib) for dead bodies + else /* lots of damage (almost autogib) for dead bodies */ { - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, - self->dmg*4, (self->dmg*3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); + T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, + self->dmg * 4, (self->dmg * 3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); } } - else // full damage in one shot for inanimate objects + else /* full damage in one shot for inanimate objects */ { - T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal, - self->dmg, (self->dmg*3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); + T_Damage(other, self, self->owner, self->velocity, self->s.origin, plane->normal, + self->dmg, (self->dmg * 3), TRACKER_IMPACT_FLAGS, MOD_TRACKER); } } - tracker_explode (self, plane); + tracker_explode(self, plane); return; } -void tracker_fly (edict_t *self) +void +tracker_fly(edict_t *self) { - vec3_t dest; - vec3_t dir; - vec3_t center; - + vec3_t dest; + vec3_t dir; + vec3_t center; + + if (!self) + { + return; + } + if ((!self->enemy) || (!self->enemy->inuse) || (self->enemy->health < 1)) { - tracker_explode (self, NULL); + tracker_explode(self, NULL); return; } - // PMM - try to hunt for center of enemy, if possible and not client - if(self->enemy->client) + /* try to hunt for center of enemy, if possible and not client */ + if (self->enemy->client) { - VectorCopy (self->enemy->s.origin, dest); + VectorCopy(self->enemy->s.origin, dest); dest[2] += self->enemy->viewheight; } - // paranoia - else if (VectorCompare(self->enemy->absmin, vec3_origin) || VectorCompare(self->enemy->absmax, vec3_origin)) + else if (VectorCompare(self->enemy->absmin, vec3_origin) || + VectorCompare(self->enemy->absmax, vec3_origin)) { - VectorCopy (self->enemy->s.origin, dest); + VectorCopy(self->enemy->s.origin, dest); } else { - VectorMA (vec3_origin, 0.5, self->enemy->absmin, center); - VectorMA (center, 0.5, self->enemy->absmax, center); - VectorCopy (center, dest); + VectorMA(vec3_origin, 0.5, self->enemy->absmin, center); + VectorMA(center, 0.5, self->enemy->absmax, center); + VectorCopy(center, dest); } - VectorSubtract (dest, self->s.origin, dir); - VectorNormalize (dir); - vectoangles2 (dir, self->s.angles); - VectorScale (dir, self->speed, self->velocity); + VectorSubtract(dest, self->s.origin, dir); + VectorNormalize(dir); + vectoangles2(dir, self->s.angles); + VectorScale(dir, self->speed, self->velocity); VectorCopy(dest, self->monsterinfo.saved_goal); self->nextthink = level.time + 0.1; } -void fire_tracker (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, edict_t *enemy) +void +fire_tracker(edict_t *self, vec3_t start, vec3_t dir, int damage, + int speed, edict_t *enemy) { - edict_t *bolt; - trace_t tr; - - VectorNormalize (dir); + edict_t *bolt; + trace_t tr; + + if (!self || !enemy) + { + return; + } + + VectorNormalize(dir); bolt = G_Spawn(); - VectorCopy (start, bolt->s.origin); - VectorCopy (start, bolt->s.old_origin); - vectoangles2 (dir, bolt->s.angles); - VectorScale (dir, speed, bolt->velocity); + VectorCopy(start, bolt->s.origin); + VectorCopy(start, bolt->s.old_origin); + vectoangles2(dir, bolt->s.angles); + VectorScale(dir, speed, bolt->velocity); bolt->movetype = MOVETYPE_FLYMISSILE; bolt->clipmask = MASK_SHOT; bolt->solid = SOLID_BBOX; bolt->speed = speed; bolt->s.effects = EF_TRACKER; - bolt->s.sound = gi.soundindex ("weapons/disrupt.wav"); - VectorClear (bolt->mins); - VectorClear (bolt->maxs); - - bolt->s.modelindex = gi.modelindex ("models/proj/disintegrator/tris.md2"); + bolt->s.sound = gi.soundindex("weapons/disrupt.wav"); + VectorClear(bolt->mins); + VectorClear(bolt->maxs); + + bolt->s.modelindex = gi.modelindex("models/proj/disintegrator/tris.md2"); bolt->touch = tracker_touch; bolt->enemy = enemy; bolt->owner = self; bolt->dmg = damage; bolt->classname = "tracker"; - gi.linkentity (bolt); + gi.linkentity(bolt); - if(enemy) + if (enemy) { bolt->nextthink = level.time + 0.1; bolt->think = tracker_fly; @@ -2109,13 +1926,15 @@ void fire_tracker (edict_t *self, vec3_t start, vec3_t dir, int damage, int spee } if (self->client) - check_dodge (self, bolt->s.origin, dir, speed); + { + check_dodge(self, bolt->s.origin, dir, speed); + } + + tr = gi.trace(self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); - tr = gi.trace (self->s.origin, NULL, NULL, bolt->s.origin, bolt, MASK_SHOT); if (tr.fraction < 1.0) { - VectorMA (bolt->s.origin, -10, dir, bolt->s.origin); - bolt->touch (bolt, tr.ent, NULL, NULL); + VectorMA(bolt->s.origin, -10, dir, bolt->s.origin); + bolt->touch(bolt, tr.ent, NULL, NULL); } -} - +}