thirtyflightsofloving/game/g_abel_gunarm.c
2020-06-12 12:21:21 -07:00

327 lines
No EOL
6.4 KiB
C

#include "g_local.h"
#define GUNARM_FIRERATE 4
#define BASEDAMAGE 40
#define RANDDAMAGE 30
#define BASEDISTANCE 2048
// ============================= TARGET_GUNARMS
void firetracer (edict_t *self, vec3_t pos, vec3_t dir)
{
edict_t *gib;
vec3_t forward;
edict_t *player;
player = &g_edicts[1]; // Gotta be, since this is SP only
gib = G_Spawn();
gi.setmodel (gib, "models/objects/tracer/tris.md2");
gib->solid = SOLID_NOT;
VectorCopy(pos, gib->s.origin);
gib->movetype = MOVETYPE_NOCLIP;
VectorNormalize(dir);
vectoangles(dir, gib->s.angles);
AngleVectors(dir, forward, NULL, NULL);
//gib->s.angles[PITCH] = player->client->ps.stats[STAT_GUNARM_PITCH] ;
//gib->s.angles[YAW] = player->client->ps.stats[STAT_GUNARM_YAW] + 90;
//vectoangles(forward, forward);
VectorScale (dir, 1536, gib->velocity);
//add player velocity
//VectorAdd (gib->velocity, self->velocity, gib->velocity);
gib->think = G_FreeEdict;
gib->nextthink = level.time + 0.4;
gi.linkentity (gib);
}
void gunarm_fire(edict_t *self, edict_t *badguy)
{
edict_t *player;
vec3_t playervec, viewang, aimdir, forward, right, armforward, muzzledir;
vec3_t hitpos;
//right 5
//forward 23
player = &g_edicts[1]; // Gotta be, since this is SP only
//left gun or right gun.
if (self->style <= 0)
self->style = 1;
else
self->style = 0;
AngleVectors (player->client->ps.viewangles, forward, right, NULL);
VectorCopy (player->s.origin, playervec);
forward[2] = 0;
VectorMA(playervec, 23, forward, playervec);
if (self->style <= 0)
VectorMA(playervec, 7, right, playervec);
else
VectorMA(playervec, -7, right, playervec);
playervec[2] += 5;
aimdir[PITCH] = player->client->ps.stats[STAT_GUNARM_PITCH] ;
aimdir[YAW] = player->client->ps.stats[STAT_GUNARM_YAW] + player->s.angles[YAW];
aimdir[ROLL] = 0;
AngleVectors (aimdir, armforward, NULL, NULL);
VectorMA(playervec, 29 , armforward, playervec); //distance from shoulder to gun muzzle.
//muzzle.
VectorSubtract ( badguy->s.origin,playervec, muzzledir);
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_SHOTGUN);
gi.WritePosition (playervec);
gi.WriteDir (muzzledir);
gi.multicast (playervec, MULTICAST_PVS);
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (player - g_edicts);
gi.WriteByte (MZ_MACHINEGUN);
gi.multicast (playervec, MULTICAST_PVS);
VectorCopy(badguy->s.origin, hitpos);
hitpos[2] += random() * 30;
firetracer(self, playervec, muzzledir);
T_Damage (badguy, player, player, vec3_origin, hitpos, vec3_origin, BASEDAMAGE + rand() % RANDDAMAGE, -10, DAMAGE_BULLET, MOD_UNKNOWN);
//advance the counter
self->count++;
if (self->count >= 56 && self->crane_dir <= 0)
{
self->crane_dir = 1;
G_UseTargets (self, self);
}
}
void gunarm_aimat(edict_t *self, edict_t *badguy)
{
if (self->density <= 0)
{
//fire gun.
self->density = GUNARM_FIRERATE;
gunarm_fire(self, badguy);
}
}
qboolean CheckBadguy(edict_t *self, edict_t *player, edict_t *badguy)
{
float dist;
vec3_t playervec;
float yawang, pitchang;
trace_t tr;
vec3_t playereyes;
dist = realrange(player,badguy);
if (dist > BASEDISTANCE)
return false; //too far.
VectorCopy (player->s.origin, playervec);
playervec[2] += 24;
VectorSubtract (playervec, badguy->s.origin, playervec);
vectoangles(playervec,playervec);
yawang = playervec[YAW] - player->s.angles[YAW] - 180;
if (yawang < -60 || yawang > 60)
return false;
pitchang = playervec[PITCH] + 360;
if (pitchang < -85 || pitchang > 85)
return false;
VectorCopy(player->s.origin, playereyes);
playereyes[2] += 24;
tr = gi.trace (
playereyes,
vec3_origin,
vec3_origin,
badguy->s.origin, //dest
player, //ignore
MASK_SOLID);//MASK_SOLID
if (tr.startsolid || tr.allsolid )
return false;
//gi.dprintf("%f\n", tr.fraction);
if (tr.fraction < 1)
return false;
player->client->ps.stats[STAT_GUNARM_YAW] = yawang;
player->client->ps.stats[STAT_GUNARM_PITCH] = -pitchang;
return true;
}
edict_t *FindBadguy(edict_t *self)
{
edict_t *player;
edict_t *badguy;
player = &g_edicts[1]; // Gotta be, since this is SP only
badguy = NULL;
badguy = G_Find(NULL, FOFS(classname), "monster_floater");
while(badguy)
{
if (CheckBadguy(self, player, badguy) == true)
return badguy;
badguy = G_Find(badguy, FOFS(classname), "monster_floater");
}
player->client->ps.stats[STAT_GUNARM_YAW] = sin(level.time / 2) * 30;
player->client->ps.stats[STAT_GUNARM_PITCH] = -12 + sin(level.time / 3) * 8;
return NULL;
}
void think_gunarms(edict_t *self)
{
edict_t *player;
edict_t *badguy;
player = &g_edicts[1]; // Gotta be, since this is SP only
//find a badguy
badguy = FindBadguy(self);
if (self->density > 0)
self->density--;
if (badguy)
{
//aim at bad guy.
gunarm_aimat(self, badguy);
}
self->think = think_gunarms;
self->nextthink = level.time + FRAMETIME;
}
void use_gunarms(edict_t *self, edict_t *other, edict_t *activator)
{
int modelIndex;
edict_t *player;
player = &g_edicts[1]; // Gotta be, since this is SP only
if (self->spawnflags & 1)
{
//turn off.
player->client->ps.stats[STAT_GUNARMS] = 0;
player->client->ps.stats[STAT_GUNARM_YAW] = 0;
player->client->ps.stats[STAT_GUNARM_PITCH] = 0;
return;
}
modelIndex = gi.modelindex (self->usermodel);
if (self->spawnflags & 2)
player->client->ps.stats[STAT_GUNARMS] = 1;
else
{
player->client->ps.stats[STAT_GUNARMS] = modelIndex;
self->think = think_gunarms;
self->nextthink = level.time + FRAMETIME;
}
}
void SP_target_gunarms(edict_t *self)
{
if (!self->usermodel && !(self->spawnflags & 1))
{
gi.dprintf("%s without a model at %s\n", self->classname, vtos(self->s.origin));
G_FreeEdict(self);
return;
}
self->use = use_gunarms;
self->svflags = SVF_NOCLIENT;
}
// =========== target_gunarmhide
void use_gunarmhide(edict_t *self, edict_t *other, edict_t *activator)
{
edict_t *player;
int modelindex;
player = &g_edicts[1]; // Gotta be, since this is SP only
if (self->spawnflags & 1)
{
//hide.
player->client->ps.stats[STAT_GUNARMS] = 0;
return;
}
//unhide.
modelindex = gi.modelindex (self->message);
player->client->ps.stats[STAT_GUNARMS] = modelindex;
}
void SP_target_gunarmhide(edict_t *self)
{
if (!self->message && !(self->spawnflags & 1))
{
gi.dprintf("%s without a message at %s. Using default: models/objects/gunarm/tris.md2\n", self->classname, vtos(self->s.origin));
self->message = "models/objects/gunarm/tris.md2";
}
self->use = use_gunarmhide;
self->svflags = SVF_NOCLIENT;
}