// g_weapon.c #include "g_local.h" #include "m_player.h" static qboolean is_quad; // RAFAEL static qboolean is_quadfire; static byte is_silenced; void weapon_grenade_fire (edict_t *ent, qboolean held); // RAFAEL void weapon_trap_fire (edict_t *ent, qboolean held); static 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) { if (deathmatch->value && type != PNOISE_WEAPON) return; VectorCopy( who->s.origin, who->noise_pos ); who->noise_time = level.time + 2; who->noise_type = type; VectorCopy( who->s.angles, who->noise_angles ); } #define MAX_PISTOL_ROUNDS 10 #define MAX_TOMMYGUN_ROUNDS 50 #define MAX_SHOTGUN_ROUNDS 8 #define MAX_BARMACHINEGUN_ROUNDS 30 #define MAX_GRENADELAUNCHER_ROUNDS 3 #define MAX_ROCKETLAUNCHER_ROUNDS 5 #define MAX_FLAMEGUN_ROUNDS 50 // this is here so we can simplify the auto-reload code. it's in the same order as clip_t int auto_rounds[] = { 0, MAX_PISTOL_ROUNDS, MAX_SHOTGUN_ROUNDS, MAX_TOMMYGUN_ROUNDS, MAX_BARMACHINEGUN_ROUNDS, MAX_GRENADELAUNCHER_ROUNDS, MAX_ROCKETLAUNCHER_ROUNDS, //MAX_FLAMEGUN_ROUNDS, 0 }; int QweryClipIndex (gitem_t *item); void AutoLoadWeapon( gclient_t *client, gitem_t *weapon, gitem_t *ammo ) { int clip_index; int ammo_index; if (((clip_index = QweryClipIndex( weapon )) != CLIP_NONE) && !(client->pers.weapon_clip[clip_index])) { ammo_index = ITEM_INDEX(ammo); if (client->pers.inventory[ammo_index] >= auto_rounds[clip_index]) { client->pers.weapon_clip[clip_index] = auto_rounds[clip_index]; client->pers.inventory[ammo_index] -= auto_rounds[clip_index]; } else // not quite enough ammo, so just load all ammo { client->pers.weapon_clip[clip_index] = client->pers.inventory[ammo_index]; client->pers.inventory[ammo_index] = 0; } } } qboolean Pickup_Weapon (edict_t *ent, edict_t *other) { int index; gitem_t *ammo; int auto_reload=false; 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 } // Ridah, start with gun loaded if (!(other->client->pers.inventory[index])) auto_reload = true; //other->client->pers.inventory[index]++; other->client->pers.inventory[index] = 1; if (ent->item->ammo && !(ent->spawnflags & DROPPED_ITEM) ) { // give them some ammo with it ammo = FindItem (ent->item->ammo); if ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) Add_Ammo (other, ammo, 1000); else Add_Ammo (other, ammo, ammo->quantity); if (auto_reload) AutoLoadWeapon( other->client, ent->item, ammo ); 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; } } else if (!(strcmp (ent->classname, "weapon_crowbar"))) { 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->client->pers.weapon == FindItem ("SPistol")) other->client->pers.silencer_shots = 20; /* if (other->client->pers.weapon != ent->item && (other->client->pers.inventory[index] == 1) && ( !deathmatch->value || other->client->pers.weapon == FindItem("Pipe") ) ) other->client->newweapon = ent->item; */ if (deathmatch->value) { if (other->client->pers.weapon != ent->item && auto_reload && (other->client->pers.weapon == FindItem ("Pistol") || other->client->pers.weapon == FindItem ("Pipe") )) other->client->newweapon = ent->item; } else { if (other->client->pers.weapon != ent->item && auto_reload) other->client->newweapon = ent->item; } return true; } /* Change Clip Index */ void ChangeClipIndex (edict_t *ent) { if (!strcmp(ent->client->pers.weapon->pickup_name, "Pipe")) ent->client->clip_index = CLIP_NONE; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Crowbar")) ent->client->clip_index = CLIP_NONE; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Pistol")) ent->client->clip_index = CLIP_PISTOL; else if (!strcmp(ent->client->pers.weapon->pickup_name, "SPistol")) ent->client->clip_index = CLIP_PISTOL; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Shotgun")) ent->client->clip_index = CLIP_SHOTGUN; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Tommygun")) ent->client->clip_index = CLIP_TOMMYGUN; else if (!strcmp(ent->client->pers.weapon->pickup_name, "FlameThrower")) ent->client->clip_index = CLIP_FLAMEGUN; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Bazooka")) ent->client->clip_index = CLIP_ROCKETS; else if (!strcmp(ent->client->pers.weapon->pickup_name, "Grenade Launcher")) ent->client->clip_index = CLIP_GRENADES; // JOSEPH 16-APR-99 else if (!strcmp(ent->client->pers.weapon->pickup_name, "Heavy machinegun")) ent->client->clip_index = CLIP_SLUGS; // END JOSEPH } int QweryClipIndex (gitem_t *item) { if (!strcmp(item->pickup_name, "Pipe")) return CLIP_NONE; else if (!strcmp(item->pickup_name, "Crowbar")) return CLIP_NONE; else if (!strcmp(item->pickup_name, "Pistol")) return CLIP_PISTOL; else if (!strcmp(item->pickup_name, "SPistol")) return CLIP_PISTOL; else if (!strcmp(item->pickup_name, "Shotgun")) return CLIP_SHOTGUN; else if (!strcmp(item->pickup_name, "Tommygun")) return CLIP_TOMMYGUN; else if (!strcmp(item->pickup_name, "FlameThrower")) return CLIP_FLAMEGUN; else if (!strcmp(item->pickup_name, "Bazooka")) return CLIP_ROCKETS; else if (!strcmp(item->pickup_name, "Grenade Launcher")) return CLIP_GRENADES; // JOSEPH 16-APR-99 else if (!strcmp(item->pickup_name, "Heavy machinegun")) return CLIP_SLUGS; // END JOSEPH return (0); } /* =============== ChangeWeapon The old weapon has been dropped all the way, so make the new one current =============== */ void ChangeWeapon (edict_t *ent) { int i; 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; // set visible model if (ent->s.modelindex == 255) { if (ent->client->pers.weapon) i = (((QweryClipIndex(ent->client->pers.weapon)+1) & 0xff) << 8); else i = 0; ent->s.skinnum = (ent - g_edicts - 1) | i; } 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; // ent->client->flashlight = false; // RAFAEL 28-dec-98 ent->client->gun_noise = false; if (ent->client->pers.weapon) ChangeClipIndex (ent); { int i; if (!strcmp (ent->client->pers.weapon->pickup_name , "SPistol")) { if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) ent->client->ps.gunindex = gi.modelindex("models/weapons/silencer_mdx/magnum.mdx"); else ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); } else if (!strcmp (ent->client->pers.weapon->pickup_name , "Pistol")) { if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) ent->client->ps.gunindex = gi.modelindex("models/weapons/v_colt/magnum.mdx"); else ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); } else if (!strcmp (ent->client->pers.weapon->pickup_name, "Shotgun")) ent->client->ps.gunindex = gi.modelindex("models/weapons/shotgun/shotgun.mdx"); else if (!strcmp (ent->client->pers.weapon->pickup_name, "Heavy machinegun")) { if (ent->client->pers.pistol_mods & WEAPON_MOD_COOLING_JACKET) ent->client->ps.gunindex = gi.modelindex("models/weapons/v_hmgcool/hmgcool.mdx"); else ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); } else ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); memset(&(ent->client->ps.model_parts[0]), 0, sizeof(model_part_t) * MAX_MODEL_PARTS); ent->client->ps.num_parts = 0; ent->client->ps.num_parts++; // ent->client->ps.model_parts[PART_HEAD].modelindex = gi.modelindex(ent->client->pers.weapon->view_model); ent->client->ps.model_parts[PART_HEAD].modelindex = ent->client->ps.gunindex;//gi.modelindex(ent->client->pers.weapon->view_model); for (i=0; iclient->ps.model_parts[PART_HEAD].skinnum[i] = 0; // will we have more than one skin??? // HACK, set arm model if (!strcmp(ent->client->pers.weapon->pickup_name, "Shotgun")) { // Ridah, HACK: changed this to use PART_LEGS, since PART_BODY sometimes doesn't show up ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/shotgun/hand.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? } // JOSEPH 12-OCT-98 // JOSEPH 5-FEB-99-B else if (!strcmp(ent->client->pers.weapon->pickup_name, "Pipe")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/blakjak/hand.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? } // END JOSEPH // JOSEPH 19-JAN-99 else if (!strcmp(ent->client->pers.weapon->pickup_name, "Crowbar")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/crowbar/hand.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? } // END JOSEPH else if (!strcmp(ent->client->pers.weapon->pickup_name, "FlameThrower")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/v_flamegun/hand.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? } // END JOSEPH // JOSEPH 4-MAR-99 else if (!strcmp(ent->client->pers.weapon->pickup_name, "Bazooka")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/v_rocket_launcher/hand.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/v_rocket_launcher/shell_a.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? // note to self: not using this anymore /* ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_GUN].modelindex = gi.modelindex("models/weapons/v_rocket_launcher/shell_b.mdx"); for (i=0; iclient->ps.model_parts[PART_GUN].skinnum[i] = 0; // will we have more than one skin??? */ ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_GUN2].modelindex = gi.modelindex("models/weapons/v_rocket_launcher/clip.mdx"); for (i=0; iclient->ps.model_parts[PART_GUN2].skinnum[i] = 0; // will we have more than one skin??? } // END JOSEPH else if (!strcmp (ent->client->pers.weapon->pickup_name , "SPistol")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/silencer_mdx/handl.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/silencer_mdx/handr.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_GUN].modelindex = gi.modelindex("models/weapons/silencer_mdx/clip.mdx"); for (i=0; iclient->ps.model_parts[PART_GUN].skinnum[i] = 0; ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); } else if (!strcmp (ent->client->pers.weapon->pickup_name , "Pistol")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/v_colt/handl.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/v_colt/handr.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_GUN].modelindex = gi.modelindex("models/weapons/v_colt/clip.mdx"); for (i=0; iclient->ps.model_parts[PART_GUN].skinnum[i] = 0; } else if (!strcmp(ent->client->pers.weapon->pickup_name, "Tommygun")) { // Ridah, hacked this, we're still having disappearing hands after going from the Pistol ?! ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_CIGAR].modelindex = gi.modelindex("models/weapons/v_tomgun/lhand.mdx"); for (i=0; iclient->ps.model_parts[PART_CIGAR].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/v_tomgun/rhand.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? } // JOSEPH 16-APR-99 else if (!strcmp (ent->client->pers.weapon->pickup_name , "Heavy machinegun")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/v_hmg/lhand.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/v_hmg/clip.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? } // END JOSEPH else if (!strcmp (ent->client->pers.weapon->pickup_name , "Grenade Launcher")) { ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_LEGS].modelindex = gi.modelindex("models/weapons/v_grenade_launcher/lhand.mdx"); for (i=0; iclient->ps.model_parts[PART_LEGS].skinnum[i] = 0; // will we have more than one skin??? ent->client->ps.num_parts++; ent->client->ps.model_parts[PART_BODY].modelindex = gi.modelindex("models/weapons/v_grenade_launcher/clip.mdx"); for (i=0; iclient->ps.model_parts[PART_BODY].skinnum[i] = 0; // will we have more than one skin??? } } // ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); #if 0 ent->client->anim_priority = ANIM_PAIN; if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) { int rnd; rnd = rand()%3; if (rnd==0) { ent->s.frame = FRAME_crouch_pain1_01; ent->client->anim_end = FRAME_crouch_pain1_08; } else if (rnd==1) { ent->s.frame = FRAME_crouch_pain2_01; ent->client->anim_end = FRAME_crouch_pain2_06; } else if (rnd==2) { ent->s.frame = FRAME_crouch_pain3_01; ent->client->anim_end = FRAME_crouch_pain3_06; } } else { int rnd; /* rnd = rand()%3; if (rnd==0) { ent->s.frame = FRAME_pain1_01; ent->client->anim_end = FRAME_pain1_05; } else if (rnd==1) { ent->s.frame = FRAME_pain2_01; ent->client->anim_end = FRAME_pain2_05; } else if (rnd==2) { ent->s.frame = FRAME_pain3_01; ent->client->anim_end = FRAME_pain3_05; } */ rnd = rand()%6; switch (rnd) { case 0: ent->s.frame = FRAME_pain_Rarm_01; ent->client->anim_end = FRAME_pain_Rarm_10; break; case 1: ent->s.frame = FRAME_pain_Larm_01; ent->client->anim_end = FRAME_pain_Larm_09; break; case 2: ent->s.frame = FRAME_pain_chest_01; ent->client->anim_end = FRAME_pain_chest_09; break; case 3: ent->s.frame = FRAME_pain_head_01; ent->client->anim_end = FRAME_pain_head_10; break; case 4: ent->s.frame = FRAME_pain_Rleg_01; ent->client->anim_end = FRAME_pain_Rleg_10; break; case 5: ent->s.frame = FRAME_pain_Lleg_01; ent->client->anim_end = FRAME_pain_Lleg_08; break; } } #endif } /* ================= NoAmmoWeaponChange ================= */ void NoAmmoWeaponChange (edict_t *ent) { if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("grenades"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("grenade launcher"))] ) { ent->client->newweapon = FindItem ("grenade launcher"); return; } // JOSEPH 16-APR-99 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("308cal"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("heavy machinegun"))] ) { ent->client->newweapon = FindItem ("heavy machinegun"); return; } // END JOSEPH if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("gas"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("flamethrower"))] ) { ent->client->newweapon = FindItem ("flamethrower"); return; } if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("rockets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("bazooka"))] ) { ent->client->newweapon = FindItem ("Bazooka"); return; } if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("tommygun"))] ) { ent->client->newweapon = FindItem ("tommygun"); return; } if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] ) { ent->client->newweapon = FindItem ("shotgun"); return; } if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("pistol"))] ) { ent->client->newweapon = FindItem ("pistol"); return; } // JOSEPH 5-FEB-99-B if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("crowbar"))]) ent->client->newweapon = FindItem ("Crowbar"); else ent->client->newweapon = FindItem ("Pipe"); // END JOSEPH } /* Think_FlashLight */ void Think_FlashLight (edict_t *ent) { trace_t tr; vec3_t forward; vec3_t end; vec3_t mins, maxs; edict_t *light; vec3_t angles, origin; if (ent->health < 1) return; if (ent->client->flashlight) { VectorCopy (ent->client->v_angle, angles); VectorCopy (ent->s.origin, origin); AngleVectors (angles, forward, NULL, NULL); VectorCopy (origin, end); VectorMA (end, 8194, forward, end); VectorSet (mins, -8, -8, -8 ); VectorSet (maxs, 8, 8, 8); tr = gi.trace (ent->s.origin, mins, maxs, end, ent, MASK_SHOT); if (((tr.ent) && (tr.ent->s.renderfx2 & RF2_SURF_ALPHA)) || ((tr.contents & MASK_ALPHA))) { vec3_t start; VectorCopy (tr.endpos, start); VectorMA (start, 8, forward, start); tr = gi.trace (start, mins, maxs, end, ent, MASK_SHOT); } light = G_Spawn(); VectorCopy (tr.endpos, light->s.origin); light->s.renderfx |= RF_BEAM; light->s.effects |= EF_FLASHLIGHT; light->nextthink = level.time + 0.1; light->think = G_FreeEdict; gi.linkentity (light); } } /* ================= Think_Weapon Called by ClientBeginServerFrame and ClientThink ================= */ void Think_Weapon (edict_t *ent) { // make sure flamethrower is disabled when it should be ent->s.renderfx2 &= ~RF2_FLAMETHROWER; // if just died, put the weapon away if (ent->health < 1) { ent->client->newweapon = NULL; ChangeWeapon (ent); } // JOSEPH 10-FEB-99 if (level.bar_lvl) return; // END JOSEPH // Unholster a holstered gun if fired if ((!ent->client->pers.weapon) && ent->client->pers.holsteredweapon && (((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK))) { ent->client->newweapon = ent->client->pers.holsteredweapon; ChangeWeapon (ent); ent->client->pers.holsteredweapon = 0; } else if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) { is_quad = (ent->client->quad_framenum > level.framenum); // RAFAEL is_quadfire = (ent->client->quadfire_framenum > level.framenum); //if (ent->client->pers.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; int clip_index; // see if we're already using it if (item == ent->client->pers.weapon) return; if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) { ammo_item = FindItem(item->ammo); ammo_index = ITEM_INDEX(ammo_item); clip_index = QweryClipIndex (item); if (!ent->client->pers.inventory[ammo_index] && !ent->client->pers.weapon_clip [clip_index]) { 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) { 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; int index; int clip_index; // JOSEPH 5-FEB-99-B if (strcmp (item->pickup_name, "Pipe") == 0) { // Ridah, changed this so it defaults to Crowbar if we have it if (ent->client->pers.weapon != FindItem ("Crowbar")) { item = FindItem ("Crowbar"); index = ITEM_INDEX (item); if (!ent->client->pers.inventory[index]) { item = FindItem ("Pipe"); } } } // END JOSEPH else if (strcmp (item->pickup_name, "Pistol") == 0) { if (item == ent->client->pers.weapon) { item = FindItem ("SPistol"); index = ITEM_INDEX (item); if (!ent->client->pers.inventory[index]) { item = FindItem ("Pistol"); } } } // 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); clip_index = QweryClipIndex (item); if (!ent->client->pers.inventory[ammo_index] && !g_select_empty->value && !ent->client->pers.weapon_clip [clip_index]) { 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) ) { 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) #define FRAME_OFFSET_FOR_SPISTOL 43 #define FRAME_OFFSET_FOR_SPISTOL_WITH_SILENCER 70 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)) { int n; // RAFAEL 01-11-99 if (ent->client->weaponstate == WEAPON_RELOADING_SPISTOL) { if (ent->client->ps.gunframe == FRAME_OFFSET_FOR_SPISTOL) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } ent->client->ps.gunframe++; return; } if (ent->client->weaponstate == WEAPON_RELOADING) { if (ent->client->ps.gunframe == FRAME_FIRE_LAST) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; return; } ent->client->ps.gunframe++; return; } if (ent->client->weaponstate == WEAPON_RELOAD_CYCLE) { /* if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = FRAME_IDLE_FIRST; } else */ { ent->client->ps.gunframe++; return; } } if (ent->client->weaponstate == WEAPON_DROPPING) { if (ent->client->pers.weapon == FindItem("SPistol")) { if (ent->client->pers.silencer_shots && ent->client->ps.gunframe == FRAME_OFFSET_FOR_SPISTOL_WITH_SILENCER) { ChangeWeapon (ent); return; } if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) { ChangeWeapon (ent); return; } } else { if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) { ChangeWeapon (ent); return; } else if ((ent->client->weaponstate != WEAPON_FIRING) && (ent->client->ps.gunframe < FRAME_DEACTIVATE_FIRST)) { ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; return; } } /* 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; } } */ ent->client->ps.gunframe++; // Ridah, faster weapon changing in deathmatch if (deathmatch->value && ent->client->ps.gunframe < FRAME_DEACTIVATE_LAST) 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++; // Ridah, faster weapon changing in deathmatch if (deathmatch->value && ent->client->ps.gunframe < FRAME_ACTIVATE_LAST) 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; /* 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; } } */ return; } if (ent->client->weaponstate == WEAPON_READY) { if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) { ent->client->latched_buttons &= ~BUTTON_ATTACK; if (ent->client->clip_index == CLIP_PISTOL && ent->client->pers.weapon_clip[ent->client->clip_index] >= 1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else if (ent->client->clip_index == CLIP_SHOTGUN && ent->client->pers.weapon_clip[ent->client->clip_index] >= 1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else if (ent->client->clip_index == CLIP_TOMMYGUN && ent->client->pers.weapon_clip[ent->client->clip_index] >=1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else if (ent->client->clip_index == CLIP_SLUGS && ent->client->pers.weapon_clip[ent->client->clip_index] >=1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else if (ent->client->clip_index == CLIP_GRENADES && ent->client->pers.weapon_clip[ent->client->clip_index] >=1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else if (ent->client->clip_index == CLIP_ROCKETS && ent->client->pers.weapon_clip[ent->client->clip_index] >=1) { ent->client->ps.gunframe = FRAME_FIRE_FIRST; ent->client->weaponstate = WEAPON_FIRING; } else 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; } 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); } } 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]) { if (ent->client->quad_framenum > level.framenum) gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); /* if (ent->client->anim_priority <= ANIM_JUMP && (!ent->groundentity || (!ent->client->anim_run && !ent->client->anim_slide))) { // start the animation ent->client->anim_priority = ANIM_ATTACK; if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) { if (ent->s.frame != FRAME_crch_shoot_01) ent->s.frame = FRAME_crch_shoot_01-1; ent->client->anim_end = FRAME_crch_shoot_05; } else { if (ent->s.frame != FRAME_shoot_01) ent->s.frame = FRAME_shoot_01-1; ent->client->anim_end = FRAME_shoot_04; } } */ fire (ent); break; } } if (!fire_frames[n]) ent->client->ps.gunframe++; // JOSEPH 5-FEB-99-B // Blackjack hack if ((ent->client->ps.gunframe == 9) && (!((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK)) && (!strcmp(ent->client->pers.weapon->pickup_name, "Pipe"))) { ent->client->ps.gunframe = FRAME_IDLE_FIRST+1; ent->client->weaponstate = WEAPON_READY; } // END JOSEPH // JOSEPH 19-JAN-99 // Crowbar hack else if ((ent->client->ps.gunframe == 9) && (!((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK)) && (!strcmp(ent->client->pers.weapon->pickup_name, "Crowbar"))) { ent->client->ps.gunframe = FRAME_IDLE_FIRST+1; ent->client->weaponstate = WEAPON_READY; } // END JOSEPH if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) ent->client->weaponstate = WEAPON_READY; } } /* ====================================================================== 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 = 125; float timer; int speed; float radius; radius = damage+40; if (is_quad) damage *= 4; 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); if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) ent->client->pers.inventory[ent->client->ammo_index]--; ent->client->grenade_time = level.time + 1.0; /* 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) & BUTTON_ATTACK) ) { ent->client->latched_buttons &= ~BUTTON_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/grenade_launcher/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/grenade_launcher/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 & BUTTON_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; } } } // JOSEPH 18-DEC-98 void Think_Eject_Shell (edict_t *ent) { if (!ent->misstime--) { ent->nextthink = 0; G_FreeEdict(ent); } else { if (ent->misstime <= 20) { if (ent->misstime == 20) { ent->s.renderfx2 |= RF2_PASSALPHA; ent->s.effects = 1; // this is full alpha now } ent->s.effects += (255/20); if (ent->s.effects > 255) ent->s.effects = 255; } // ent->s.angles[0] += ent->avelocity[0]; ent->s.angles[1] += ent->avelocity[1]; // ent->s.angles[2] += ent->avelocity[2]; ent->nextthink = level.time + 0.1; } } // END JOSEPH // JOSEPH 7-JAN-99 void Eject_Shotgun_Shell (edict_t *ent) { edict_t *dropped = NULL; vec3_t forward, right, up; vec3_t offset; if (!(ent->client)) return; if (deathmatch->value) return; //gi.dprintf("angles = %s\n", vtos(ent->s.angles)); dropped = G_Spawn(); if (!dropped) return; dropped->s.modelindex = gi.modelindex("models/weapons/sshell_md2/tris.md2"); dropped->movetype = MOVETYPE_BOUNCE; dropped->mins[0] = -4; dropped->mins[1] = -4; dropped->mins[2] = -2; dropped->maxs[0] = 4; dropped->maxs[1] = 4; dropped->maxs[2] = 4; AngleVectors (ent->client->v_angle, forward, right, up); dropped->s.angles[YAW] = ent->client->v_angle[YAW]; VectorSet(offset, 0, 16, ent->viewheight -2 ); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, dropped->s.origin); VectorScale (forward, 5 + ((rand()&15)-8), dropped->velocity); VectorMA (dropped->velocity, 50 + (rand()&31), right, dropped->velocity); dropped->velocity[2] = 150 + (rand()&31); // Ridah, changed this so they don't stick in the ground so much VectorSet(dropped->avelocity, 0/*((rand()&7)-4)*/, ((rand()&15)-8), ((rand()&7)-4)); dropped->think = Think_Eject_Shell; dropped->misstime = 40; dropped->nextthink = level.time + 0.1; dropped->s.renderfx2 |= RF2_NOSHADOW; gi.linkentity (dropped); return; } // END JOSEPH //====================================================================== // JOSEPH 12-OCT-98 void Blackjack_Hit (edict_t *ent, vec3_t vorigin, int damage) { vec3_t start; vec3_t forward, right; int kick = 2; vec3_t offset; if (is_quad) damage *= 4; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight); VectorAdd (offset, vorigin, offset); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); if (fire_blackjack (ent, start, forward, damage, kick, MOD_BLACKJACK)) ent->client->ps.weapon_usage++; if (ent->client->ps.weapon_usage > 20) { ent->client->ps.rdflags &= ~RDF_SKINPLUS; ent->client->ps.rdflags |= RDF_SKINPLUSPLUS; } else if (ent->client->ps.weapon_usage > 10) ent->client->ps.rdflags |= RDF_SKINPLUS; // PlayerNoise(ent, start, PNOISE_WEAPON); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_BLACKJACK_SWING); gi.multicast (ent->s.origin, MULTICAST_PVS); } void Weapon_Blackjack_Hit (edict_t *ent) { int damage; if (deathmatch->value) damage = 10; else damage = 8;// - (int)(skill->value-1); Blackjack_Hit (ent, vec3_origin, damage); ent->client->ps.gunframe++; } void Weapon_Blackjack (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {8, 11, 0}; if (ent->client->ps.gunframe < 5) { ent->client->ps.rdflags &= ~RDF_SKINPLUS; ent->client->ps.rdflags &= ~RDF_SKINPLUSPLUS; } Weapon_Generic (ent, 5, 13, 31, 36, pause_frames, fire_frames, Weapon_Blackjack_Hit); ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; } // END JOSEPH // JOSEPH 19-JAN-99 void Crowbar_Hit (edict_t *ent, vec3_t vorigin, int damage) { vec3_t start; vec3_t forward, right; int kick = 2; vec3_t offset; if (is_quad) damage *= 4; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight); VectorAdd (offset, vorigin, offset); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); if (fire_crowbar (ent, start, forward, damage, kick, MOD_CROWBAR)) ent->client->ps.weapon_usage++; if (ent->client->ps.weapon_usage > 20) { ent->client->ps.rdflags &= ~RDF_SKINPLUS; ent->client->ps.rdflags |= RDF_SKINPLUSPLUS; } else if (ent->client->ps.weapon_usage > 10) ent->client->ps.rdflags |= RDF_SKINPLUS; // PlayerNoise(ent, start, PNOISE_WEAPON); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_CROWBAR_SWING); gi.multicast (ent->s.origin, MULTICAST_PVS); } void Weapon_Crowbar_Hit (edict_t *ent) { int damage; if (deathmatch->value) damage = 50; // This should be very powerful in deathmatch else damage = 12;// - (int)(skill->value-1); Crowbar_Hit (ent, vec3_origin, damage); ent->client->ps.gunframe++; } void Weapon_Crowbar (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {8, 11, 0}; if (ent->client->ps.gunframe < 5) { ent->client->ps.rdflags &= ~RDF_SKINPLUS; ent->client->ps.rdflags &= ~RDF_SKINPLUSPLUS; } Weapon_Generic (ent, 5, 13, 31, 36, pause_frames, fire_frames, Weapon_Crowbar_Hit); ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; } // END JOSEPH // JOSEPH 7-JAN-99 void Eject_Pistol_Shell (edict_t *ent) { edict_t *dropped = NULL; vec3_t forward, right, up; vec3_t offset; if (!(ent->client)) return; if (deathmatch->value) return; //gi.dprintf("angles = %s\n", vtos(ent->s.angles)); dropped = G_Spawn(); if (!dropped) return; dropped->s.modelindex = gi.modelindex("models/weapons/shell_md2/tris.md2"); dropped->movetype = MOVETYPE_BOUNCE; dropped->mins[0] = -4; dropped->mins[1] = -4; dropped->mins[2] = -2; dropped->maxs[0] = 4; dropped->maxs[1] = 4; dropped->maxs[2] = 4; AngleVectors (ent->client->v_angle, forward, right, up); dropped->s.angles[YAW] = ent->client->v_angle[YAW]; VectorSet(offset, 0, 16, ent->viewheight -2 ); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, dropped->s.origin); VectorScale (forward, 5 + ((rand()&15)-8), dropped->velocity); VectorMA (dropped->velocity, 50 + (rand()&31), right, dropped->velocity); dropped->velocity[2] = 150 + (rand()&31); // Ridah, changed this so they don't stick in the ground so much VectorSet(dropped->avelocity, 0/*((rand()&7)-4)*/, ((rand()&15)-8), ((rand()&7)-4)); dropped->think = Think_Eject_Shell; dropped->misstime = 40; dropped->nextthink = level.time + 0.1; dropped->s.renderfx2 |= RF2_NOSHADOW; gi.linkentity (dropped); return; } // JOSEPH 7-JAN-99 void Eject_Tommy_Shell (edict_t *ent) { edict_t *dropped = NULL; vec3_t forward, right, up; vec3_t offset; if (!(ent->client)) return; if (deathmatch->value) return; //gi.dprintf("angles = %s\n", vtos(ent->s.angles)); dropped = G_Spawn(); if (!dropped) return; dropped->s.modelindex = gi.modelindex("models/weapons/shell_md2/tris.md2"); dropped->movetype = MOVETYPE_BOUNCE; dropped->mins[0] = -4; dropped->mins[1] = -4; dropped->mins[2] = -2; dropped->maxs[0] = 4; dropped->maxs[1] = 4; dropped->maxs[2] = 4; AngleVectors (ent->client->v_angle, forward, right, up); dropped->s.angles[YAW] = ent->client->v_angle[YAW]; VectorSet(offset, 0, 16, ent->viewheight -2 ); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, dropped->s.origin); VectorScale (forward, 5 + ((rand()&15)-8), dropped->velocity); VectorMA (dropped->velocity, 50 + (rand()&31), right, dropped->velocity); dropped->velocity[2] = 150 + (rand()&31); // Ridah, changed this so they don't stick in the ground so much VectorSet(dropped->avelocity, 0/*((rand()&7)-4)*/, ((rand()&15)-8), ((rand()&7)-4)); dropped->think = Think_Eject_Shell; dropped->misstime = 40; dropped->nextthink = level.time + 0.1; dropped->s.renderfx2 |= RF2_NOSHADOW; gi.linkentity (dropped); return; } // END JOSEPH // WEAPON PISTOL void Pistol_Fire (edict_t *ent, vec3_t vorigin, int damage) { vec3_t start; vec3_t forward, right; int kick = 2; vec3_t offset; if (is_quad) damage *= 4; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight); VectorAdd (offset, vorigin, offset); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -4; fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_PISTOL); if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_PISTOL_DAMAGE_MOD | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); } else { gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_PISTOL | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); } PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) { ent->client->pers.weapon_clip[ent->client->clip_index]--; } ent->client->gun_noise = true; } void Weapon_Pistol_Fire (edict_t *ent) { int damage; int rounds; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 29; } return; } if (deathmatch->value) damage = 15; else damage = 10; if (ent->client->ps.gunframe == 6) { if (ent->client->pers.pistol_mods & WEAPON_MOD_ROF) { if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) { damage *= 2; } ent->client->ps.gunframe = 8; } else { if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) { damage *= 2; } ent->client->ps.gunframe++; } Pistol_Fire (ent, vec3_origin, damage); Eject_Pistol_Shell(ent); } else if (ent->client->ps.gunframe == 10) { if (!ent->client->pers.weapon_clip[ent->client->clip_index]) { if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; ent->client->ps.gunframe++; if (ent->client->pers.pistol_mods & WEAPON_MOD_RELOAD) ;//gi.dprintf ("need fast reload sound\n"); else gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/clip_out.wav"), 1, ATTN_NORM, 0); if (! ent->client->pers.weapon_clip[ent->client->clip_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 ent->client->ps.gunframe = 29; } } void Weapon_Pistol (edict_t *ent) { int rounds; //static int pause_frames[] = {46, 0, 0}; static int pause_frames[] = {0, 0, 0}; static int fire_frames[] = {6, 10, 0}; if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 28 && ent->client->ps.gunframe <= 44) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_PISTOL_ROUNDS) { ent->client->ps.gunframe = 10; ent->client->weaponstate = WEAPON_RELOADING; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; } ent->client->reload_weapon = false; } else ent->client->reload_weapon = false; } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 28 && ent->client->ps.gunframe <= 44) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 10; ent->client->weaponstate = WEAPON_RELOADING; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; } } if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) ent->client->ps.gunindex = gi.modelindex("models/weapons/v_colt/magnum.mdx"); Weapon_Generic (ent, 5, 28, 44, 49, pause_frames, fire_frames, Weapon_Pistol_Fire); if (ent->client->pers.pistol_mods & WEAPON_MOD_RELOAD) { if (ent->client->ps.gunframe == 21) ent->client->ps.gunframe = 26; } if (ent->client->ps.gunframe >= 10 && ent->client->ps.gunframe <= 28) { ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; } else ent->client->ps.model_parts[PART_BODY].invisible_objects = (1<<0 | 1<<1); if (ent->client->ps.gunframe == 1) gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/holster.wav"), 1, ATTN_NORM, 0); if (ent->client->ps.gunframe == 11) gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/clip_out.wav"), 1, ATTN_NORM, 0); if (ent->client->ps.gunframe == 18) gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/clip_in.wav"), 1, ATTN_NORM, 0); if (ent->client->ps.gunframe >= 10 && ent->client->ps.gunframe <= 24) { ent->client->ps.model_parts[PART_GUN].invisible_objects = 0; } else ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); } void SPistol_Fire (edict_t *ent, vec3_t vorigin, int damage) { vec3_t start; vec3_t forward, right; int kick = 2; vec3_t offset; // is_silenced = MZ_SILENCED; if (is_quad) damage *= 4; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight); VectorAdd (offset, vorigin, offset); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); VectorScale (forward, -2, ent->client->kick_origin); ent->client->kick_angles[0] = -4; fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_SILENCER); gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); gi.WriteByte (MZ_SPISTOL | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) ent->client->pers.weapon_clip[ent->client->clip_index]--; if (!ent->client->pers.weapon_clip[ent->client->clip_index] && !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); } Eject_Pistol_Shell(ent); ent->client->gun_noise = false; } void Weapon_SPistol_Fire (edict_t *ent) { int damage; int rounds; if (ent->waterlevel >= 2) { //gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 50; } return; } if (deathmatch->value) damage = 15; else damage = 10; if (ent->client->ps.gunframe == 21) { if (ent->client->pers.pistol_mods & WEAPON_MOD_ROF) { ent->client->ps.gunframe = 23; } else { ent->client->ps.gunframe++; } if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) { damage *= 2; } SPistol_Fire (ent, vec3_origin, damage); Eject_Pistol_Shell(ent); ent->client->pers.silencer_shots--; if (!ent->client->pers.silencer_shots) ent->client->ps.gunframe = 43; } else if (ent->client->ps.gunframe == 25) { if (!ent->client->pers.weapon_clip[ent->client->clip_index]) { if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; ent->client->ps.gunframe++; if (ent->client->pers.pistol_mods & WEAPON_MOD_RELOAD) ;//gi.dprintf ("need fast reload sound\n"); else gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/clip_out.wav"), 1, ATTN_NORM, 0); if (! ent->client->pers.weapon_clip[ent->client->clip_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 ent->client->ps.gunframe = 50; } else if (ent->client->ps.gunframe == 44) { if (!(ent->client->pers.silencer_shots)) ent->client->ps.gunframe++; else ent->client->ps.gunframe = 50; } } void Weapon_SPistol (edict_t *ent) { static int pause_frames[] = {0, 0, 0}; static int fire_frames[] = {21, 25, 44, 0}; int rounds; // gi.dprintf ("silencer shots left: %d\n", ent->client->pers.silencer_shots); if (ent->client->ps.gunframe < 22) { ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; } else if (ent->client->weaponstate == WEAPON_RELOADING_SPISTOL && ent->client->ps.gunframe < 40) { if (ent->client->ps.gunframe < 39) ent->client->ps.model_parts[PART_GUN].invisible_objects = 0; else ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; } else if (ent->client->pers.holsteredweapon) { ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); ent->client->ps.model_parts[PART_BODY].invisible_objects = (1<<0 | 1<<1); } else { ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); ent->client->ps.model_parts[PART_BODY].invisible_objects = (1<<0 | 1<<1); } if (ent->client->ps.gunframe == 49) { if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] && ent->client->pers.inventory[ITEM_INDEX(FindItem("pistol"))] ) { ent->client->newweapon = FindItem ("pistol"); } else NoAmmoWeaponChange (ent); ent->client->ps.gunframe = 71; ent->client->weaponstate = WEAPON_DROPPING; { gitem_t *it; int index; it = FindItem ("SPistol"); index = ITEM_INDEX (it); ent->client->pers.inventory[index] = 0; } } else if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 50 && ent->client->ps.gunframe <= 65) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_PISTOL_ROUNDS) { ent->client->ps.gunframe = 25; ent->client->weaponstate = WEAPON_RELOADING_SPISTOL; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; } ent->client->reload_weapon = false; } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 50 && ent->client->ps.gunframe <= 65) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 25; ent->client->weaponstate = WEAPON_RELOADING_SPISTOL; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_PISTOL_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_PISTOL_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; } } if (ent->client->pers.pistol_mods & WEAPON_MOD_DAMAGE) ent->client->ps.gunindex = gi.modelindex("models/weapons/silencer_mdx/magnum.mdx"); Weapon_Generic (ent, 20, 49, 65, 75, pause_frames, fire_frames, Weapon_SPistol_Fire); if (ent->client->ps.gunframe == 1) gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/pistol/silencerattatch.wav"), 1, ATTN_NORM, 0); } // JOSEPH 26-AUG-98 /* ====================================================================== TOMMYGUN ====================================================================== */ void Tommygun_Fire (edict_t *ent) { int i; vec3_t start; //vec3_t fireorigin; vec3_t forward, right; vec3_t angles; int damage = 8; int kick = 2; vec3_t offset; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 30; } return; } // First shot if (!(ent->client->buttons & BUTTON_ATTACK)) { // ent->client->machinegun_shots = 0; ent->client->ps.gunframe = 30; return; } if (deathmatch->value) damage *= 1.75; if (ent->client->pers.inventory[ent->client->ammo_index] == 0 && ent->client->pers.weapon_clip[ent->client->clip_index] == 0) return; if (ent->client->ps.gunframe == 5) ent->client->ps.gunframe = 4; else ent->client->ps.gunframe = 5; if (is_quad) { damage *= 4; kick *= 4; } // Tommy is too powerful in real-mode if (dm_realmode->value) damage /= 2; // Bounce for (i=1 ; i<3 ; i++) { ent->client->kick_origin[i] = crandom() * 0.22; ent->client->kick_angles[i] = crandom() * 0.6; } ent->client->kick_origin[0] = crandom() * 0.22; // ent->client->kick_angles[0] = ent->client->machinegun_shots * -.5; // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); AngleVectors (angles, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight-1); 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); 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); // Disable for unlimited ammo if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) { ent->client->pers.weapon_clip [ent->client->clip_index]--; if (!(ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { NoAmmoWeaponChange (ent); ent->client->ps.gunframe = 30; } else if (!ent->client->pers.weapon_clip [ent->client->clip_index]) { ent->client->reload_weapon = true; ent->client->ps.gunframe = 30; // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/machinegun/machgcock.wav"), 1, ATTN_NORM, 0); } } if (!deathmatch->value) // uses up bandwidth Eject_Tommy_Shell(ent); ent->client->gun_noise = true; } void Weapon_Tommygun (edict_t *ent) { int rounds; static int pause_frames[] = {44, 0, 0}; static int fire_frames[] = {4, 5, 0}; if (ent->client->pers.inventory[ent->client->ammo_index] == 0 && ent->client->pers.weapon_clip[ent->client->clip_index] == 0 && ent->client->weaponstate != WEAPON_DROPPING) { 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 if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 30 && ent->client->ps.gunframe <= 40) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_TOMMYGUN_ROUNDS) { ent->client->ps.gunframe = 6; ent->client->weaponstate = WEAPON_RELOADING; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_TOMMYGUN_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_TOMMYGUN_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/machinegun/machgcock.wav"), 1, ATTN_NORM, 0); } ent->client->reload_weapon = false; } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 30 && ent->client->ps.gunframe <= 40) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 6; ent->client->weaponstate = WEAPON_RELOADING; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_TOMMYGUN_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_TOMMYGUN_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/machinegun/machgcock.wav"), 1, ATTN_NORM, 0); } } Weapon_Generic (ent, 3, 29, 40, 46, pause_frames, fire_frames, Tommygun_Fire); } // END JOSEPH /* ====================================================================== FLAMETHROWER ====================================================================== */ void FlameThrower_Fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t angles; int damage = 2; int kick = 0; static int flamesnd = 0; // vec3_t offset; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 14; ent->s.renderfx2 &= ~RF2_FLAMETHROWER; } return; } if (deathmatch->value && rand()%2) damage = 1; if (ent->health <= 0) return; if (!(ent->client->buttons & BUTTON_ATTACK)) { // ent->client->machinegun_shots = 0; ent->client->ps.gunframe = 14; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/flame_thrower/flameend.wav"), 1, ATTN_NORM, 0); flamesnd = 0; ent->s.renderfx2 &= ~RF2_FLAMETHROWER; return; } ent->client->ps.gunframe ++ ; if (ent->client->ps.gunframe == 14) ent->client->ps.gunframe = 6; 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); ent->s.renderfx2 &= ~RF2_FLAMETHROWER; return; } if (is_quad) { damage *= 4; kick *= 4; } // get start / end positions VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); AngleVectors (angles, forward, right, NULL); VectorCopy( ent->s.origin, start ); fire_flamethrower (ent, start, forward, damage, kick, MOD_FLAMETHROWER); PlayerNoise(ent, start, PNOISE_WEAPON); ent->s.renderfx2 |= RF2_FLAMETHROWER; flamesnd++; if (flamesnd > 2) flamesnd = 0; if (flamesnd == 1) gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/flame_thrower/flame2.wav"), 1, ATTN_NORM, 0); else if (flamesnd == 2) gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/flame_thrower/flame3.wav"), 1, ATTN_NORM, 0); else gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/flame_thrower/flame1.wav"), 1, ATTN_NORM, 0); if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) { if ((ent->client->pers.inventory[ent->client->ammo_index] -= 2) < 0) ent->client->pers.inventory[ent->client->ammo_index] = 0; } // RAFAEL 28-dec-98 ent->client->gun_noise = true; } void Weapon_FlameThrower (edict_t *ent) { static int pause_frames[] = {18, 24, 0}; static int fire_frames[] = {6, 7, 8, 9, 10, 11, 12, 13}; Weapon_Generic (ent, 5, 13, 25, 31, pause_frames, fire_frames, FlameThrower_Fire); } /* SHOTGUN */ void shotgun_fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage = 8; int kick = 50; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 33; } return; } if (deathmatch->value) damage *= 2; AngleVectors (ent->client->v_angle, forward, right, NULL); VectorSet(offset, 0, 0, ent->viewheight-2); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); if (deathmatch->value) { fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SAWED_SHOTGUN_COUNT, MOD_SHOTGUN); } else { fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SAWED_SHOTGUN_COUNT , MOD_SHOTGUN); } VectorScale (forward, -2, ent->client->kick_origin); // 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 && deathmatch->value ) ) ent->client->pers.weapon_clip[ent->client->clip_index]--; Eject_Shotgun_Shell(ent); ent->client->gun_noise = true; } void Weapon_Shotgun_Fire (edict_t *ent) { if (ent->client->ps.gunframe == 6) { if (ent->client->pers.weapon_clip[ent->client->clip_index]) shotgun_fire (ent); else { ent->client->ps.gunframe = 17; ent->client->reload_weapon = true; ent->client->weaponstate = WEAPON_RELOAD_CYCLE; } } else if (ent->client->ps.gunframe == 16) { if (!ent->client->pers.weapon_clip[ent->client->clip_index]) { if (ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->ps.gunframe ++; ent->client->reload_weapon = true; ent->client->weaponstate = WEAPON_RELOAD_CYCLE; } 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); } } else { ent->client->ps.gunframe = 33; } } } void Weapon_Shotgun (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {6, 16, 0}; static int kick_frames[] = {-12, -9, -6, -4, -1}; if ((ent->client->ps.gunframe >= 6) & (ent->client->ps.gunframe <= 9)) { ent->client->kick_angles[0] = kick_frames[ent->client->ps.gunframe-6]; } if (ent->client->ps.gunframe == 7) ent->client->ps.rdflags |= RDF_NOLERP; else ent->client->ps.rdflags &= ~RDF_NOLERP; if (ent->client->reload_weapon) { if (ent->client->buttons & BUTTON_ATTACK && ent->client->pers.weapon_clip[ent->client->clip_index] >= 1 && ent->client->weaponstate != WEAPON_FIRING) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 33; ent->client->weaponstate = WEAPON_READY; } else if (ent->client->newweapon) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 33; ent->client->weaponstate = WEAPON_DROPPING; } else { if (ent->client->ps.gunframe == 29) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_SHOTGUN_ROUNDS) { if (ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->pers.inventory[ent->client->ammo_index]--; ent->client->pers.weapon_clip[ent->client->clip_index]++; if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_SHOTGUN_ROUNDS) ent->client->ps.gunframe = 21; else { ent->client->reload_weapon = false; ent->client->ps.gunframe = 29; ent->client->weaponstate = WEAPON_RELOADING; } } else { ent->client->reload_weapon = false; ent->client->weaponstate = WEAPON_RELOADING; } } else { ent->client->reload_weapon = false; ent->client->weaponstate = WEAPON_RELOADING; } } else if (ent->client->ps.gunframe >= 33 && ent->client->ps.gunframe <= 40) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_SHOTGUN_ROUNDS && ent->client->pers.inventory[ent->client->ammo_index]) { ent->client->weaponstate = WEAPON_RELOAD_CYCLE; ent->client->ps.gunframe = 17; } } } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->weaponstate != WEAPON_DROPPING && !ent->client->buttons & BUTTON_ATTACK) { ent->client->reload_weapon = true; ent->client->weaponstate = WEAPON_RELOAD_CYCLE; ent->client->ps.gunframe = 17; 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); ent->client->reload_weapon = false; ent->client->ps.gunframe = 33; ent->client->weaponstate = WEAPON_READY; } } if (ent->client->ps.gunframe == 21) { gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/shotgun/shotgload.wav"), 1, ATTN_NORM, 0); } Weapon_Generic (ent, 5, 32, 40, 45, pause_frames, fire_frames, Weapon_Shotgun_Fire); /* if (ent->client->ps.gunframe == 1) { ent->client->ps.model_parts[PART_HEAD].invisible_objects = 0; ent->client->ps.model_parts[PART_BODY].invisible_objects = 0; ent->client->ps.model_parts[PART_LEGS].invisible_objects = 0; } */ } /* BAR .308 */ void weapon_barmachinegun_fire (edict_t *ent) { vec3_t start; vec3_t forward, right; vec3_t offset; int damage; int kick; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 43; } return; } if (deathmatch->value) { // tone down if too much in deathmatch damage = 50; kick = 50; } else { damage = 25; kick = 50; } AngleVectors (ent->client->v_angle, forward, right, NULL); VectorScale (forward, -3, ent->client->kick_origin); ent->client->kick_angles[0] = -3; VectorSet(offset, 0, 0, ent->viewheight-1); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_bullet (ent, start, forward, damage, kick, 0, 0, MOD_BARMACHINEGUN); // send muzzle flash gi.WriteByte (svc_muzzleflash); gi.WriteShort (ent-g_edicts); if (ent->client->ps.gunframe == 5) gi.WriteByte (MZ_BARMACHINEGUN | is_silenced); else gi.WriteByte (MZ_BARMACHINEGUN2 | is_silenced); gi.multicast (ent->s.origin, MULTICAST_PVS); PlayerNoise(ent, start, PNOISE_WEAPON); if (! ( (int)dmflags->value & DF_INFINITE_AMMO && deathmatch->value ) ) { ent->client->pers.weapon_clip [ent->client->clip_index]--; if (!(ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { NoAmmoWeaponChange (ent); ent->client->ps.gunframe = 43; } else if (ent->client->pers.inventory[ent->client->ammo_index] && !(ent->client->pers.weapon_clip [ent->client->clip_index])) { ent->client->reload_weapon = true; ent->client->ps.gunframe = 43; } } Eject_Tommy_Shell(ent); ent->client->gun_noise = true; } void barmachinegun_fire (edict_t *ent) { if ((ent->client->ps.gunframe == 19)/* && !(ent->client->buttons & BUTTON_ATTACK)*/) { ent->client->ps.gunframe = 43; return; } else if (ent->client->ps.gunframe == 12) { if (ent->client->pers.pistol_mods & WEAPON_MOD_COOLING_JACKET) { ent->client->ps.gunframe = 43; } } else if (ent->client->ps.gunframe == 5 || ent->client->ps.gunframe == 7 || ent->client->ps.gunframe == 9) { weapon_barmachinegun_fire (ent); if (ent->client->pers.pistol_mods & WEAPON_MOD_COOLING_JACKET) { ent->client->pers.hmg_shots --; if (!ent->client->pers.hmg_shots) { ent->client->pers.pistol_mods &= ~WEAPON_MOD_COOLING_JACKET; ent->client->newweapon = ent->client->pers.weapon; if (ent->client->pers.inventory[ent->client->ammo_index] || ent->client->pers.weapon_clip[ent->client->clip_index]) ChangeWeapon (ent); else NoAmmoWeaponChange (ent); } } } ent->client->ps.gunframe++; } #define MAX_BARGUN_ROUNDS 30 void Weapon_Barmachinegun (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {5, 6, 7, 8, 9, 12, 19, 0}; int rounds; if (ent->client->pers.inventory[ent->client->ammo_index] == 0 && ent->client->pers.weapon_clip[ent->client->clip_index] == 0 && ent->client->weaponstate != WEAPON_DROPPING) { 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 if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 43 && ent->client->ps.gunframe <= 53) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_BARGUN_ROUNDS) { ent->client->ps.gunframe = 20; ent->client->weaponstate = WEAPON_RELOADING; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_BARGUN_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_BARGUN_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hmg/hmgcock.wav"), 1, ATTN_NORM, 0); } ent->client->reload_weapon = false; } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 43 && ent->client->ps.gunframe <= 53) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 20; ent->client->weaponstate = WEAPON_RELOADING; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_BARGUN_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_BARGUN_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/hmg/hmgcock.wav"), 1, ATTN_NORM, 0); } } Weapon_Generic (ent, 4, 42, 53, 59, pause_frames, fire_frames, barmachinegun_fire); // gi.dprintf ("Frame: %d\n", ent->client->ps.gunframe); } /* ====================================================================== GRENADE LAUNCHER ====================================================================== */ void Eject_Grenade_Shell (edict_t *ent) { edict_t *dropped = NULL; vec3_t forward, right, up; vec3_t offset; if (!(ent->client)) return; if (deathmatch->value) return; //gi.dprintf("angles = %s\n", vtos(ent->s.angles)); dropped = G_Spawn(); if (!dropped) return; dropped->s.modelindex = gi.modelindex("models/weapons/grenade_shell/tris.md2"); dropped->movetype = MOVETYPE_BOUNCE; dropped->mins[0] = -4; dropped->mins[1] = -4; dropped->mins[2] = -2; dropped->maxs[0] = 4; dropped->maxs[1] = 4; dropped->maxs[2] = 4; AngleVectors (ent->client->v_angle, forward, right, up); dropped->s.angles[YAW] = ent->client->v_angle[YAW]; VectorSet(offset, 0, 16, ent->viewheight -2 ); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, dropped->s.origin); VectorScale (forward, 5 + ((rand()&15)-8), dropped->velocity); VectorMA (dropped->velocity, 50 + (rand()&31), right, dropped->velocity); dropped->velocity[2] = 150 + (rand()&31); // Ridah, changed this so they don't stick in the ground so much VectorSet(dropped->avelocity, 0/*((rand()&7)-4)*/, ((rand()&15)-8), ((rand()&7)-4)); dropped->think = Think_Eject_Shell; dropped->misstime = 40; dropped->nextthink = level.time + 0.1; dropped->s.renderfx2 |= RF2_NOSHADOW; gi.linkentity (dropped); return; } void weapon_grenadelauncher_fire (edict_t *ent) { vec3_t offset; vec3_t forward, right; vec3_t start; int damage = 120; float radius; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 33; } return; } damage *= 2; // 240 points of damage radius = damage*2; // 480 units radius radius *= 0.75; VectorSet(offset, 16, 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, 750, 2.0, radius); 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 && deathmatch->value ) ) { ent->client->pers.weapon_clip[ent->client->clip_index]--; if (!(ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { NoAmmoWeaponChange (ent); ent->client->ps.gunframe = 33; } } Eject_Grenade_Shell(ent); ent->client->gun_noise = true; } void Weapon_GrenadeLauncher_Fire (edict_t *ent) { if (ent->client->ps.gunframe == 5) weapon_grenadelauncher_fire (ent); else if (ent->client->ps.gunframe == 16) { if ((ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { ent->client->reload_weapon = true; } ent->client->ps.gunframe = 33; } } #define MAX_GRENADE_ROUNDS 3 void Weapon_GrenadeLauncher (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {5, 16, 0}; int rounds; if (ent->client->pers.inventory[ent->client->ammo_index] == 0 && ent->client->pers.weapon_clip[ent->client->clip_index] == 0 && ent->client->weaponstate != WEAPON_DROPPING) { 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 if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 33 && ent->client->ps.gunframe <= 40) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_GRENADE_ROUNDS) { ent->client->ps.gunframe = 17; ent->client->weaponstate = WEAPON_RELOADING; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_GRENADE_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_GRENADE_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/grenade_launcher/reload.wav"), 1, ATTN_NORM, 0); } ent->client->reload_weapon = false; } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 33 && ent->client->ps.gunframe <= 40) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 17; ent->client->weaponstate = WEAPON_RELOADING; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_GRENADE_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_GRENADE_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/grenade_launcher/reload.wav"), 1, ATTN_NORM, 0); } } Weapon_Generic (ent, 4, 32, 40, 45, pause_frames, fire_frames, Weapon_GrenadeLauncher_Fire); if (ent->client->ps.gunframe >= 17 && ent->client->ps.gunframe <= 32) { ent->client->ps.model_parts[PART_GUN].invisible_objects = 0; } else ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); if (ent->client->ps.gunframe >= 9 && ent->client->ps.gunframe <= 16) ent->client->ps.rdflags |= RDF_NOLERP; else ent->client->ps.rdflags &= ~RDF_NOLERP; } // rocket launcher void weapon_rocketlauncher_fire (edict_t *ent) { vec3_t offset, start; vec3_t forward, right; int damage; float damage_radius; int radius_damage; if (ent->waterlevel >= 2) { // gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); if (ent->client->weaponstate == WEAPON_FIRING) { ent->client->weaponstate = WEAPON_READY; ent->client->ps.gunframe = 30; } return; } damage = 100 + (int)(random() * 20.0); radius_damage = 120; damage_radius = 180; // 256; 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] = -4; VectorSet(offset, 8, 8, ent->viewheight-8); P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); fire_rocket (ent, start, forward, damage, 900, 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 && deathmatch->value ) ) { ent->client->pers.weapon_clip[ent->client->clip_index]--; if (!(ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { NoAmmoWeaponChange (ent); ent->client->ps.gunframe = 30; } } ent->client->gun_noise = true; } void Weapon_RocketLauncher_Fire (edict_t *ent) { if (ent->client->ps.gunframe == 6) weapon_rocketlauncher_fire (ent); else if (ent->client->ps.gunframe == 13) { if ((ent->client->pers.inventory[ent->client->ammo_index]) && !ent->client->pers.weapon_clip [ent->client->clip_index]) { ent->client->reload_weapon = true; } ent->client->ps.gunframe = 30; } } #define MAX_ROCKET_ROUNDS 5 void Weapon_RocketLauncher (edict_t *ent) { static int pause_frames[] = {0, 0}; static int fire_frames[] = {6, 13, 0}; int rounds; if (ent->client->pers.inventory[ent->client->ammo_index] == 0 && ent->client->pers.weapon_clip[ent->client->clip_index] == 0 && ent->client->weaponstate != WEAPON_DROPPING) { 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 if (ent->client->reload_weapon) { if (ent->client->ps.gunframe >= 30 && ent->client->ps.gunframe <= 41) { if (ent->client->pers.weapon_clip[ent->client->clip_index] < MAX_ROCKET_ROUNDS) { ent->client->ps.gunframe = 14; ent->client->weaponstate = WEAPON_RELOADING; ent->client->pers.inventory[ent->client->ammo_index] += ent->client->pers.weapon_clip[ent->client->clip_index]; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_ROCKET_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_ROCKET_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/rocket_launcher/reload.wav"), 1, ATTN_NORM, 0); } ent->client->reload_weapon = false; } } else if (!ent->client->pers.weapon_clip[ent->client->clip_index] && ent->client->pers.inventory[ent->client->ammo_index]) { if (ent->client->ps.gunframe >= 30 && ent->client->ps.gunframe <= 41) { ent->client->reload_weapon = false; ent->client->ps.gunframe = 14; ent->client->weaponstate = WEAPON_RELOADING; if (ent->client->pers.inventory[ent->client->ammo_index] < MAX_ROCKET_ROUNDS) { rounds = ent->client->pers.inventory[ent->client->ammo_index]; } else rounds = MAX_ROCKET_ROUNDS; ent->client->pers.weapon_clip[ent->client->clip_index] = rounds; ent->client->pers.inventory[ent->client->ammo_index] -= rounds; gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/rocket_launcher/reload.wav"), 1, ATTN_NORM, 0); } } Weapon_Generic (ent, 5, 29, 41, 47, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); /* if (ent->client->ps.gunframe >= 14 && ent->client->ps.gunframe <= 29) { ent->client->ps.model_parts[PART_GUN].invisible_objects = 0; } else ent->client->ps.model_parts[PART_GUN].invisible_objects = (1<<0 | 1<<1); */ // gi.dprintf ("frame: %d\n", ent->client->ps.gunframe); }