thirtyflightsofloving/3zb2/p_weapon.c
Knightmare66 95295401a4 Added support for custom client railgun colors in 3ZB2, Awakening2, and Zaero DLLs.
Added weapon balancing and tech control cvars to 3ZB2 DLL.
Added Vampire and Ammogen techs to 3ZB2 game DLL.
Fixed func_door_secret movement bug (when built with origin brush) in Zaero DLL.
Fixed armor stacking bug in default Lazarus, missionpack, and Zaero DLLs.
Removed unused tech cvars in default Lazarus DLL.
Changed parsing of TE_BLASTER_COLORED tempent.
2021-10-31 03:53:09 -04:00

2631 lines
68 KiB
C
Raw Permalink Blame History

// g_weapon.c
#include "g_local.h"
#include "m_player.h"
#include "bot.h"
qboolean is_quad;
// RAFAEL
static qboolean is_quadfire;
static byte is_silenced;
static int damage_multiplier; // Knightmare added
void weapon_grenade_fire (edict_t *ent, qboolean held);
// RAFAEL
void weapon_trap_fire (edict_t *ent, qboolean held);
void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
{
vec3_t _distance;
VectorCopy (distance, _distance);
if (client->pers.hand == LEFT_HANDED)
_distance[1] *= -1;
else if (client->pers.hand == CENTER_HANDED)
_distance[1] = 0;
G_ProjectSource (point, _distance, forward, right, result);
}
/*
===============
PlayerNoise
Each player can have two noise objects associated with it:
a personal noise (jumping, pain, weapon firing), and a weapon
target noise (bullet wall impacts)
Monsters that don't directly see the player can move
to a noise in hopes of seeing the player from there.
===============
*/
void PlayerNoise(edict_t *who, vec3_t where, int type)
{
edict_t *noise;
if (type == PNOISE_WEAPON)
{
if (who->client->silencer_shots)
{
who->client->silencer_shots--;
return;
}
}
if (deathmatch->value)
return;
if (who->flags & FL_NOTARGET)
return;
if (!who->mynoise)
{
noise = G_Spawn();
noise->classname = "player_noise";
VectorSet (noise->mins, -8, -8, -8);
VectorSet (noise->maxs, 8, 8, 8);
noise->owner = who;
noise->svflags = SVF_NOCLIENT;
who->mynoise = noise;
noise = G_Spawn();
noise->classname = "player_noise";
VectorSet (noise->mins, -8, -8, -8);
VectorSet (noise->maxs, 8, 8, 8);
noise->owner = who;
noise->svflags = SVF_NOCLIENT;
who->mynoise2 = noise;
}
if (type == PNOISE_SELF || type == PNOISE_WEAPON)
{
noise = who->mynoise;
level.sound_entity = noise;
level.sound_entity_framenum = level.framenum;
}
else // type == PNOISE_IMPACT
{
noise = who->mynoise2;
level.sound2_entity = noise;
level.sound2_entity_framenum = level.framenum;
}
VectorCopy (where, noise->s.origin);
VectorSubtract (where, noise->maxs, noise->absmin);
VectorAdd (where, noise->maxs, noise->absmax);
noise->teleport_time = level.time;
gi.linkentity (noise);
}
void ShowGun(edict_t *ent);
qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
{
int index,i;
gitem_t *ammo,*item;
index = ITEM_INDEX(ent->item);
if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
&& other->client->pers.inventory[index])
{
if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
return false; // leave the weapon for others to pickup
}
other->client->pers.inventory[index]++;
if (!(ent->spawnflags & DROPPED_ITEM) )
{
// give them some ammo with it
ammo = FindItem (ent->item->ammo);
if ( (int)dmflags->value & DF_INFINITE_AMMO )
Add_Ammo (other, ammo, 1000);
else
Add_Ammo (other, ammo, ammo->quantity);
if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
{
if (deathmatch->value)
{
if ((int)(dmflags->value) & DF_WEAPONS_STAY)
ent->flags |= FL_RESPAWN;
else
SetRespawn (ent, 30);
}
if (coop->value)
ent->flags |= FL_RESPAWN;
}
}
if ((other->svflags & SVF_MONSTER) && ctf->value && other->client->zc.route_trace)
{
if (!other->client->zc.first_target)
{
for (i = 0;i < (5 * 2);i++)
{
if ((other->client->zc.routeindex + i) >= CurrentIndex) break;
if (Route[other->client->zc.routeindex + i].state == GRS_GRAPSHOT)
{
item = Fdi_GRAPPLE;//FindItem("Grapple");
if ( other->client->pers.inventory[ITEM_INDEX(item)]) item->use(other,item);
return true;
}
}
}
}
if (other->client->pers.weapon != ent->item &&
(other->client->pers.inventory[index] == 1) &&
( !deathmatch->value || other->client->pers.weapon == Fdi_BLASTER/*FindItem("blaster")*/ ) )
{
if (other->svflags & SVF_MONSTER) ent->item->use(other,ent->item);
else other->client->newweapon = ent->item;
}
if (other->svflags & SVF_MONSTER
&& (other->client->pers.weapon == Fdi_BLASTER/*FindItem("blaster") */
|| other->client->pers.weapon == Fdi_GRENADES/*FindItem("Grenades")*/))
{
ent->item->use(other,ent->item);//other->client->pers.weapon = ent->item;
ShowGun(other);
}
return true;
}
/*
===============
ChangeWeapon
The old weapon has been dropped all the way, so make the new one
current
===============
*/
// ### Hentai ### BEGIN
void ShowGun (edict_t *ent)
{
int i,j;
if (!ent->client->pers.weapon)
{
ent->s.modelindex2 = 0;
return;
}
if (!vwep->value)
{
ent->s.modelindex2 = MAX_MODELS-1;
return;
}
j = Get_KindWeapon(ent->client->pers.weapon);
if (j == WEAP_GRAPPLE) j = WEAP_BLASTER;
ent->s.modelindex2 = MAX_MODELS-1;
if (ent->client->pers.weapon)
i = ((j & 0xff) << 8);
else
i = 0;
ent->s.skinnum = (ent - g_edicts - 1) | i;
}
// ### Hentai ### END
void ChangeWeapon (edict_t *ent)
{
char *mdl;
#ifdef KMQUAKE2_ENGINE_MOD
int color;
#endif // KMQUAKE2_ENGINE_MOD
if (ent->client->grenade_time)
{
ent->client->grenade_time = level.time;
ent->client->weapon_sound = 0;
weapon_grenade_fire (ent, false);
ent->client->grenade_time = 0;
}
ent->client->pers.lastweapon = ent->client->pers.weapon;
ent->client->pers.weapon = ent->client->newweapon;
ent->client->newweapon = NULL;
ent->client->machinegun_shots = 0;
if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
else
ent->client->ammo_index = 0;
if (!ent->client->pers.weapon)
{ // dead
ent->client->ps.gunindex = 0;
return;
}
ent->client->weaponstate = WEAPON_ACTIVATING;
ent->client->ps.gunframe = 0;
// Knightmare- set blaster skin based on bolt color
#ifdef KMQUAKE2_ENGINE_MOD
if (ITEM_INDEX(ent->client->pers.weapon) == blaster_index)
{
// select color
color = (int)sk_blaster_color->value;
// blaster_color could be any other value, so clamp it
if ( ((int)sk_blaster_color->value < 1) || ((int)sk_blaster_color->value > 4) )
color = BLASTER_ORANGE;
// CTF color override
if ( (int)ctf->value && (int)ctf_blastercolors->value && ent->client )
color = (5 - ent->client->resp.ctf_team);
ent->client->ps.gunskin = max((color - 1), 0);
}
else if (ITEM_INDEX(ent->client->pers.weapon) == rg_index)
{
// select color
color = (int)sk_railgun_skin->value;
// CTF color override
if ( (int)ctf->value && (int)ctf_railcolors->value && ent->client )
color = (ent->client->resp.ctf_team - 1);
ent->client->ps.gunskin = min(max(color, 0), 3);
}
else
ent->client->ps.gunskin = 0;
#endif // KMQUAKE2_ENGINE_MOD
// lm ctf
mdl = ent->client->pers.weapon->view_model;
if (ctf->value == 2)
{
if (Q_stricmp (ent->client->pers.weapon->classname, "weapon_grapple") == 0)
{
mdl = "models/weapons/v_hook/tris.md2";
}
}
ent->client->ps.gunindex = gi.modelindex(mdl/*ent->client->pers.weapon->view_model*/);
//lm ctf
// ### Hentai ### BEGIN
ent->client->anim_priority = ANIM_PAIN;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crpain1;
ent->client->anim_end = FRAME_crpain4;
}
else
{
ent->s.frame = FRAME_pain301;
ent->client->anim_end = FRAME_pain304;
}
ShowGun(ent);
// ### Hentai ### END
}
/*
=================
NoAmmoWeaponChange
=================
*/
void NoAmmoWeaponChange (edict_t *ent)
{
gitem_t* item = NULL;
if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_SLUGS/*FindItem("slugs")*/)]
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_RAILGUN/*FindItem("railgun")*/)] )
{
item = Fdi_RAILGUN;//FindItem ("railgun");
// return;
}
// RAFAEL
else if ( ent->client->pers.inventory[ITEM_INDEX (Fdi_MAGSLUGS/*FindItem ("mag slug")*/)]
&& ent->client->pers.inventory[ITEM_INDEX (Fdi_PHALANX/*FindItem ("phalanx")*/)])
{
item = Fdi_PHALANX;//FindItem ("phalanx");
}
// RAFAEL
else if ( ent->client->pers.inventory[ITEM_INDEX (Fdi_CELLS/*FindItem ("cells")*/)]
&& ent->client->pers.inventory[ITEM_INDEX (Fdi_BOOMER/*FindItem ("ionripper")*/)])
{
item = Fdi_BOOMER;//FindItem ("ionrippergun");
}
else if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_CELLS/*FindItem("cells")*/)]
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_HYPERBLASTER/*FindItem("hyperblaster")*/)] )
{
item = Fdi_HYPERBLASTER;//FindItem ("hyperblaster");
// return;
}
else if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_BULLETS/*FindItem("bullets")*/)]
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_CHAINGUN/*FindItem("chaingun")*/)] )
{
item = Fdi_CHAINGUN;//FindItem ("chaingun");
// return;
}
else if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_BULLETS/*FindItem("bullets")*/)]
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_MACHINEGUN/*FindItem("machinegun")*/)] )
{
item = Fdi_MACHINEGUN;//FindItem ("machinegun");
// return;
}
else if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_SHELLS/*FindItem("shells")*/)] > 1
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_SUPERSHOTGUN/*FindItem("super shotgun")*/)] )
{
item = Fdi_SUPERSHOTGUN;//FindItem ("super shotgun");
// return;
}
else if ( ent->client->pers.inventory[ITEM_INDEX(Fdi_SHELLS/*FindItem("shells")*/)]
&& ent->client->pers.inventory[ITEM_INDEX(Fdi_SHOTGUN/*FindItem("shotgun")*/)] )
{
item = Fdi_SHOTGUN;//FindItem ("shotgun");
// return;
}
if (item == NULL) item = Fdi_BLASTER;//FindItem ("blaster");
if (ent->svflags & SVF_MONSTER) item->use(ent,item);
else ent->client->newweapon = item;
}
/*
=================
GetDamageModifier
// Knightmare- addded double damage
=================
*/
void GetDamageModifier (edict_t *ent)
{
is_quad = false;
damage_multiplier = 1;
if (ent->client->quad_framenum > level.framenum) {
is_quad = true;
damage_multiplier *= 4;
}
if (ent->client->double_framenum > level.framenum)
{
if ( (damage_multiplier == 1) ||
(deathmatch->value && !((int)(dmflags->value) & DF_NO_STACK_DOUBLE)) )
{
is_quad = true;
damage_multiplier *= 2;
}
}
}
/*
=================
Think_Weapon
Called by ClientBeginServerFrame and ClientThink
=================
*/
void Think_Weapon (edict_t *ent)
{
// if just died, put the weapon away
if (ent->health < 1)
{
ent->client->newweapon = NULL;
ChangeWeapon (ent);
}
// call active weapon think routine
if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
{
GetDamageModifier (ent); // Knightmare- addded double damage
// is_quad = (ent->client->quad_framenum > level.framenum);
// RAFAEL
is_quadfire = (ent->client->quadfire_framenum > level.framenum);
if (ent->client->silencer_shots)
is_silenced = MZ_SILENCED;
else
is_silenced = 0;
ent->client->pers.weapon->weaponthink (ent);
}
}
/*
================
Use_Weapon
Make the weapon ready if there is ammo
================
*/
void Use_Weapon (edict_t *ent, gitem_t *item)
{
int ammo_index;
gitem_t *ammo_item;
// see if we're already using it
if (item == ent->client->pers.weapon)
return;
if (ent->svflags & SVF_MONSTER)
{
if (ent->client->newweapon != NULL) return;
if (!Q_stricmp (item->pickup_name, "Blaster"))
{
ent->client->newweapon = item;
return;
}
}
if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
{
ammo_item = FindItem(item->ammo);
ammo_index = ITEM_INDEX(ammo_item);
if (!ent->client->pers.inventory[ammo_index])
{
if (!(ent->svflags & SVF_MONSTER)) gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
return;
}
if (ent->client->pers.inventory[ammo_index] < item->quantity)
{
if (!(ent->svflags & SVF_MONSTER)) gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
return;
}
}
// change to this weapon when down
ent->client->newweapon = item;
}
// RAFAEL 14-APR-98
void Use_Weapon2 (edict_t *ent, gitem_t *item)
{
int ammo_index;
gitem_t *ammo_item;
gitem_t *nextitem;
int index;
if (ent->svflags & SVF_MONSTER)
{
Use_Weapon(ent,item);
return;
}
if (strcmp (item->pickup_name, "HyperBlaster") == 0)
{
if (item == ent->client->pers.weapon)
{
item = Fdi_BOOMER;//FindItem ("Ionripper");
index = ITEM_INDEX (item);
if (!ent->client->pers.inventory[index])
{
item = Fdi_HYPERBLASTER;//FindItem ("HyperBlaster");
}
}
}
else if (strcmp (item->pickup_name, "Railgun") == 0)
{
ammo_item = FindItem(item->ammo);
ammo_index = ITEM_INDEX(ammo_item);
if (!ent->client->pers.inventory[ammo_index])
{
nextitem = Fdi_PHALANX;//FindItem ("Phalanx");
ammo_item = FindItem(nextitem->ammo);
ammo_index = ITEM_INDEX(ammo_item);
if (ent->client->pers.inventory[ammo_index])
{
item = Fdi_PHALANX;//FindItem ("Phalanx");
index = ITEM_INDEX (item);
if (!ent->client->pers.inventory[index])
{
item = Fdi_RAILGUN;//FindItem ("Railgun");
}
}
}
else if (item == ent->client->pers.weapon)
{
item = Fdi_PHALANX;//FindItem ("Phalanx");
index = ITEM_INDEX (item);
if (!ent->client->pers.inventory[index])
{
item = Fdi_RAILGUN;//FindItem ("Railgun");
}
}
}
// see if we're already using it
if (item == ent->client->pers.weapon)
return;
if (item->ammo)
{
ammo_item = FindItem(item->ammo);
ammo_index = ITEM_INDEX(ammo_item);
if (!ent->client->pers.inventory[ammo_index] && !g_select_empty->value)
{
gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
return;
}
}
// change to this weapon when down
ent->client->newweapon = item;
}
// END 14-APR-98
/*
================
Drop_Weapon
================
*/
void Drop_Weapon (edict_t *ent, gitem_t *item)
{
int index;
if ((int)(dmflags->value) & DF_WEAPONS_STAY)
return;
index = ITEM_INDEX(item);
// see if we're already using it
if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
{
if (!(ent->svflags & SVF_MONSTER)) gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
return;
}
Drop_Item (ent, item);
ent->client->pers.inventory[index]--;
}
/*
================
Weapon_Generic
A generic function to handle the basics of weapon thinking
================
*/
#define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1)
#define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
#define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
void Weapon_Generic2 (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent, qboolean altfire))
{
int n;
int current_weapon_index = ITEM_INDEX(ent->client->pers.weapon);
// Knightmare- activate and putaway sounds for ION Ripper
if (!strcmp (ent->client->pers.weapon->pickup_name, "ION Ripper") && sk_ionripper_extra_sounds->value)
{
if (ent->client->ps.gunframe == 0)
gi.sound (ent, CHAN_AUTO, gi.soundindex("weapons/ionactive.wav"), 1.0, ATTN_NORM, 0);
#ifdef KMQUAKE2_ENGINE_MOD
else if (ent->client->ps.gunframe == 37)
gi.sound (ent, CHAN_AUTO, gi.soundindex("weapons/ionaway.wav"), 1.0, ATTN_NORM, 0);
#endif
}
if (ent->client->weaponstate == WEAPON_DROPPING)
{
if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
{
ChangeWeapon (ent);
return;
}// ### Hentai ### BEGIN
else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
{
ent->client->anim_priority = ANIM_REVERSE;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crpain4+1;
ent->client->anim_end = FRAME_crpain1;
}
else
{
ent->s.frame = FRAME_pain304+1;
ent->client->anim_end = FRAME_pain301;
}
}
// ### Hentai ### END
ent->client->ps.gunframe++;
return;
}
if (ent->client->weaponstate == WEAPON_ACTIVATING)
{
if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
{
ent->client->weaponstate = WEAPON_READY;
ent->client->ps.gunframe = FRAME_IDLE_FIRST;
return;
}
ent->client->ps.gunframe++;
return;
}
if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
{
ent->client->weaponstate = WEAPON_DROPPING;
ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
// ### Hentai ### BEGIN
if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
{
ent->client->anim_priority = ANIM_REVERSE;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crpain4+1;
ent->client->anim_end = FRAME_crpain1;
}
else
{
ent->s.frame = FRAME_pain304+1;
ent->client->anim_end = FRAME_pain301;
}
}
// ### Hentai ### END
return;
}
if (ent->client->weaponstate == WEAPON_READY)
{
// Knightmare- catch alt fire commands
if ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK2)
{
// Add weapon alt attack handlers here
// Examples:
/* if (current_weapon_index == rl_index) // homing rocket switch
{
if (ent->client->pers.inventory[homing_index] > 0)
Use_Weapon (ent, FindItem("homing rocket launcher"));
ent->client->latched_buttons &= ~BUTTONS_ATTACK;
ent->client->buttons &= ~BUTTONS_ATTACK;
return;
}
else if (current_weapon_index == hml_index)
{
if (ent->client->pers.inventory[rockets_index] > 0)
Use_Weapon (ent, FindItem("rocket launcher"));
ent->client->latched_buttons &= ~BUTTONS_ATTACK;
ent->client->buttons &= ~BUTTONS_ATTACK;
return;
}*/
}
if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTONS_ATTACK) )
{
ent->client->latched_buttons &= ~BUTTONS_ATTACK;
if ((!ent->client->ammo_index) ||
( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
{
ent->client->ps.gunframe = FRAME_FIRE_FIRST;
ent->client->weaponstate = WEAPON_FIRING;
// start the animation
ent->client->anim_priority = ANIM_ATTACK;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crattak1-1;
ent->client->anim_end = FRAME_crattak9;
}
else
{
ent->s.frame = FRAME_attack1-1;
ent->client->anim_end = FRAME_attack8;
}
}
else
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
/*if (ent->client->pers.weapon) gi.bprintf(PRINT_HIGH,"weapon %s %i\n"
,ent->client->pers.weapon->pickup_name
,ent->client->ammo_index);*/
// ,ent->client->pers.inventory[ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo))]
// );
NoAmmoWeaponChange (ent);
}
}
else
{
if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
{
ent->client->ps.gunframe = FRAME_IDLE_FIRST;
return;
}
if (pause_frames)
{
for (n = 0; pause_frames[n]; n++)
{
if (ent->client->ps.gunframe == pause_frames[n])
{
if (rand()&15)
return;
}
}
}
ent->client->ps.gunframe++;
return;
}
}
if (ent->client->weaponstate == WEAPON_FIRING)
{
for (n = 0; fire_frames[n]; n++)
{
if (ent->client->ps.gunframe == fire_frames[n])
{
//ZOID
if (!CTFApplyStrengthSound(ent))
//ZOID
if (ent->client->quad_framenum > level.framenum)
gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
// Knightmare- addded double damage
else if (ent->client->double_framenum > level.framenum)
gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0);
//ZOID
CTFApplyHasteSound(ent);
//ZOID
fire (ent, ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK2));
break;
}
}
if (!fire_frames[n])
ent->client->ps.gunframe++;
if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
ent->client->weaponstate = WEAPON_READY;
}
}
//ZOID
void Weapon_Generic (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent, qboolean altfire))
{
int oldstate = ent->client->weaponstate;
Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST,
FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames,
fire_frames, fire);
// run the weapon frame again if hasted
if (Q_stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 &&
ent->client->weaponstate == WEAPON_FIRING)
return;
if ((CTFApplyHaste(ent) ||
(Q_stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 &&
ent->client->weaponstate != WEAPON_FIRING))
&& oldstate == ent->client->weaponstate) {
Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST,
FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames,
fire_frames, fire);
}
}
//ZOID
/*
======================================================================
GRENADE
======================================================================
*/
#define GRENADE_TIMER 3.0
#define GRENADE_MINSPEED 400
#define GRENADE_MAXSPEED 800
void weapon_grenade_fire (edict_t *ent, qboolean held)
{
vec3_t offset;
vec3_t forward, right;
vec3_t start;
int damage = sk_hand_grenade_damage->value; // was 125
float timer;
int speed;
float radius;
radius = sk_hand_grenade_radius->value; // was damage + 40
if (is_quad)
// damage *= 4;
damage *= damage_multiplier;
VectorSet(offset, 8, 8, ent->viewheight-8);
AngleVectors (ent->client->v_angle, forward, right, NULL);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
timer = ent->client->grenade_time - level.time;
speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
// ### Hentai ### BEGIN
/* if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->client->anim_priority = ANIM_ATTACK;
ent->s.frame = FRAME_crattak1-1;
ent->client->anim_end = FRAME_crattak3;
}
else
{
ent->client->anim_priority = ANIM_REVERSE;
ent->s.frame = FRAME_wave08;
ent->client->anim_end = FRAME_wave01;
}*/
// ### Hentai ### END
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
ent->client->grenade_time = level.time + 1.0;
if (ent->deadflag || ent->s.modelindex != MAX_MODELS-1) // VWep animations screw up corpses
{
return;
}
if (ent->health <= 0)
return;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->client->anim_priority = ANIM_ATTACK;
ent->s.frame = FRAME_crattak1-1;
ent->client->anim_end = FRAME_crattak3;
}
else
{
ent->client->anim_priority = ANIM_REVERSE;
ent->s.frame = FRAME_wave08;
ent->client->anim_end = FRAME_wave01;
}
}
void Weapon_Grenade (edict_t *ent)
{
if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
{
ChangeWeapon (ent);
return;
}
if (ent->client->weaponstate == WEAPON_ACTIVATING)
{
ent->client->weaponstate = WEAPON_READY;
ent->client->ps.gunframe = 16;
return;
}
if (ent->client->weaponstate == WEAPON_READY)
{
if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTONS_ATTACK) )
{
ent->client->latched_buttons &= ~BUTTONS_ATTACK;
if (ent->client->pers.inventory[ent->client->ammo_index])
{
ent->client->ps.gunframe = 1;
ent->client->weaponstate = WEAPON_FIRING;
ent->client->grenade_time = 0;
}
else
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
}
return;
}
if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
{
if (rand()&15)
return;
}
if (++ent->client->ps.gunframe > 48)
ent->client->ps.gunframe = 16;
return;
}
if (ent->client->weaponstate == WEAPON_FIRING)
{
if (ent->client->ps.gunframe == 5)
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
if (ent->client->ps.gunframe == 11)
{
if (!ent->client->grenade_time)
{
ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
}
// they waited too long, detonate it in their hand
if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
{
ent->client->weapon_sound = 0;
weapon_grenade_fire (ent, true);
ent->client->grenade_blew_up = true;
}
if (ent->client->buttons & BUTTONS_ATTACK)
return;
if (ent->client->grenade_blew_up)
{
if (level.time >= ent->client->grenade_time)
{
ent->client->ps.gunframe = 15;
ent->client->grenade_blew_up = false;
}
else
{
return;
}
}
}
if (ent->client->ps.gunframe == 12)
{
ent->client->weapon_sound = 0;
weapon_grenade_fire (ent, false);
}
if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
return;
ent->client->ps.gunframe++;
if (ent->client->ps.gunframe == 16)
{
ent->client->grenade_time = 0;
ent->client->weaponstate = WEAPON_READY;
}
}
}
/*
======================================================================
GRENADE LAUNCHER
======================================================================
*/
void weapon_grenadelauncher_fire (edict_t *ent, qboolean altfire)
{
vec3_t offset;
vec3_t forward, right;
vec3_t start;
int damage = sk_grenade_damage->value; // was 120
float radius;
radius = sk_grenade_radius->value; // was damage + 40
if (is_quad)
// damage *= 4;
damage += damage_multiplier;
VectorSet(offset, 8, 8, ent->viewheight-8);
AngleVectors (ent->client->v_angle, forward, right, NULL);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
// fire_grenade (ent, start, forward, damage, 600, 2.5, radius, altfire);
fire_grenade (ent, start, forward, damage, (int)sk_grenade_speed->value, 2.5, radius, altfire);
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_GRENADE | 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]--;
}
void Weapon_GrenadeLauncher (edict_t *ent)
{
static int pause_frames[] = {34, 51, 59, 0};
static int fire_frames[] = {6, 0};
Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
}
/*
======================================================================
ROCKET
======================================================================
*/
void fire_lockon_rocket (edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage);
void Weapon_RocketLauncher_Fire (edict_t *ent, qboolean altfire)
{
vec3_t offset, start;
vec3_t forward, right;
int damage;
float damage_radius;
int radius_damage;
// damage = 100 + (int)(random() * 20.0);
damage = (int)sk_rocket_damage->value + (int)(random() * (int)sk_rocket_damage2->value);
radius_damage = (int)sk_rocket_rdamage->value; // was 120
damage_radius = sk_rocket_radius->value; // was 120
if (is_quad)
{
// damage *= 4;
// radius_damage *= 4;
damage *= damage_multiplier;
radius_damage *= damage_multiplier;
}
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);
if (ent->client->zc.aiming != 4) {
fire_rocket (ent, start, forward, damage, (int)sk_rocket_speed->value, damage_radius, radius_damage); // was 650
}
else
{
damage -= 20;//<2F><><EFBFBD>b<EFBFBD>N<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD>20<32>_<EFBFBD><5F><EFBFBD>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD>
fire_lockon_rocket (ent, start, forward, damage, (int)sk_rocket_lockon_speed->value, damage_radius, radius_damage); // was 20
}
// 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]--;
// ent->client->ps.fov = 90; //<2F>Y<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ent->client->zc.aiming = 0; //<2F>Y<EFBFBD>[<5B><><EFBFBD>s<EFBFBD><73>
}
//<2F><><EFBFBD>b<EFBFBD>N<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD>P<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>`<60><><EFBFBD>[
void Weapon_LockonRocketLauncher_Fire (edict_t *ent, qboolean altfire)
{
vec3_t tmp,out,aim,min,max;
vec_t f;
trace_t rs_trace;
if (ent->client->buttons & BUTTONS_ATTACK)
{
ent->client->zc.lockon = false; //<2F>X<EFBFBD>i<EFBFBD>C<EFBFBD>p<EFBFBD>[<5B>Ƀ<EFBFBD><C983>b<EFBFBD>N<EFBFBD>I<EFBFBD><49><EFBFBD>@<40>\<5C>Ȃ<EFBFBD>
if (ent->client->zc.aiming == 0)
{
gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/sshotr1b.wav"), 1, ATTN_NONE, 0);
ent->client->zc.aiming = 3;
if (ent->client->zc.distance <10 || ent->client->zc.distance > 90) ent->client->zc.distance = 90;
ent->client->ps.fov = ent->client->zc.distance;//<2F>Y<EFBFBD>[<5B><><EFBFBD>J<EFBFBD>n
}
VectorSet (max, 8, 8, 8);
VectorSet (min, -8, -8, -8);
AngleVectors (ent->client->v_angle, aim, NULL , NULL);
VectorNormalize (aim);
VectorScale (aim, 8193, out);
VectorCopy (ent->s.origin, tmp);
if (ent->maxs[2] >= 32) tmp[2] += 22;
else tmp[2] -= 2;
VectorAdd(tmp,out,aim);
rs_trace = gi.trace (tmp, min, max, aim,ent, MASK_PLAYERSOLID);
if (rs_trace.ent != NULL)
{
if (Q_stricmp (rs_trace.ent->classname, "player") == 0)
{
if (ctf->value)
{
if (ent->client->resp.ctf_team != rs_trace.ent->client->resp.ctf_team)
{
ent->client->zc.lockon = true;
if (ent->client->zc.first_target != rs_trace.ent)
gi.sound (ent, CHAN_AUTO, gi.soundindex("3zb/locrloc.wav"), 1, ATTN_NORM, 0);
ent->client->zc.first_target = rs_trace.ent;
}
else ent->client->zc.first_target = NULL;
}
else
{
ent->client->zc.lockon = true;
if (ent->client->zc.first_target != rs_trace.ent)
gi.sound (ent, CHAN_AUTO, gi.soundindex("3zb/locrloc.wav"), 1, ATTN_NORM, 0);
ent->client->zc.first_target = rs_trace.ent;
}
return; //<2F>I<EFBFBD>[<5B>g<EFBFBD>Y<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
else ent->client->zc.first_target = NULL;
}
else ent->client->zc.first_target = NULL;
if (ent->client->zc.autozoom )
{
VectorSubtract(ent->s.origin,rs_trace.endpos,tmp);
f = VectorLength(tmp);
if (f < 200) ent->client->zc.distance = 90;
// else if (f < 300) ent->client->zc.distance = 75;
// else if (f < 500) ent->client->zc.distance = 60;
// else if (f < 800) ent->client->zc.distance = 45;
else if (f < 1300)
{
ent->client->zc.distance = 90 - (f - 200) / 14.6;//30;
}
else ent->client->zc.distance = 14;
if (ent->client->ps.fov != ent->client->zc.distance)
{
f = ent->client->ps.fov - ent->client->zc.distance;
if (f > 15 || f < -15 )
gi.sound (ent, CHAN_AUTO, gi.soundindex("3zb/zoom.wav"), 1, ATTN_NORM, 0);
ent->client->ps.fov = ent->client->zc.distance;
}
}
return;
}
ent->client->zc.aiming = 4;
Weapon_RocketLauncher_Fire (ent, altfire);
}
void Weapon_RocketLauncher (edict_t *ent)
{
static int pause_frames[] = {25, 33, 42, 50, 0};
static int fire_frames[] = {5, 0};
if (!(ent->client->buttons & BUTTONS_ATTACK)) ent->client->zc.aiming = 0; //<2F>A<EFBFBD>N<EFBFBD>e<EFBFBD>B<EFBFBD>x<EFBFBD>[<5B>g0
if (0/*1*/)
{
Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_LockonRocketLauncher_Fire);
}
else
{
Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
}
}
/*
======================================================================
BLASTER / HYPERBLASTER
======================================================================
*/
void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect, int color)
{
vec3_t forward, right;
vec3_t start;
vec3_t offset;
int muzzleflash;
if (is_quad)
// damage *= 4;
damage *= damage_multiplier;
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorSet(offset, 24, 8, ent->viewheight-8);
if (!(ent->svflags & SVF_MONSTER))
{
VectorAdd (offset, g_offset, offset);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
VectorScale (forward, -2, ent->client->kick_origin);
ent->client->kick_angles[0] = -1;
}
else
{
VectorSet(offset, 0, 0, ent->viewheight-8);
VectorAdd (offset, ent->s.origin, start);
}
if (!hyper)
fire_blaster (ent, start, forward, damage, (int)sk_blaster_speed->value, effect, hyper, color); // was 1000
else
fire_blaster (ent, start, forward, damage, (int)sk_hyperblaster_speed->value, effect, hyper, color); // was 1000
// Knightmare- changeable color muzzle flash
if (hyper)
{
if (color == BLASTER_GREEN)
#ifdef KMQUAKE2_ENGINE_MOD
muzzleflash = MZ_GREENHYPERBLASTER;
#else
muzzleflash = MZ_HYPERBLASTER;
#endif
else if (color == BLASTER_BLUE)
muzzleflash = MZ_BLUEHYPERBLASTER;
#ifdef KMQUAKE2_ENGINE_MOD
else if (color == BLASTER_RED)
muzzleflash = MZ_REDHYPERBLASTER;
#endif
else //standard orange
muzzleflash = MZ_HYPERBLASTER;
}
else
{
if (color == BLASTER_GREEN)
muzzleflash = MZ_BLASTER2;
else if (color == BLASTER_BLUE)
#ifdef KMQUAKE2_ENGINE_MOD
muzzleflash = MZ_BLUEBLASTER;
#else
muzzleflash = MZ_BLASTER;
#endif
#ifdef KMQUAKE2_ENGINE_MOD
else if (color == BLASTER_RED)
muzzleflash = MZ_REDBLASTER;
#endif
else //standard orange
muzzleflash = MZ_BLASTER;
}
// end Knightmare
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
/* if (hyper)
gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
else
gi.WriteByte (MZ_BLASTER | is_silenced); */
gi.WriteByte (muzzleflash | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
PlayerNoise(ent, start, PNOISE_WEAPON);
}
void Weapon_Blaster_Fire (edict_t *ent, qboolean altfire)
{
int damage;
int effect, color; // Knightmare added
if (deathmatch->value)
damage = (int)sk_blaster_damage_dm->value; // was 15
else
damage = (int)sk_blaster_damage->value; // was 10
// Knightmare- selectable color
color = (int)sk_blaster_color->value;
// blaster_color could be any other value, so clamp it
if ( ((int)sk_blaster_color->value < 1) || ((int)sk_blaster_color->value > 4) )
color = BLASTER_ORANGE;
// CTF color override
if ( (int)ctf->value && (int)ctf_blastercolors->value && ent->client )
color = (5 - ent->client->resp.ctf_team);
#ifndef KMQUAKE2_ENGINE_MOD
if (color == BLASTER_RED) color = BLASTER_ORANGE;
#endif
if (color == BLASTER_GREEN)
effect = (EF_BLASTER|EF_TRACKER);
else if (color == BLASTER_BLUE)
#ifdef KMQUAKE2_ENGINE_MOD
effect = EF_BLASTER|EF_BLUEHYPERBLASTER;
#else
effect = EF_BLUEHYPERBLASTER;
#endif
else if (color == BLASTER_RED)
effect = EF_BLASTER|EF_IONRIPPER;
else // standard orange
effect = EF_BLASTER;
// end Knightmare
// Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
Blaster_Fire (ent, vec3_origin, damage, false, effect, color);
ent->client->ps.gunframe++;
}
void Weapon_Blaster (edict_t *ent)
{
static int pause_frames[] = {19, 32, 0};
static int fire_frames[] = {5, 0};
Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
}
void Weapon_HyperBlaster_Fire (edict_t *ent, qboolean altfire)
{
float rotation;
vec3_t offset;
int effect;
int damage;
int color; // Knightmare added
ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
if (!(ent->client->buttons & BUTTONS_ATTACK))
{
ent->client->ps.gunframe++;
}
else
{
if (! ent->client->pers.inventory[ent->client->ammo_index] )
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
}
else
{
rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
offset[0] = -4 * sin(rotation);
offset[1] = 0;
offset[2] = 4 * cos(rotation);
// Knightmare- selectable color
color = (int)sk_hyperblaster_color->value;
// hyperblaster_color could be any other value, so clamp it
if ( ((int)sk_hyperblaster_color->value < 1) || ((int)sk_hyperblaster_color->value > 4) )
color = BLASTER_ORANGE;
// CTF color override
if ( (int)ctf->value && (int)ctf_blastercolors->value && ent->client )
color = 5-ent->client->resp.ctf_team;
#ifndef KMQUAKE2_ENGINE_MOD
if (color == BLASTER_RED) color = BLASTER_ORANGE;
#endif
if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
{
if (color == BLASTER_GREEN)
effect = (EF_HYPERBLASTER|EF_TRACKER);
else if (color == BLASTER_BLUE)
effect = EF_BLUEHYPERBLASTER;
else if (color == BLASTER_RED)
effect = EF_HYPERBLASTER|EF_IONRIPPER;
else // standard orange
effect = EF_HYPERBLASTER;
}
else
effect = 0;
// end Knightmare
/* if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
effect = EF_HYPERBLASTER;
else
effect = 0; */
if (deathmatch->value)
damage = (int)sk_hyperblaster_damage_dm->value; // was 15
else
damage = (int)sk_hyperblaster_damage->value; // was 20
Blaster_Fire (ent, offset, damage, true, effect, color);
// ### Hentai ### BEGIN
ent->client->anim_priority = ANIM_ATTACK;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crattak1 - 1;
ent->client->anim_end = FRAME_crattak9;
}
else
{
ent->s.frame = FRAME_attack1 - 1;
ent->client->anim_end = FRAME_attack8;
}
// ### Hentai ### END
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
}
ent->client->ps.gunframe++;
if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
ent->client->ps.gunframe = 6;
}
if (ent->client->ps.gunframe == 12)
{
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
ent->client->weapon_sound = 0;
}
}
void Weapon_HyperBlaster (edict_t *ent)
{
static int pause_frames[] = {0};
static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0};
Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
}
/*
======================================================================
MACHINEGUN / CHAINGUN
======================================================================
*/
void Machinegun_Fire (edict_t *ent, qboolean altfire)
{
int i;
vec3_t start;
vec3_t forward, right;
vec3_t angles;
int damage = (int)sk_machinegun_damage->value; // was 8
int kick = 2;
vec3_t offset;
if (!(ent->client->buttons & BUTTONS_ATTACK))
{
ent->client->machinegun_shots = 0;
ent->client->ps.gunframe++;
return;
}
if (ent->client->ps.gunframe == 5)
ent->client->ps.gunframe = 4;
else
ent->client->ps.gunframe = 5;
if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
{
ent->client->ps.gunframe = 6;
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
return;
}
if (is_quad)
{
// damage *= 4;
// kick *= 4;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
for (i=1 ; i<3 ; i++)
{
ent->client->kick_origin[i] = crandom() * 0.35;
ent->client->kick_angles[i] = crandom() * 0.7;
}
ent->client->kick_origin[0] = crandom() * 0.35;
ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
// raise the gun as it is firing
if (!deathmatch->value)
{
ent->client->machinegun_shots++;
if (ent->client->machinegun_shots > 9)
ent->client->machinegun_shots = 9;
}
// get start / end positions
VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
AngleVectors (angles, forward, right, NULL);
VectorSet(offset, 0, 8, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
// fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
fire_bullet (ent, start, forward, damage, kick, (int)sk_machinegun_hspread->value, (int)sk_machinegun_vspread->value, MOD_MACHINEGUN);
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_MACHINEGUN | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
PlayerNoise(ent, start, PNOISE_WEAPON);
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
ent->client->anim_priority = ANIM_ATTACK;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
ent->client->anim_end = FRAME_crattak9;
}
else
{
ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
ent->client->anim_end = FRAME_attack8;
}
ent->client->weaponstate = WEAPON_READY;
}
void Weapon_Machinegun (edict_t *ent)
{
static int pause_frames[] = {23, 45, 0};
static int fire_frames[] = {4, 5, 0};
Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
}
void Chaingun_Fire (edict_t *ent, qboolean altfire)
{
int i;
int shots;
vec3_t start;
vec3_t forward, right, up;
float r, u;
vec3_t offset;
int damage;
int kick = 2;
if (deathmatch->value)
damage = (int)sk_chaingun_damage_dm->value; // was 6
else
damage = (int)sk_chaingun_damage->value; //was 8
if (ent->client->ps.gunframe == 5)
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTONS_ATTACK))
{
ent->client->ps.gunframe = 32;
ent->client->weapon_sound = 0;
return;
}
else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTONS_ATTACK)
&& ent->client->pers.inventory[ent->client->ammo_index])
{
ent->client->ps.gunframe = 15;
}
else
{
ent->client->ps.gunframe++;
}
if (ent->client->ps.gunframe == 22)
{
ent->client->weapon_sound = 0;
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
}
else
{
ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
}
if (ent->client->ps.gunframe <= 9)
shots = 1;
else if (ent->client->ps.gunframe <= 14)
{
if (ent->client->buttons & BUTTONS_ATTACK)
shots = 2;
else
shots = 1;
}
else
shots = 3;
if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
shots = ent->client->pers.inventory[ent->client->ammo_index];
if (!shots)
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
return;
}
if (is_quad)
{
// damage *= 4;
// kick *= 4;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
for (i=0 ; i<3 ; i++)
{
ent->client->kick_origin[i] = crandom() * 0.35;
ent->client->kick_angles[i] = crandom() * 0.7;
}
for (i=0 ; i<shots ; i++)
{
// get start / end positions
AngleVectors (ent->client->v_angle, forward, right, up);
r = 7 + crandom()*4;
u = crandom()*4;
VectorSet(offset, 0, r, u + ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
// fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
fire_bullet (ent, start, forward, damage, kick, (int)sk_chaingun_hspread->value, (int)sk_chaingun_vspread->value, MOD_CHAINGUN);
}
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
PlayerNoise(ent, start, PNOISE_WEAPON);
// ### Hentai ### BEGIN
ent->client->anim_priority = ANIM_ATTACK;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crattak1 - 1 + (ent->client->ps.gunframe % 3);
ent->client->anim_end = FRAME_crattak9;
}
else
{
ent->s.frame = FRAME_attack1 - 1 + (ent->client->ps.gunframe % 3);
ent->client->anim_end = FRAME_attack8;
}
// ### Hentai ### END
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index] -= shots;
}
#if 0
void Gatringgun_Fire (edict_t *ent, qboolean altfire)
{
int i;
int shots;
vec3_t start;
vec3_t forward, right, up;
float r, u;
vec3_t offset;
int damage;
int kick = 2;
if (deathmatch->value)
damage = 8;
else
damage = 8;
if (ent->client->ps.gunframe == 5)
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTONS_ATTACK))
{
ent->client->ps.gunframe = 32;
ent->client->weapon_sound = 0;
return;
}
else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTONS_ATTACK)
&& ent->client->pers.inventory[ent->client->ammo_index])
{
ent->client->ps.gunframe = 15;
}
else
{
ent->client->ps.gunframe++;
}
if (ent->client->ps.gunframe == 22)
{
ent->client->weapon_sound = 0;
gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
}
else
{
ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
}
if (ent->client->ps.gunframe <= 9)
shots = 10;//1;
else if (ent->client->ps.gunframe <= 14)
{
if (ent->client->buttons & BUTTONS_ATTACK)
shots = 10;//2;
else
shots = 10;//1;
}
else
shots = 3;//3;
if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
shots = ent->client->pers.inventory[ent->client->ammo_index];
if (shots == 10 ) return;
if (!shots)
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
return;
}
if (is_quad)
{
// damage *= 4;
// kick *= 4;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
for (i=0 ; i<3 ; i++)
{
ent->client->kick_origin[i] = crandom() * 0.35;
ent->client->kick_angles[i] = crandom() * 0.7;
}
for (i=0 ; i<shots ; i++)
{
// get start / end positions
AngleVectors (ent->client->v_angle, forward, right, up);
r = 7 + crandom()*4;
u = crandom()*4;
VectorSet(offset, 0, r, u + ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
}
if (is_silenced) u = 0.5;
else u = 1.0;
gi.sound (ent, CHAN_AUTO, gi.soundindex("3zb/gatgf.wav"), u, ATTN_NORM, 0);
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte ((MZ_BLASTER) | MZ_SILENCED);
gi.multicast (ent->s.origin, MULTICAST_PVS);
PlayerNoise(ent, start, PNOISE_WEAPON);
// ### Hentai ### BEGIN
ent->client->anim_priority = ANIM_ATTACK;
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
{
ent->s.frame = FRAME_crattak1 - 1 + (ent->client->ps.gunframe % 3);
ent->client->anim_end = FRAME_crattak9;
}
else
{
ent->s.frame = FRAME_attack1 - 1 + (ent->client->ps.gunframe % 3);
ent->client->anim_end = FRAME_attack8;
}
// ### Hentai ### END
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index] -= 1;//shots;
}
#endif
void Weapon_Chaingun (edict_t *ent)
{
static int pause_frames[] = {38, 43, 51, 61, 0};
static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
#if 0
if (0)
Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Gatringgun_Fire);
else
#endif
{
Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
}
}
/*
======================================================================
SHOTGUN / SUPERSHOTGUN
======================================================================
*/
void weapon_shotgun_fire (edict_t *ent, qboolean altfire)
{
vec3_t start;
vec3_t forward, right;
vec3_t offset;
int damage = (int)sk_shotgun_damage->value; // was 4
int kick = 8;
if (ent->client->ps.gunframe == 9)
{
ent->client->ps.gunframe++;
return;
}
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;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
if (deathmatch->value)
// fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
fire_shotgun (ent, start, forward, damage, kick, (int)sk_shotgun_hspread->value, (int)sk_shotgun_vspread->value, (int)sk_shotgun_count->value, MOD_SHOTGUN);
else
// fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
fire_shotgun (ent, start, forward, damage, kick, (int)sk_shotgun_hspread->value, (int)sk_shotgun_vspread->value, (int)sk_shotgun_count->value, MOD_SHOTGUN);
// 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_WEAPON);
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
}
void Weapon_Shotgun (edict_t *ent)
{
static int pause_frames[] = {22, 28, 34, 0};
static int fire_frames[] = {8, 9, 0};
Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
}
void weapon_supershotgun_fire (edict_t *ent, qboolean altfire)
{
vec3_t start;
vec3_t forward, right;
vec3_t offset;
vec3_t v;
int damage = (int)sk_sshotgun_damage->value; // was 6
int kick = 12;
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;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
v[PITCH] = ent->client->v_angle[PITCH];
v[YAW] = ent->client->v_angle[YAW] - 5;
v[ROLL] = ent->client->v_angle[ROLL];
AngleVectors (v, forward, NULL, NULL);
// fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
fire_shotgun (ent, start, forward, damage, kick, (int)sk_sshotgun_hspread->value, (int)sk_sshotgun_vspread->value, (int)sk_sshotgun_count->value/2, MOD_SSHOTGUN);
v[YAW] = ent->client->v_angle[YAW] + 5;
AngleVectors (v, forward, NULL, NULL);
// fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
fire_shotgun (ent, start, forward, damage, kick, (int)sk_sshotgun_hspread->value, (int)sk_sshotgun_vspread->value, (int)sk_sshotgun_count->value/2, MOD_SSHOTGUN);
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_SSHOTGUN | 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] -= 2;
}
void Weapon_SuperShotgun (edict_t *ent)
{
static int pause_frames[] = {29, 42, 57, 0};
static int fire_frames[] = {7, 0};
Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
}
/*
======================================================================
RAILGUN
======================================================================
*/
void fire_sniperail (edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick);
void RSight_think (edict_t *ent)
{
trace_t rs_trace;
vec3_t aim,out,tmp;
vec3_t max,min;
vec_t f;
if (ent->owner->client->ps.gunframe != 4 || ent->owner->deadflag)
{
G_FreeEdict(ent);
return;
}
VectorSet (max, 4 ,4, 4);
VectorSet (min, -4, -4, -4);
AngleVectors (ent->owner->client->v_angle, aim, NULL , NULL);
VectorNormalize(aim);
VectorScale (aim, 8193, out);
VectorCopy(ent->owner->s.origin,tmp);
if (ent->owner->maxs[2] >= 32) tmp[2] += 22;
else tmp[2] -= 2;
VectorAdd(tmp,out,aim);
rs_trace = gi.trace (tmp, min, max, aim,ent->owner, MASK_PLAYERSOLID);
VectorCopy(rs_trace.endpos,ent->s.origin);
ent->nextthink = level.time + FRAMETIME;
if (rs_trace.ent != NULL)
{
if (Q_stricmp (rs_trace.ent->classname, "player") == 0) return;//<2F>I<EFBFBD>[<5B>g<EFBFBD>Y<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
if (ent->owner->client->zc.autozoom )
{
VectorSubtract(ent->s.origin,ent->owner->s.origin,tmp);
f = VectorLength(tmp);
if (f < 100) ent->owner->client->zc.distance = 90;
// else if (f < 300) ent->owner->client->zc.distance = 75;
// else if (f < 500) ent->owner->client->zc.distance = 60;
// else if (f < 800) ent->owner->client->zc.distance = 45;
else if (f < 1000)
{
ent->owner->client->zc.distance = 90 - (f - 100) / 12;//30;
}
else ent->owner->client->zc.distance = 15;
if (ent->owner->client->ps.fov != ent->owner->client->zc.distance)
{
f = ent->owner->client->ps.fov - ent->owner->client->zc.distance;
if ( f > 15 || f < -15)
gi.sound (ent->owner, CHAN_AUTO, gi.soundindex("3zb/zoom.wav"), 1, ATTN_NORM, 0);
ent->owner->client->ps.fov = ent->owner->client->zc.distance;
}
}
}
void weapon_railgun_fire (edict_t *ent, qboolean altfire)
{
vec3_t start;
vec3_t forward, right;
vec3_t offset;
int damage;
int kick;
int red=20, green=48, blue=176;
qboolean useColor=false;
if (deathmatch->value)
{ // normal damage is too extreme in dm
damage = (int)sk_railgun_damage_dm->value; // was 100
kick = 200;
}
else
{
damage = (int)sk_railgun_damage->value; // was 150
kick = 250;
}
if (is_quad)
{
// damage *= 4;
// kick *= 4;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
// Knightmare- CTF color override
if ( (int)ctf->value && (int)ctf_railcolors->value && ent->client )
{
useColor = true;
if (ent->client->resp.ctf_team == CTF_TEAM1) {
red = 176; green = 20; blue = 20;
}
else if (ent->client->resp.ctf_team == CTF_TEAM2) {
red = 20; green = 20; blue = 176;
}
/* else if (ent->client->resp.ctf_team == CTF_TEAM3) {
red = 20; green = 176; blue = 20;
} */
}
// Knightmare- custom client color
else if ( ent->client && (ent->client->pers.color1[3] != 0) )
{
useColor = true;
red = ent->client->pers.color1[0];
green = ent->client->pers.color1[1];
blue = ent->client->pers.color1[2];
}
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorScale (forward, -3, ent->client->kick_origin);
ent->client->kick_angles[0] = -3;
VectorSet(offset, 0, 7, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
if (ent->client->zc.aiming == 0) {
fire_rail (ent, start, forward, damage, kick, useColor, red, green, blue);
}
else
{
damage += 20;
fire_sniperail (ent, start, forward, damage, kick);
}
// gi.bprintf(PRINT_HIGH,"jj %i\n",ent->moveinfo.sound_start);
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_RAILGUN | 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]--;
// ent->client->ps.fov = 90; //<2F>Y<EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
ent->client->zc.aiming = 0; //<2F>Y<EFBFBD>[<5B><><EFBFBD>s<EFBFBD><73>
}
//<2F>X<EFBFBD>i<EFBFBD>C<EFBFBD>p<EFBFBD>[<5B>prail<69>K<EFBFBD><4B>
void Weapon_SnipeRailgun (edict_t *ent, qboolean altfire)
{
edict_t *sight;
if (ent->client->buttons & BUTTONS_ATTACK)
{
ent->client->zc.lockon = false; //<2F>X<EFBFBD>i<EFBFBD>C<EFBFBD>p<EFBFBD>[<5B>Ƀ<EFBFBD><C983>b<EFBFBD>N<EFBFBD>I<EFBFBD><49><EFBFBD>@<40>\<5C>Ȃ<EFBFBD>
if ( ent->client->zc.aiming == 0)
{
//<2F>T<EFBFBD>C<EFBFBD>g<EFBFBD>̍쐬
sight = G_Spawn();
VectorClear (sight->mins);
VectorClear (sight->maxs);
sight->movetype = MOVETYPE_FLYMISSILE;
sight->solid = SOLID_NOT;
sight->owner = ent;
sight->s.modelindex = gi.modelindex ("sprites/zsight.sp2");
sight->s.effects = 0;
sight->s.renderfx = RF_SHELL_RED;
sight->think = RSight_think;
sight->nextthink = level.time + FRAMETIME;
sight->classname = "rail sight";
if ( ent->client->resp.ctf_team == CTF_TEAM2 && ctf->value)
{
sight->s.frame = 1;
}
else sight->s.frame = 0;
gi.sound (ent, CHAN_WEAPON, gi.soundindex("weapons/sshotr1b.wav"), 1, ATTN_NONE, 0);
ent->client->zc.aiming = 1;
if (ent->client->zc.distance <10 || ent->client->zc.distance > 90) ent->client->zc.distance = 90;
ent->client->ps.fov = ent->client->zc.distance;//<2F>Y<EFBFBD>[<5B><><EFBFBD>J<EFBFBD>n
}
return;
}
// if (ent->client->buttons & BUTTONS_ATTACK) return;
ent->client->zc.aiming = 2;
weapon_railgun_fire (ent, altfire);
}
void Weapon_Railgun (edict_t *ent)
{
static int pause_frames[] = {56, 0};
static int fire_frames[] = {4, 0};
if (!(ent->client->buttons & BUTTONS_ATTACK)) ent->client->zc.aiming = 0; //<2F>A<EFBFBD>N<EFBFBD>e<EFBFBD>B<EFBFBD>x<EFBFBD>[<5B>g0
if (0)
{
Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, Weapon_SnipeRailgun/*weapon_railgun_fire*/);
}
else
{
Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
}
}
/*
======================================================================
BFG10K
======================================================================
*/
void weapon_bfg_fire (edict_t *ent, qboolean altfire)
{
vec3_t offset, start;
vec3_t forward, right;
int damage;
float damage_radius = sk_bfg_radius->value; // was 1000
if (deathmatch->value)
damage = (int)sk_bfg_damage_dm->value; // was 200
else
damage = (int)sk_bfg_damage->value; // was 500
if (ent->client->ps.gunframe == 9)
{
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_BFG | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
ent->client->ps.gunframe++;
PlayerNoise(ent, start, PNOISE_WEAPON);
return;
}
// cells can go down during windup (from power armor hits), so
// check again and abort firing if we don't have enough now
if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
{
ent->client->ps.gunframe++;
return;
}
if (is_quad)
// damage *= 4;
damage *= damage_multiplier;
AngleVectors (ent->client->v_angle, forward, right, NULL);
VectorScale (forward, -2, ent->client->kick_origin);
// make a big pitch kick with an inverse fall
ent->client->v_dmg_pitch = -40;
ent->client->v_dmg_roll = crandom()*8;
ent->client->v_dmg_time = level.time + DAMAGE_TIME;
VectorSet(offset, 8, 8, ent->viewheight-8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
fire_bfg (ent, start, forward, damage, (int)sk_bfg_speed->value, damage_radius); // was 400
ent->client->ps.gunframe++;
PlayerNoise(ent, start, PNOISE_WEAPON);
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index] -= 50;
}
void Weapon_BFG (edict_t *ent)
{
static int pause_frames[] = {39, 45, 50, 55, 0};
static int fire_frames[] = {9, 17, 0};
Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
// RAFAEL
if (is_quadfire)
Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
}
//======================================================================
// RAFAEL
/*
RipperGun
*/
void weapon_ionripper_fire (edict_t *ent, qboolean altfire)
{
vec3_t start;
vec3_t forward, right;
vec3_t offset;
vec3_t tempang;
int damage;
int kick;
if (deathmatch->value)
{
// tone down for deathmatch
damage = (int)sk_ionripper_damage_dm->value; // was 30
kick = (int)sk_ionripper_kick_dm->value; // was 40
}
else
{
damage = (int)sk_ionripper_damage->value; // was 50
kick = (int)sk_ionripper_kick->value; // was 60
}
if (is_quad)
{
// damage *= 4;
// kick *= 4;
damage *= damage_multiplier;
kick *= damage_multiplier;
}
VectorCopy (ent->client->v_angle, tempang);
tempang[YAW] += crandom();
AngleVectors (tempang, forward, right, NULL);
VectorScale (forward, -3, ent->client->kick_origin);
ent->client->kick_angles[0] = -3;
// VectorSet (offset, 0, 7, ent->viewheight - 8);
VectorSet (offset, 16, 7, ent->viewheight - 8);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
fire_ionripper (ent, start, forward, damage, (int)sk_ionripper_speed->value, EF_IONRIPPER); // was 500
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent - g_edicts);
gi.WriteByte (MZ_IONRIPPER | 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] -= ent->client->pers.weapon->quantity;
if (ent->client->pers.inventory[ent->client->ammo_index] < 0)
ent->client->pers.inventory[ent->client->ammo_index] = 0;
}
void Weapon_Ionripper (edict_t *ent)
{
static int pause_frames[] = {36, 0};
static int fire_frames[] = {5, 0};
Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire);
if (is_quadfire)
Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire);
}
//
// Phalanx
//
void weapon_phalanx_fire (edict_t *ent, qboolean altfire)
{
vec3_t start;
vec3_t forward, right, up;
vec3_t offset;
vec3_t v;
int kick = 12;
int damage;
float damage_radius;
int radius_damage;
// damage = 70 + (int)(random() * 10.0);
damage = (int)sk_phalanx_damage->value + (int)(random() * (int)sk_phalanx_damage2->value);
radius_damage = (int)sk_phalanx_radius_damage->value; // was 120
damage_radius = sk_phalanx_radius->value; // was 120
if (is_quad)
{
// damage *= 4;
// radius_damage *= damage_multiplier;
damage *= 4;
radius_damage *= damage_multiplier;
}
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 (ent->client->ps.gunframe == 8)
{
v[PITCH] = ent->client->v_angle[PITCH];
v[YAW] = ent->client->v_angle[YAW] - 1.5;
v[ROLL] = ent->client->v_angle[ROLL];
AngleVectors (v, forward, right, up);
radius_damage = 30;
damage_radius = 120;
fire_plasma (ent, start, forward, damage, (int)sk_phalanx_speed->value, damage_radius, radius_damage); // was 725
if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
}
else
{
v[PITCH] = ent->client->v_angle[PITCH];
v[YAW] = ent->client->v_angle[YAW] + 1.5;
v[ROLL] = ent->client->v_angle[ROLL];
AngleVectors (v, forward, right, up);
fire_plasma (ent, start, forward, damage, (int)sk_phalanx_speed->value, damage_radius, radius_damage); // was 725
// send muzzle flash
gi.WriteByte (svc_muzzleflash);
gi.WriteShort (ent-g_edicts);
gi.WriteByte (MZ_PHALANX | is_silenced);
gi.multicast (ent->s.origin, MULTICAST_PVS);
PlayerNoise(ent, start, PNOISE_WEAPON);
}
ent->client->ps.gunframe++;
}
void Weapon_Phalanx (edict_t *ent)
{
static int pause_frames[] = {29, 42, 55, 0};
static int fire_frames[] = {7, 8, 0};
Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire);
if (is_quadfire)
Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire);
}
/*
======================================================================
TRAP
======================================================================
*/
#define TRAP_TIMER 5.0
#define TRAP_MINSPEED 300
#define TRAP_MAXSPEED 700
void weapon_trap_fire (edict_t *ent, qboolean held)
{
vec3_t offset;
vec3_t forward, right;
vec3_t start;
int damage = 125;
float timer;
int speed;
float radius;
radius = damage+40;
if (is_quad)
// damage *= 4;
damage *= damage_multiplier;
VectorSet(offset, 8, 8, ent->viewheight-8);
AngleVectors (ent->client->v_angle, forward, right, NULL);
P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
timer = ent->client->grenade_time - level.time;
speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
// fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
fire_trap (ent, start, forward, damage, speed, timer, radius, held);
// you don't get infinite traps! ZOID
// if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
ent->client->pers.inventory[ent->client->ammo_index]--;
ent->client->grenade_time = level.time + 1.0;
}
void Weapon_Trap (edict_t *ent)
{
if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
{
ChangeWeapon (ent);
return;
}
if (ent->client->weaponstate == WEAPON_ACTIVATING)
{
ent->client->weaponstate = WEAPON_READY;
ent->client->ps.gunframe = 16;
return;
}
if (ent->client->weaponstate == WEAPON_READY)
{
if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTONS_ATTACK) )
{
ent->client->latched_buttons &= ~BUTTONS_ATTACK;
if (ent->client->pers.inventory[ent->client->ammo_index])
{
ent->client->ps.gunframe = 1;
ent->client->weaponstate = WEAPON_FIRING;
ent->client->grenade_time = 0;
}
else
{
if (level.time >= ent->pain_debounce_time)
{
gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
ent->pain_debounce_time = level.time + 1;
}
NoAmmoWeaponChange (ent);
}
return;
}
if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
{
if (rand()&15)
return;
}
if (++ent->client->ps.gunframe > 48)
ent->client->ps.gunframe = 16;
return;
}
if (ent->client->weaponstate == WEAPON_FIRING)
{
if (ent->client->ps.gunframe == 5)
// RAFAEL 16-APR-98
// gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/trapcock.wav"), 1, ATTN_NORM, 0);
// END 16-APR-98
if (ent->client->ps.gunframe == 11)
{
if (!ent->client->grenade_time)
{
ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
// RAFAEL 16-APR-98
ent->client->weapon_sound = gi.soundindex("weapons/traploop.wav");
// END 16-APR-98
}
// they waited too long, detonate it in their hand
if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
{
ent->client->weapon_sound = 0;
weapon_trap_fire (ent, true);
ent->client->grenade_blew_up = true;
}
if (ent->client->buttons & BUTTONS_ATTACK)
return;
if (ent->client->grenade_blew_up)
{
if (level.time >= ent->client->grenade_time)
{
ent->client->ps.gunframe = 15;
ent->client->grenade_blew_up = false;
}
else
{
return;
}
}
}
if (ent->client->ps.gunframe == 12)
{
ent->client->weapon_sound = 0;
weapon_trap_fire (ent, false);
if (ent->client->pers.inventory[ent->client->ammo_index] == 0)
NoAmmoWeaponChange (ent);
}
if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
return;
ent->client->ps.gunframe++;
if (ent->client->ps.gunframe == 16)
{
ent->client->grenade_time = 0;
ent->client->weaponstate = WEAPON_READY;
}
}
}