q2wf-portable/w_stinger.c

205 lines
5.2 KiB
C

#include "g_local.h"
/*
======================================================================
Stinger Launcher
by Aleksey 'Fireball' Bragin, 08/12/1998
Modified by Gregg Reno 12/24/98
======================================================================
*/
void Rocket_Explode (edict_t *ent);
//If stinger touches anything, just go dead
void stinger_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
ent->s.sound = 0;
ent->movetype = MOVETYPE_BOUNCE;
ent->delay = level.time + 3;
//Play an impact sound
//gi.sound (ent, CHAN_WEAPON, gi.soundindex ("misc/fhit3.wav"), 1, ATTN_NORM, 0);
gi.sound (ent, CHAN_WEAPON, gi.soundindex ("darthit.wav"), 1, ATTN_NORM, 0);
}
void stinger_think (edict_t *ent)
{
edict_t *target = NULL;
edict_t *blip = NULL;
vec3_t targetdir, blipdir;
vec_t speed;
float dist;
//Blow up if we are past the delay time
if (level.time > ent->delay)
{
ent->nextthink = level.time + .1;
ent->think = Rocket_Explode;
return;
}
while ((blip = findradius(blip, ent->s.origin, 1000)) != NULL)
{
if (!blip->client)
continue;
if (blip == ent->creator)
continue;
if (blip->disguised)
continue;
//dont aim at same team unless friendly fire is on
if ((blip->wf_team == ent->wf_team) && (((int)wfflags->value & WF_ALLOW_FRIENDLY_FIRE)==0))
continue;
// if (!blip->takedamage)
// continue;
if (blip->health <= 0)
continue;
if (!visible(ent, blip))
continue;
if (!infront(ent, blip))
continue;
if ((!blip->client->thrusting) && (!blip->client->ctf_grapple))
continue;
//We have a possible target. If we are close
//enough, just blow up.
VectorSubtract(blip->s.origin, ent->s.origin, blipdir);
dist = VectorLength(blipdir);
if (dist < 100)
{
ent->nextthink = level.time + .1;
ent->think = Rocket_Explode;
return;
}
blipdir[2] += 16;
if ((target == NULL) || (VectorLength(blipdir) < VectorLength(targetdir)))
{
target = blip;
VectorCopy(blipdir, targetdir);
}
}
if (target != NULL)
{
// target acquired, nudge our direction toward it
VectorNormalize(targetdir);
VectorScale(targetdir, 0.28, targetdir);
VectorAdd(targetdir, ent->movedir, targetdir);
VectorNormalize(targetdir);
VectorCopy(targetdir, ent->movedir);
vectoangles(targetdir, ent->s.angles);
speed = VectorLength(ent->velocity);
VectorScale(targetdir, speed, ent->velocity);
//is this the first time we locked in? sound warning for the target
if (ent->homing_lock == 0)
{
// gi.sound (target, CHAN_AUTO, gi.soundindex ("homelock.wav"), 1, ATTN_NORM, 0);
// gi.sound (target, CHAN_AUTO, gi.soundindex ("misc/keyuse.wav"), 1, ATTN_NORM, 0);
ent->homing_lock = 1;
}
}
ent->nextthink = level.time + .1;
}
void fire_stinger (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage)
{
edict_t *rocket;
rocket = G_Spawn();
VectorCopy (start, rocket->s.origin);
VectorCopy (dir, rocket->movedir);
vectoangles (dir, rocket->s.angles);
VectorScale (dir, speed, rocket->velocity);
rocket->movetype = MOVETYPE_FLYMISSILE;
rocket->clipmask = MASK_SHOT;
rocket->solid = SOLID_BBOX;
rocket->s.effects |= EF_ROCKET;
VectorClear (rocket->mins);
VectorClear (rocket->maxs);
rocket->s.modelindex = gi.modelindex ("models/objects/rocket/tris.md2");
rocket->creator = self;
rocket->mod = MOD_STINGER;
rocket->touch = stinger_touch;
//Set the team of the rocket
rocket->wf_team = self->wf_team;
rocket->dmg = damage;
rocket->radius_dmg = radius_damage;
rocket->dmg_radius = damage_radius;
rocket->nextthink = level.time + .1;
rocket->think = stinger_think;
rocket->dmg = damage;
rocket->delay = level.time + 10; //blow up after 10 seconds no mater what
rocket->s.sound = gi.soundindex ("weapons/rockfly.wav");
rocket->classname = "rocket";
// Don't forget to set owner
rocket->owner = self;
gi.linkentity (rocket);
}
void Weapon_StingerLauncher_Fire (edict_t *ent)
{
vec3_t offset, start;
vec3_t forward, right;
int damage;
float damage_radius;
int radius_damage;
damage = wf_game.weapon_damage[WEAPON_STINGER];
radius_damage = 120;
damage_radius = 120;
if (is_quad)
{
damage *= 4;
radius_damage *= 4;
}
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
VectorSet(offset, 8, 8, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
fire_stinger (ent, start, forward, damage, wf_game.weapon_speed[WEAPON_STINGER], damage_radius, radius_damage);
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_ROCKET | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
ent->client->ps.gunframe++;
PlayerNoise(ent, start, PNOISE_WEAPON);
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index] -=5;
if (ent->client->pers.inventory[ent->client->ammo_index] < 0)
ent->client->pers.inventory[ent->client->ammo_index] = 0;
}
void Weapon_StingerLauncher (edict_t *ent)
{
static int pause_frames[] = {7, 0};
static int fire_frames[] = {2, 0};
Weapon_Generic (ent, 1, 6, 8, 10, pause_frames, fire_frames, Weapon_StingerLauncher_Fire);
}