q2wf-portable/wf_knife.c

248 lines
5.8 KiB
C
Raw Normal View History

#include "g_local.h"
/*
==========================
Knife
==========================
*/
void drop_temp_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf);
void drop_make_touchable (edict_t *ent);
void WFRemoveDisguise(edict_t *ent);
void ChuckAmmoFromSentry(edict_t *ent)
{
edict_t *dropped;
vec3_t forward, right;
gitem_t *item;
int count;
if (ent->light_level <= 0) return;//out of ammo
item = FindItem("Bullets");
if (item == NULL)
{
//gi.dprintf("Cant find bullets item\n");
return;
}
dropped = G_Spawn();
dropped->classname = item->classname;
dropped->item = item;
dropped->spawnflags = DROPPED_ITEM;
dropped->s.effects = item->world_model_flags;
dropped->s.renderfx = RF_GLOW;
VectorSet (dropped->mins, -15, -15, -15);
VectorSet (dropped->maxs, 15, 15, 15);
gi.setmodel (dropped, dropped->item->world_model);
dropped->solid = SOLID_TRIGGER;
dropped->movetype = MOVETYPE_TOSS;
dropped->touch = drop_temp_touch;
dropped->owner = ent;
AngleVectors (ent->s.angles, forward, right, NULL);
VectorCopy (ent->s.origin, dropped->s.origin);
VectorScale (forward, 100, dropped->velocity);
dropped->velocity[2] = 300;
dropped->think = drop_make_touchable;
dropped->nextthink = level.time + 1;
//Do 100 bullets at a time
if (ent->light_level > 100)
count = 100;
else
count = ent->light_level;
dropped->count = count;
ent->light_level -= count;
gi.linkentity (dropped);
}
/*
=================
fire_stab
=================
*/
void fire_stab (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int mod)
{
trace_t tr;
edict_t *ignore;
// int mask;
// qboolean water;
vec3_t forward, wallp;
int content_mask = MASK_PLAYERSOLID |MASK_MONSTERSOLID |MASK_SHOT;
int bodypos; //Where on the body was the hit?
// VectorMA (start, 8192, aimdir, end);
// VectorCopy (start, from);
ignore = self;
// Setup "little look" to close wall
VectorCopy(self->s.origin,wallp);
// Cast along view angle
AngleVectors (self->client->v_angle, forward, NULL, NULL);
// Setup end point
wallp[0]=self->s.origin[0]+forward[0]*50;
wallp[1]=self->s.origin[1]+forward[1]*50;
wallp[2]=self->s.origin[2]+forward[2]*50;
// trace
tr = gi.trace (self->s.origin, NULL, NULL, wallp, self, content_mask);
// Line complete ? (ie. no collision)
if (tr.fraction == 1.0)
{
//gi.dprintf ("Too far from entity.\n");
//A complete miss will not remove your disguise
//if ((self->disguiseshots <= 0) && (self->disguised)) self->disguiseshots = 1;
return;
}
//gi.dprintf("Knife Hit %s\n", tr.ent->classname);
//Location damage! Was it a head or leg shot?
if (tr.ent->client)
{
if (self->disguised) WFRemoveDisguise(self);
if (tr.endpos[2] < (tr.ent->s.origin[2] - 10))
{
bodypos = 1; // leg shot
}
else if (tr.endpos[2] > ((tr.ent->s.origin[2] + 20)))
{
bodypos = 2;
}
else
{
bodypos = 0; //Body shot
//See if it was in the back!
if (!infront(tr.ent, self))
{
bodypos = 3; //in the back!
damage = damage * 5;
}
}
if (tr.ent->wf_team != self->wf_team)
{
//Play a hit sound
if (bodypos == 3)
gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/knifescream.wav"), 1, ATTN_NORM, 0);
else
gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/knifehit.wav"), 1, ATTN_NORM, 0);
}
else
damage = 0;
}
else
{
//For non-clients
//gi.dprintf("Hit item: %s\n",tr.ent->classname);
//If it is a sentry gun, remove some ammo
if (strcmp(tr.ent->classname, "SentryGun") == 0)
{
if ((tr.ent->wf_team != self->wf_team) && (self->client->player_special & SPECIAL_DISGUISE))
{
gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/knifehit.wav"), 1, ATTN_NORM, 0);
ChuckAmmoFromSentry(tr.ent);
damage = damage * .1;
//Hitting the sentry gun will not remove your disguise
//if (self->disguiseshots <= 0) self->disguiseshots = 1;
}
else
damage = 0;
}
//If it is a decoy, don't do much
else if (strcmp(tr.ent->classname, "decoy") == 0)
{
//gi.sound (self, CHAN_WEAPON, gi.soundindex("weapons/disembowel.wav"), 1, ATTN_NORM, 0);
}
//Otherwise, make it look like a bullet shot.
else
{
//damage = 0;
if (self->disguised) WFRemoveDisguise(self);
fire_bullet (self, start, aimdir, 0, kick, 0, 0, MOD_SNIPERRIFLE);
}
}
if ((damage) && (CanDamage(tr.ent, self)) )
T_Damage (tr.ent, self, self, aimdir, tr.endpos, tr.plane.normal, damage, kick, 0, mod);
// if (self->client)
// PlayerNoise(self, tr.endpos, PNOISE_IMPACT);
}
void weapon_knife_fire (edict_t *ent)
{
vec3_t start;
vec3_t forward, right;
vec3_t offset;
int damage = wf_game.weapon_damage[WEAPON_KNIFE];
int kick = 4;
if (ent->client->ps.gunframe == 11)
{
//Play a slicing cound
gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/knifeswish.wav"), 1, ATTN_NORM, 0);
ent->client->ps.gunframe++;
return;
}
//Must be frame 13 here then
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -2;
VectorSet(offset, 0, 8, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
if (is_quad)
{
damage *= 4;
kick *= 4;
}
fire_stab (ent, start, forward, damage, kick, MOD_KNIFE);
// send muzzle flash
// gi.WriteByte (svc_muzzleflash);
// gi.WriteShort (ent-g_edicts);
// gi.WriteByte (MZ_SHOTGUN | is_silenced);
// gi.multicast (ent->s.origin, MULTICAST_PVS);
ent->client->ps.gunframe++;
PlayerNoise(ent, start, PNOISE_IMPACT);
//does not take any ammo
// if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
// ent->client->pers.inventory[ent->client->ammo_index]--;
}
void Weapon_Knife (edict_t *ent)
{
static int pause_frames[] = {22, 28, 34, 0};
static int fire_frames[] = {11, 13, 0}; //Call fire frame on 8 and 13
Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_knife_fire);
}