|
|
1.1 ! root 1: // g_weapon.c ! 2: ! 3: #include "g_local.h" ! 4: #include "m_player.h" ! 5: ! 6: ! 7: static qboolean is_quad; ! 8: // RAFAEL ! 9: static qboolean is_quadfire; ! 10: static byte is_silenced; ! 11: ! 12: ! 13: void weapon_grenade_fire (edict_t *ent, qboolean held); ! 14: // RAFAEL ! 15: void weapon_trap_fire (edict_t *ent, qboolean held); ! 16: ! 17: ! 18: static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) ! 19: { ! 20: vec3_t _distance; ! 21: ! 22: VectorCopy (distance, _distance); ! 23: if (client->pers.hand == LEFT_HANDED) ! 24: _distance[1] *= -1; ! 25: else if (client->pers.hand == CENTER_HANDED) ! 26: _distance[1] = 0; ! 27: G_ProjectSource (point, _distance, forward, right, result); ! 28: } ! 29: ! 30: ! 31: /* ! 32: =============== ! 33: PlayerNoise ! 34: ! 35: Each player can have two noise objects associated with it: ! 36: a personal noise (jumping, pain, weapon firing), and a weapon ! 37: target noise (bullet wall impacts) ! 38: ! 39: Monsters that don't directly see the player can move ! 40: to a noise in hopes of seeing the player from there. ! 41: =============== ! 42: */ ! 43: void PlayerNoise(edict_t *who, vec3_t where, int type) ! 44: { ! 45: edict_t *noise; ! 46: ! 47: if (type == PNOISE_WEAPON) ! 48: { ! 49: if (who->client->silencer_shots) ! 50: { ! 51: who->client->silencer_shots--; ! 52: return; ! 53: } ! 54: } ! 55: ! 56: if (deathmatch->value) ! 57: return; ! 58: ! 59: if (who->flags & FL_NOTARGET) ! 60: return; ! 61: ! 62: ! 63: if (!who->mynoise) ! 64: { ! 65: noise = G_Spawn(); ! 66: noise->classname = "player_noise"; ! 67: VectorSet (noise->mins, -8, -8, -8); ! 68: VectorSet (noise->maxs, 8, 8, 8); ! 69: noise->owner = who; ! 70: noise->svflags = SVF_NOCLIENT; ! 71: who->mynoise = noise; ! 72: ! 73: noise = G_Spawn(); ! 74: noise->classname = "player_noise"; ! 75: VectorSet (noise->mins, -8, -8, -8); ! 76: VectorSet (noise->maxs, 8, 8, 8); ! 77: noise->owner = who; ! 78: noise->svflags = SVF_NOCLIENT; ! 79: who->mynoise2 = noise; ! 80: } ! 81: ! 82: if (type == PNOISE_SELF || type == PNOISE_WEAPON) ! 83: { ! 84: noise = who->mynoise; ! 85: level.sound_entity = noise; ! 86: level.sound_entity_framenum = level.framenum; ! 87: } ! 88: else // type == PNOISE_IMPACT ! 89: { ! 90: noise = who->mynoise2; ! 91: level.sound2_entity = noise; ! 92: level.sound2_entity_framenum = level.framenum; ! 93: } ! 94: ! 95: VectorCopy (where, noise->s.origin); ! 96: VectorSubtract (where, noise->maxs, noise->absmin); ! 97: VectorAdd (where, noise->maxs, noise->absmax); ! 98: noise->teleport_time = level.time; ! 99: gi.linkentity (noise); ! 100: } ! 101: ! 102: ! 103: qboolean Pickup_Weapon (edict_t *ent, edict_t *other) ! 104: { ! 105: int index; ! 106: gitem_t *ammo; ! 107: ! 108: index = ITEM_INDEX(ent->item); ! 109: ! 110: if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) ! 111: && other->client->pers.inventory[index]) ! 112: { ! 113: if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) ) ! 114: return false; // leave the weapon for others to pickup ! 115: } ! 116: ! 117: other->client->pers.inventory[index]++; ! 118: ! 119: if (!(ent->spawnflags & DROPPED_ITEM) ) ! 120: { ! 121: // give them some ammo with it ! 122: ammo = FindItem (ent->item->ammo); ! 123: // Don't get infinite ammo with trap ! 124: if ( ((int)dmflags->value & DF_INFINITE_AMMO) && Q_stricmp(ent->item->pickup_name, "ammo_trap") ) ! 125: Add_Ammo (other, ammo, 1000); ! 126: else ! 127: Add_Ammo (other, ammo, ammo->quantity); ! 128: ! 129: if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) ) ! 130: { ! 131: if (deathmatch->value) ! 132: { ! 133: if ((int)(dmflags->value) & DF_WEAPONS_STAY) ! 134: ent->flags |= FL_RESPAWN; ! 135: else ! 136: SetRespawn (ent, 30); ! 137: } ! 138: if (coop->value) ! 139: ent->flags |= FL_RESPAWN; ! 140: } ! 141: } ! 142: ! 143: if (other->client->pers.weapon != ent->item && ! 144: (other->client->pers.inventory[index] == 1) && ! 145: ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) ) ! 146: other->client->newweapon = ent->item; ! 147: ! 148: return true; ! 149: } ! 150: ! 151: ! 152: /* ! 153: =============== ! 154: ChangeWeapon ! 155: ! 156: The old weapon has been dropped all the way, so make the new one ! 157: current ! 158: =============== ! 159: */ ! 160: void ChangeWeapon (edict_t *ent) ! 161: { ! 162: if (ent->client->grenade_time) ! 163: { ! 164: ent->client->grenade_time = level.time; ! 165: ent->client->weapon_sound = 0; ! 166: weapon_grenade_fire (ent, false); ! 167: ent->client->grenade_time = 0; ! 168: } ! 169: ! 170: ent->client->pers.lastweapon = ent->client->pers.weapon; ! 171: ent->client->pers.weapon = ent->client->newweapon; ! 172: ent->client->newweapon = NULL; ! 173: ent->client->machinegun_shots = 0; ! 174: ! 175: if (ent->client->pers.weapon && ent->client->pers.weapon->ammo) ! 176: ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo)); ! 177: else ! 178: ent->client->ammo_index = 0; ! 179: ! 180: if (!ent->client->pers.weapon) ! 181: { // dead ! 182: ent->client->ps.gunindex = 0; ! 183: return; ! 184: } ! 185: ! 186: ent->client->weaponstate = WEAPON_ACTIVATING; ! 187: ent->client->ps.gunframe = 0; ! 188: ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); ! 189: ! 190: ent->client->anim_priority = ANIM_PAIN; ! 191: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 192: { ! 193: ent->s.frame = FRAME_crpain1; ! 194: ent->client->anim_end = FRAME_crpain4; ! 195: } ! 196: else ! 197: { ! 198: ent->s.frame = FRAME_pain301; ! 199: ent->client->anim_end = FRAME_pain304; ! 200: ! 201: } ! 202: } ! 203: ! 204: /* ! 205: ================= ! 206: NoAmmoWeaponChange ! 207: ================= ! 208: */ ! 209: void NoAmmoWeaponChange (edict_t *ent) ! 210: { ! 211: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))] ! 212: && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] ) ! 213: { ! 214: ent->client->newweapon = FindItem ("railgun"); ! 215: return; ! 216: } ! 217: // RAFAEL ! 218: if ( ent->client->pers.inventory[ITEM_INDEX (FindItem ("mag slug"))] ! 219: && ent->client->pers.inventory[ITEM_INDEX (FindItem ("phalanx"))]) ! 220: { ! 221: ent->client->newweapon = FindItem ("phalanx"); ! 222: } ! 223: // RAFAEL ! 224: if ( ent->client->pers.inventory[ITEM_INDEX (FindItem ("cells"))] ! 225: && ent->client->pers.inventory[ITEM_INDEX (FindItem ("ionripper"))]) ! 226: { ! 227: ent->client->newweapon = FindItem ("ionrippergun"); ! 228: } ! 229: ! 230: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] ! 231: && ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] ) ! 232: { ! 233: ent->client->newweapon = FindItem ("hyperblaster"); ! 234: return; ! 235: } ! 236: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] ! 237: && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] ) ! 238: { ! 239: ent->client->newweapon = FindItem ("chaingun"); ! 240: return; ! 241: } ! 242: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] ! 243: && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] ) ! 244: { ! 245: ent->client->newweapon = FindItem ("machinegun"); ! 246: return; ! 247: } ! 248: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1 ! 249: && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] ) ! 250: { ! 251: ent->client->newweapon = FindItem ("super shotgun"); ! 252: return; ! 253: } ! 254: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] ! 255: && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] ) ! 256: { ! 257: ent->client->newweapon = FindItem ("shotgun"); ! 258: return; ! 259: } ! 260: ent->client->newweapon = FindItem ("blaster"); ! 261: } ! 262: ! 263: /* ! 264: ================= ! 265: Think_Weapon ! 266: ! 267: Called by ClientBeginServerFrame and ClientThink ! 268: ================= ! 269: */ ! 270: void Think_Weapon (edict_t *ent) ! 271: { ! 272: // if just died, put the weapon away ! 273: if (ent->health < 1) ! 274: { ! 275: ent->client->newweapon = NULL; ! 276: ChangeWeapon (ent); ! 277: } ! 278: ! 279: // call active weapon think routine ! 280: if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) ! 281: { ! 282: is_quad = (ent->client->quad_framenum > level.framenum); ! 283: // RAFAEL ! 284: is_quadfire = (ent->client->quadfire_framenum > level.framenum); ! 285: if (ent->client->silencer_shots) ! 286: is_silenced = MZ_SILENCED; ! 287: else ! 288: is_silenced = 0; ! 289: ent->client->pers.weapon->weaponthink (ent); ! 290: } ! 291: } ! 292: ! 293: ! 294: /* ! 295: ================ ! 296: Use_Weapon ! 297: ! 298: Make the weapon ready if there is ammo ! 299: ================ ! 300: */ ! 301: void Use_Weapon (edict_t *ent, gitem_t *item) ! 302: { ! 303: int ammo_index; ! 304: gitem_t *ammo_item; ! 305: ! 306: // see if we're already using it ! 307: if (item == ent->client->pers.weapon) ! 308: return; ! 309: ! 310: if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) ! 311: { ! 312: ammo_item = FindItem(item->ammo); ! 313: ammo_index = ITEM_INDEX(ammo_item); ! 314: ! 315: if (!ent->client->pers.inventory[ammo_index]) ! 316: { ! 317: gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name); ! 318: return; ! 319: } ! 320: ! 321: if (ent->client->pers.inventory[ammo_index] < item->quantity) ! 322: { ! 323: gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name); ! 324: return; ! 325: } ! 326: } ! 327: ! 328: // change to this weapon when down ! 329: ent->client->newweapon = item; ! 330: } ! 331: ! 332: // RAFAEL 14-APR-98 ! 333: void Use_Weapon2 (edict_t *ent, gitem_t *item) ! 334: { ! 335: int ammo_index; ! 336: gitem_t *ammo_item; ! 337: gitem_t *nextitem; ! 338: int index; ! 339: ! 340: if (strcmp (item->pickup_name, "HyperBlaster") == 0) ! 341: { ! 342: if (item == ent->client->pers.weapon) ! 343: { ! 344: item = FindItem ("Ionripper"); ! 345: index = ITEM_INDEX (item); ! 346: if (!ent->client->pers.inventory[index]) ! 347: { ! 348: item = FindItem ("HyperBlaster"); ! 349: } ! 350: } ! 351: } ! 352: ! 353: else if (strcmp (item->pickup_name, "Railgun") == 0) ! 354: { ! 355: ammo_item = FindItem(item->ammo); ! 356: ammo_index = ITEM_INDEX(ammo_item); ! 357: if (!ent->client->pers.inventory[ammo_index]) ! 358: { ! 359: nextitem = FindItem ("Phalanx"); ! 360: ammo_item = FindItem(nextitem->ammo); ! 361: ammo_index = ITEM_INDEX(ammo_item); ! 362: if (ent->client->pers.inventory[ammo_index]) ! 363: { ! 364: item = FindItem ("Phalanx"); ! 365: index = ITEM_INDEX (item); ! 366: if (!ent->client->pers.inventory[index]) ! 367: { ! 368: item = FindItem ("Railgun"); ! 369: } ! 370: } ! 371: } ! 372: else if (item == ent->client->pers.weapon) ! 373: { ! 374: item = FindItem ("Phalanx"); ! 375: index = ITEM_INDEX (item); ! 376: if (!ent->client->pers.inventory[index]) ! 377: { ! 378: item = FindItem ("Railgun"); ! 379: } ! 380: } ! 381: ! 382: } ! 383: ! 384: ! 385: // see if we're already using it ! 386: if (item == ent->client->pers.weapon) ! 387: return; ! 388: ! 389: if (item->ammo) ! 390: { ! 391: ammo_item = FindItem(item->ammo); ! 392: ammo_index = ITEM_INDEX(ammo_item); ! 393: if (!ent->client->pers.inventory[ammo_index] && !g_select_empty->value) ! 394: { ! 395: gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name); ! 396: return; ! 397: } ! 398: } ! 399: ! 400: // change to this weapon when down ! 401: ent->client->newweapon = item; ! 402: ! 403: } ! 404: // END 14-APR-98 ! 405: ! 406: /* ! 407: ================ ! 408: Drop_Weapon ! 409: ================ ! 410: */ ! 411: void Drop_Weapon (edict_t *ent, gitem_t *item) ! 412: { ! 413: int index; ! 414: ! 415: if ((int)(dmflags->value) & DF_WEAPONS_STAY) ! 416: return; ! 417: ! 418: index = ITEM_INDEX(item); ! 419: // see if we're already using it ! 420: if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) ) ! 421: { ! 422: gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n"); ! 423: return; ! 424: } ! 425: ! 426: Drop_Item (ent, item); ! 427: ent->client->pers.inventory[index]--; ! 428: } ! 429: ! 430: ! 431: /* ! 432: ================ ! 433: Weapon_Generic ! 434: ! 435: A generic function to handle the basics of weapon thinking ! 436: ================ ! 437: */ ! 438: #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1) ! 439: #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1) ! 440: #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1) ! 441: ! 442: 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)) ! 443: { ! 444: int n; ! 445: ! 446: if (ent->client->weaponstate == WEAPON_DROPPING) ! 447: { ! 448: if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) ! 449: { ! 450: ChangeWeapon (ent); ! 451: return; ! 452: } ! 453: else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4) ! 454: { ! 455: ent->client->anim_priority = ANIM_REVERSE; ! 456: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 457: { ! 458: ent->s.frame = FRAME_crpain4+1; ! 459: ent->client->anim_end = FRAME_crpain1; ! 460: } ! 461: else ! 462: { ! 463: ent->s.frame = FRAME_pain304+1; ! 464: ent->client->anim_end = FRAME_pain301; ! 465: ! 466: } ! 467: } ! 468: ! 469: ent->client->ps.gunframe++; ! 470: return; ! 471: } ! 472: ! 473: if (ent->client->weaponstate == WEAPON_ACTIVATING) ! 474: { ! 475: if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST) ! 476: { ! 477: ent->client->weaponstate = WEAPON_READY; ! 478: ent->client->ps.gunframe = FRAME_IDLE_FIRST; ! 479: return; ! 480: } ! 481: ! 482: ent->client->ps.gunframe++; ! 483: return; ! 484: } ! 485: ! 486: if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) ! 487: { ! 488: ent->client->weaponstate = WEAPON_DROPPING; ! 489: ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; ! 490: ! 491: if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) ! 492: { ! 493: ent->client->anim_priority = ANIM_REVERSE; ! 494: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 495: { ! 496: ent->s.frame = FRAME_crpain4+1; ! 497: ent->client->anim_end = FRAME_crpain1; ! 498: } ! 499: else ! 500: { ! 501: ent->s.frame = FRAME_pain304+1; ! 502: ent->client->anim_end = FRAME_pain301; ! 503: ! 504: } ! 505: } ! 506: return; ! 507: } ! 508: ! 509: if (ent->client->weaponstate == WEAPON_READY) ! 510: { ! 511: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) ! 512: { ! 513: ent->client->latched_buttons &= ~BUTTON_ATTACK; ! 514: if ((!ent->client->ammo_index) || ! 515: ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) ! 516: { ! 517: ent->client->ps.gunframe = FRAME_FIRE_FIRST; ! 518: ent->client->weaponstate = WEAPON_FIRING; ! 519: ! 520: // start the animation ! 521: ent->client->anim_priority = ANIM_ATTACK; ! 522: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 523: { ! 524: ent->s.frame = FRAME_crattak1-1; ! 525: ent->client->anim_end = FRAME_crattak9; ! 526: } ! 527: else ! 528: { ! 529: ent->s.frame = FRAME_attack1-1; ! 530: ent->client->anim_end = FRAME_attack8; ! 531: } ! 532: } ! 533: else ! 534: { ! 535: if (level.time >= ent->pain_debounce_time) ! 536: { ! 537: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 538: ent->pain_debounce_time = level.time + 1; ! 539: } ! 540: NoAmmoWeaponChange (ent); ! 541: } ! 542: } ! 543: else ! 544: { ! 545: if (ent->client->ps.gunframe == FRAME_IDLE_LAST) ! 546: { ! 547: ent->client->ps.gunframe = FRAME_IDLE_FIRST; ! 548: return; ! 549: } ! 550: ! 551: if (pause_frames) ! 552: { ! 553: for (n = 0; pause_frames[n]; n++) ! 554: { ! 555: if (ent->client->ps.gunframe == pause_frames[n]) ! 556: { ! 557: if (rand()&15) ! 558: return; ! 559: } ! 560: } ! 561: } ! 562: ! 563: ent->client->ps.gunframe++; ! 564: return; ! 565: } ! 566: } ! 567: ! 568: if (ent->client->weaponstate == WEAPON_FIRING) ! 569: { ! 570: for (n = 0; fire_frames[n]; n++) ! 571: { ! 572: if (ent->client->ps.gunframe == fire_frames[n]) ! 573: { ! 574: if (ent->client->quad_framenum > level.framenum) ! 575: gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); ! 576: ! 577: fire (ent); ! 578: break; ! 579: } ! 580: } ! 581: ! 582: if (!fire_frames[n]) ! 583: ent->client->ps.gunframe++; ! 584: ! 585: if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) ! 586: ent->client->weaponstate = WEAPON_READY; ! 587: } ! 588: } ! 589: ! 590: ! 591: /* ! 592: ====================================================================== ! 593: ! 594: GRENADE ! 595: ! 596: ====================================================================== ! 597: */ ! 598: ! 599: #define GRENADE_TIMER 3.0 ! 600: #define GRENADE_MINSPEED 400 ! 601: #define GRENADE_MAXSPEED 800 ! 602: ! 603: void weapon_grenade_fire (edict_t *ent, qboolean held) ! 604: { ! 605: vec3_t offset; ! 606: vec3_t forward, right; ! 607: vec3_t start; ! 608: int damage = 125; ! 609: float timer; ! 610: int speed; ! 611: float radius; ! 612: ! 613: radius = damage+40; ! 614: if (is_quad) ! 615: damage *= 4; ! 616: ! 617: VectorSet(offset, 8, 8, ent->viewheight-8); ! 618: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 619: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 620: ! 621: timer = ent->client->grenade_time - level.time; ! 622: speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); ! 623: fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); ! 624: ! 625: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 626: ent->client->pers.inventory[ent->client->ammo_index]--; ! 627: ! 628: ent->client->grenade_time = level.time + 1.0; ! 629: ! 630: if (ent->health <= 0) ! 631: return; ! 632: ! 633: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 634: { ! 635: ent->client->anim_priority = ANIM_ATTACK; ! 636: ent->s.frame = FRAME_crattak1-1; ! 637: ent->client->anim_end = FRAME_crattak3; ! 638: } ! 639: else ! 640: { ! 641: ent->client->anim_priority = ANIM_REVERSE; ! 642: ent->s.frame = FRAME_wave08; ! 643: ent->client->anim_end = FRAME_wave01; ! 644: } ! 645: } ! 646: ! 647: void Weapon_Grenade (edict_t *ent) ! 648: { ! 649: if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) ! 650: { ! 651: ChangeWeapon (ent); ! 652: return; ! 653: } ! 654: ! 655: if (ent->client->weaponstate == WEAPON_ACTIVATING) ! 656: { ! 657: ent->client->weaponstate = WEAPON_READY; ! 658: ent->client->ps.gunframe = 16; ! 659: return; ! 660: } ! 661: ! 662: if (ent->client->weaponstate == WEAPON_READY) ! 663: { ! 664: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) ! 665: { ! 666: ent->client->latched_buttons &= ~BUTTON_ATTACK; ! 667: if (ent->client->pers.inventory[ent->client->ammo_index]) ! 668: { ! 669: ent->client->ps.gunframe = 1; ! 670: ent->client->weaponstate = WEAPON_FIRING; ! 671: ent->client->grenade_time = 0; ! 672: } ! 673: else ! 674: { ! 675: if (level.time >= ent->pain_debounce_time) ! 676: { ! 677: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 678: ent->pain_debounce_time = level.time + 1; ! 679: } ! 680: NoAmmoWeaponChange (ent); ! 681: } ! 682: return; ! 683: } ! 684: ! 685: if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) ! 686: { ! 687: if (rand()&15) ! 688: return; ! 689: } ! 690: ! 691: if (++ent->client->ps.gunframe > 48) ! 692: ent->client->ps.gunframe = 16; ! 693: return; ! 694: } ! 695: ! 696: if (ent->client->weaponstate == WEAPON_FIRING) ! 697: { ! 698: if (ent->client->ps.gunframe == 5) ! 699: gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); ! 700: ! 701: if (ent->client->ps.gunframe == 11) ! 702: { ! 703: if (!ent->client->grenade_time) ! 704: { ! 705: ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; ! 706: ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); ! 707: } ! 708: ! 709: // they waited too long, detonate it in their hand ! 710: if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) ! 711: { ! 712: ent->client->weapon_sound = 0; ! 713: weapon_grenade_fire (ent, true); ! 714: ent->client->grenade_blew_up = true; ! 715: } ! 716: ! 717: if (ent->client->buttons & BUTTON_ATTACK) ! 718: return; ! 719: ! 720: if (ent->client->grenade_blew_up) ! 721: { ! 722: if (level.time >= ent->client->grenade_time) ! 723: { ! 724: ent->client->ps.gunframe = 15; ! 725: ent->client->grenade_blew_up = false; ! 726: } ! 727: else ! 728: { ! 729: return; ! 730: } ! 731: } ! 732: } ! 733: ! 734: if (ent->client->ps.gunframe == 12) ! 735: { ! 736: ent->client->weapon_sound = 0; ! 737: weapon_grenade_fire (ent, false); ! 738: } ! 739: ! 740: if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) ! 741: return; ! 742: ! 743: ent->client->ps.gunframe++; ! 744: ! 745: if (ent->client->ps.gunframe == 16) ! 746: { ! 747: ent->client->grenade_time = 0; ! 748: ent->client->weaponstate = WEAPON_READY; ! 749: } ! 750: } ! 751: } ! 752: ! 753: /* ! 754: ====================================================================== ! 755: ! 756: GRENADE LAUNCHER ! 757: ! 758: ====================================================================== ! 759: */ ! 760: ! 761: void weapon_grenadelauncher_fire (edict_t *ent) ! 762: { ! 763: vec3_t offset; ! 764: vec3_t forward, right; ! 765: vec3_t start; ! 766: int damage = 120; ! 767: float radius; ! 768: ! 769: radius = damage+40; ! 770: if (is_quad) ! 771: damage *= 4; ! 772: ! 773: VectorSet(offset, 8, 8, ent->viewheight-8); ! 774: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 775: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 776: ! 777: VectorScale (forward, -2, ent->client->kick_origin); ! 778: ent->client->kick_angles[0] = -1; ! 779: ! 780: fire_grenade (ent, start, forward, damage, 600, 2.5, radius); ! 781: ! 782: gi.WriteByte (svc_muzzleflash); ! 783: gi.WriteShort (ent-g_edicts); ! 784: gi.WriteByte (MZ_GRENADE | is_silenced); ! 785: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 786: ! 787: ent->client->ps.gunframe++; ! 788: ! 789: PlayerNoise(ent, start, PNOISE_WEAPON); ! 790: ! 791: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 792: ent->client->pers.inventory[ent->client->ammo_index]--; ! 793: } ! 794: ! 795: void Weapon_GrenadeLauncher (edict_t *ent) ! 796: { ! 797: static int pause_frames[] = {34, 51, 59, 0}; ! 798: static int fire_frames[] = {6, 0}; ! 799: ! 800: Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); ! 801: ! 802: // RAFAEL ! 803: if (is_quadfire) ! 804: Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); ! 805: ! 806: } ! 807: ! 808: /* ! 809: ====================================================================== ! 810: ! 811: ROCKET ! 812: ! 813: ====================================================================== ! 814: */ ! 815: ! 816: void Weapon_RocketLauncher_Fire (edict_t *ent) ! 817: { ! 818: vec3_t offset, start; ! 819: vec3_t forward, right; ! 820: int damage; ! 821: float damage_radius; ! 822: int radius_damage; ! 823: ! 824: damage = 100 + (int)(random() * 20.0); ! 825: radius_damage = 120; ! 826: damage_radius = 120; ! 827: if (is_quad) ! 828: { ! 829: damage *= 4; ! 830: radius_damage *= 4; ! 831: } ! 832: ! 833: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 834: ! 835: VectorScale (forward, -2, ent->client->kick_origin); ! 836: ent->client->kick_angles[0] = -1; ! 837: ! 838: VectorSet(offset, 8, 8, ent->viewheight-8); ! 839: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 840: fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage); ! 841: ! 842: // send muzzle flash ! 843: gi.WriteByte (svc_muzzleflash); ! 844: gi.WriteShort (ent-g_edicts); ! 845: gi.WriteByte (MZ_ROCKET | is_silenced); ! 846: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 847: ! 848: ent->client->ps.gunframe++; ! 849: ! 850: PlayerNoise(ent, start, PNOISE_WEAPON); ! 851: ! 852: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 853: ent->client->pers.inventory[ent->client->ammo_index]--; ! 854: } ! 855: ! 856: void Weapon_RocketLauncher (edict_t *ent) ! 857: { ! 858: static int pause_frames[] = {25, 33, 42, 50, 0}; ! 859: static int fire_frames[] = {5, 0}; ! 860: ! 861: Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); ! 862: ! 863: ! 864: // RAFAEL ! 865: if (is_quadfire) ! 866: Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); ! 867: ! 868: ! 869: } ! 870: ! 871: ! 872: /* ! 873: ====================================================================== ! 874: ! 875: BLASTER / HYPERBLASTER ! 876: ! 877: ====================================================================== ! 878: */ ! 879: ! 880: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect) ! 881: { ! 882: vec3_t forward, right; ! 883: vec3_t start; ! 884: vec3_t offset; ! 885: ! 886: if (is_quad) ! 887: damage *= 4; ! 888: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 889: VectorSet(offset, 24, 8, ent->viewheight-8); ! 890: VectorAdd (offset, g_offset, offset); ! 891: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 892: ! 893: VectorScale (forward, -2, ent->client->kick_origin); ! 894: ent->client->kick_angles[0] = -1; ! 895: ! 896: fire_blaster (ent, start, forward, damage, 1000, effect, hyper); ! 897: ! 898: // send muzzle flash ! 899: gi.WriteByte (svc_muzzleflash); ! 900: gi.WriteShort (ent-g_edicts); ! 901: if (hyper) ! 902: gi.WriteByte (MZ_HYPERBLASTER | is_silenced); ! 903: else ! 904: gi.WriteByte (MZ_BLASTER | is_silenced); ! 905: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 906: ! 907: PlayerNoise(ent, start, PNOISE_WEAPON); ! 908: } ! 909: ! 910: ! 911: void Weapon_Blaster_Fire (edict_t *ent) ! 912: { ! 913: int damage; ! 914: ! 915: if (deathmatch->value) ! 916: damage = 15; ! 917: else ! 918: damage = 10; ! 919: Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER); ! 920: ent->client->ps.gunframe++; ! 921: } ! 922: ! 923: void Weapon_Blaster (edict_t *ent) ! 924: { ! 925: static int pause_frames[] = {19, 32, 0}; ! 926: static int fire_frames[] = {5, 0}; ! 927: ! 928: Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); ! 929: ! 930: // RAFAEL ! 931: if (is_quadfire) ! 932: Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); ! 933: ! 934: } ! 935: ! 936: ! 937: void Weapon_HyperBlaster_Fire (edict_t *ent) ! 938: { ! 939: float rotation; ! 940: vec3_t offset; ! 941: int effect; ! 942: int damage; ! 943: ! 944: ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); ! 945: ! 946: if (!(ent->client->buttons & BUTTON_ATTACK)) ! 947: { ! 948: ent->client->ps.gunframe++; ! 949: } ! 950: else ! 951: { ! 952: if (! ent->client->pers.inventory[ent->client->ammo_index] ) ! 953: { ! 954: if (level.time >= ent->pain_debounce_time) ! 955: { ! 956: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 957: ent->pain_debounce_time = level.time + 1; ! 958: } ! 959: NoAmmoWeaponChange (ent); ! 960: } ! 961: else ! 962: { ! 963: rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; ! 964: offset[0] = -4 * sin(rotation); ! 965: offset[1] = 0; ! 966: offset[2] = 4 * cos(rotation); ! 967: ! 968: if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) ! 969: effect = EF_HYPERBLASTER; ! 970: else ! 971: effect = 0; ! 972: if (deathmatch->value) ! 973: damage = 15; ! 974: else ! 975: damage = 20; ! 976: Blaster_Fire (ent, offset, damage, true, effect); ! 977: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 978: ent->client->pers.inventory[ent->client->ammo_index]--; ! 979: ! 980: ent->client->anim_priority = ANIM_ATTACK; ! 981: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 982: { ! 983: ent->s.frame = FRAME_crattak1 - 1; ! 984: ent->client->anim_end = FRAME_crattak9; ! 985: } ! 986: else ! 987: { ! 988: ent->s.frame = FRAME_attack1 - 1; ! 989: ent->client->anim_end = FRAME_attack8; ! 990: } ! 991: } ! 992: ! 993: ent->client->ps.gunframe++; ! 994: if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index]) ! 995: ent->client->ps.gunframe = 6; ! 996: } ! 997: ! 998: if (ent->client->ps.gunframe == 12) ! 999: { ! 1000: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); ! 1001: ent->client->weapon_sound = 0; ! 1002: } ! 1003: ! 1004: } ! 1005: ! 1006: void Weapon_HyperBlaster (edict_t *ent) ! 1007: { ! 1008: static int pause_frames[] = {0}; ! 1009: static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; ! 1010: ! 1011: Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); ! 1012: ! 1013: ! 1014: // RAFAEL ! 1015: if (is_quadfire) ! 1016: Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); ! 1017: ! 1018: } ! 1019: ! 1020: /* ! 1021: ====================================================================== ! 1022: ! 1023: MACHINEGUN / CHAINGUN ! 1024: ! 1025: ====================================================================== ! 1026: */ ! 1027: ! 1028: void Machinegun_Fire (edict_t *ent) ! 1029: { ! 1030: int i; ! 1031: vec3_t start; ! 1032: vec3_t forward, right; ! 1033: vec3_t angles; ! 1034: int damage = 8; ! 1035: int kick = 2; ! 1036: vec3_t offset; ! 1037: ! 1038: if (!(ent->client->buttons & BUTTON_ATTACK)) ! 1039: { ! 1040: ent->client->machinegun_shots = 0; ! 1041: ent->client->ps.gunframe++; ! 1042: return; ! 1043: } ! 1044: ! 1045: if (ent->client->ps.gunframe == 5) ! 1046: ent->client->ps.gunframe = 4; ! 1047: else ! 1048: ent->client->ps.gunframe = 5; ! 1049: ! 1050: if (ent->client->pers.inventory[ent->client->ammo_index] < 1) ! 1051: { ! 1052: ent->client->ps.gunframe = 6; ! 1053: if (level.time >= ent->pain_debounce_time) ! 1054: { ! 1055: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 1056: ent->pain_debounce_time = level.time + 1; ! 1057: } ! 1058: NoAmmoWeaponChange (ent); ! 1059: return; ! 1060: } ! 1061: ! 1062: if (is_quad) ! 1063: { ! 1064: damage *= 4; ! 1065: kick *= 4; ! 1066: } ! 1067: ! 1068: for (i=1 ; i<3 ; i++) ! 1069: { ! 1070: ent->client->kick_origin[i] = crandom() * 0.35; ! 1071: ent->client->kick_angles[i] = crandom() * 0.7; ! 1072: } ! 1073: ent->client->kick_origin[0] = crandom() * 0.35; ! 1074: ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; ! 1075: ! 1076: // raise the gun as it is firing ! 1077: if (!deathmatch->value) ! 1078: { ! 1079: ent->client->machinegun_shots++; ! 1080: if (ent->client->machinegun_shots > 9) ! 1081: ent->client->machinegun_shots = 9; ! 1082: } ! 1083: ! 1084: // get start / end positions ! 1085: VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); ! 1086: AngleVectors (angles, forward, right, NULL); ! 1087: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1088: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1089: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); ! 1090: ! 1091: gi.WriteByte (svc_muzzleflash); ! 1092: gi.WriteShort (ent-g_edicts); ! 1093: gi.WriteByte (MZ_MACHINEGUN | is_silenced); ! 1094: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1095: ! 1096: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1097: ! 1098: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1099: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1100: ! 1101: ent->client->anim_priority = ANIM_ATTACK; ! 1102: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 1103: { ! 1104: ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); ! 1105: ent->client->anim_end = FRAME_crattak9; ! 1106: } ! 1107: else ! 1108: { ! 1109: ent->s.frame = FRAME_attack1 - (int) (random()+0.25); ! 1110: ent->client->anim_end = FRAME_attack8; ! 1111: } ! 1112: } ! 1113: ! 1114: void Weapon_Machinegun (edict_t *ent) ! 1115: { ! 1116: static int pause_frames[] = {23, 45, 0}; ! 1117: static int fire_frames[] = {4, 5, 0}; ! 1118: ! 1119: Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); ! 1120: ! 1121: // RAFAEL ! 1122: if (is_quadfire) ! 1123: Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); ! 1124: ! 1125: } ! 1126: ! 1127: void Chaingun_Fire (edict_t *ent) ! 1128: { ! 1129: int i; ! 1130: int shots; ! 1131: vec3_t start; ! 1132: vec3_t forward, right, up; ! 1133: float r, u; ! 1134: vec3_t offset; ! 1135: int damage; ! 1136: int kick = 2; ! 1137: ! 1138: if (deathmatch->value) ! 1139: damage = 6; ! 1140: else ! 1141: damage = 8; ! 1142: ! 1143: if (ent->client->ps.gunframe == 5) ! 1144: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); ! 1145: ! 1146: if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) ! 1147: { ! 1148: ent->client->ps.gunframe = 32; ! 1149: ent->client->weapon_sound = 0; ! 1150: return; ! 1151: } ! 1152: else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) ! 1153: && ent->client->pers.inventory[ent->client->ammo_index]) ! 1154: { ! 1155: ent->client->ps.gunframe = 15; ! 1156: } ! 1157: else ! 1158: { ! 1159: ent->client->ps.gunframe++; ! 1160: } ! 1161: ! 1162: if (ent->client->ps.gunframe == 22) ! 1163: { ! 1164: ent->client->weapon_sound = 0; ! 1165: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); ! 1166: } ! 1167: else ! 1168: { ! 1169: ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); ! 1170: } ! 1171: ! 1172: ent->client->anim_priority = ANIM_ATTACK; ! 1173: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 1174: { ! 1175: ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ! 1176: ent->client->anim_end = FRAME_crattak9; ! 1177: } ! 1178: else ! 1179: { ! 1180: ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ! 1181: ent->client->anim_end = FRAME_attack8; ! 1182: } ! 1183: ! 1184: if (ent->client->ps.gunframe <= 9) ! 1185: shots = 1; ! 1186: else if (ent->client->ps.gunframe <= 14) ! 1187: { ! 1188: if (ent->client->buttons & BUTTON_ATTACK) ! 1189: shots = 2; ! 1190: else ! 1191: shots = 1; ! 1192: } ! 1193: else ! 1194: shots = 3; ! 1195: ! 1196: if (ent->client->pers.inventory[ent->client->ammo_index] < shots) ! 1197: shots = ent->client->pers.inventory[ent->client->ammo_index]; ! 1198: ! 1199: if (!shots) ! 1200: { ! 1201: if (level.time >= ent->pain_debounce_time) ! 1202: { ! 1203: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 1204: ent->pain_debounce_time = level.time + 1; ! 1205: } ! 1206: NoAmmoWeaponChange (ent); ! 1207: return; ! 1208: } ! 1209: ! 1210: if (is_quad) ! 1211: { ! 1212: damage *= 4; ! 1213: kick *= 4; ! 1214: } ! 1215: ! 1216: for (i=0 ; i<3 ; i++) ! 1217: { ! 1218: ent->client->kick_origin[i] = crandom() * 0.35; ! 1219: ent->client->kick_angles[i] = crandom() * 0.7; ! 1220: } ! 1221: ! 1222: for (i=0 ; i<shots ; i++) ! 1223: { ! 1224: // get start / end positions ! 1225: AngleVectors (ent->client->v_angle, forward, right, up); ! 1226: r = 7 + crandom()*4; ! 1227: u = crandom()*4; ! 1228: VectorSet(offset, 0, r, u + ent->viewheight-8); ! 1229: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1230: ! 1231: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); ! 1232: } ! 1233: ! 1234: // send muzzle flash ! 1235: gi.WriteByte (svc_muzzleflash); ! 1236: gi.WriteShort (ent-g_edicts); ! 1237: gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); ! 1238: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1239: ! 1240: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1241: ! 1242: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1243: ent->client->pers.inventory[ent->client->ammo_index] -= shots; ! 1244: } ! 1245: ! 1246: ! 1247: void Weapon_Chaingun (edict_t *ent) ! 1248: { ! 1249: static int pause_frames[] = {38, 43, 51, 61, 0}; ! 1250: static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; ! 1251: ! 1252: Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); ! 1253: ! 1254: ! 1255: // RAFAEL ! 1256: if (is_quadfire) ! 1257: Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); ! 1258: ! 1259: } ! 1260: ! 1261: ! 1262: /* ! 1263: ====================================================================== ! 1264: ! 1265: SHOTGUN / SUPERSHOTGUN ! 1266: ! 1267: ====================================================================== ! 1268: */ ! 1269: ! 1270: void weapon_shotgun_fire (edict_t *ent) ! 1271: { ! 1272: vec3_t start; ! 1273: vec3_t forward, right; ! 1274: vec3_t offset; ! 1275: int damage = 4; ! 1276: int kick = 8; ! 1277: ! 1278: if (ent->client->ps.gunframe == 9) ! 1279: { ! 1280: ent->client->ps.gunframe++; ! 1281: return; ! 1282: } ! 1283: ! 1284: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1285: ! 1286: VectorScale (forward, -2, ent->client->kick_origin); ! 1287: ent->client->kick_angles[0] = -2; ! 1288: ! 1289: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1290: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1291: ! 1292: if (is_quad) ! 1293: { ! 1294: damage *= 4; ! 1295: kick *= 4; ! 1296: } ! 1297: ! 1298: if (deathmatch->value) ! 1299: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN); ! 1300: else ! 1301: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); ! 1302: ! 1303: // send muzzle flash ! 1304: gi.WriteByte (svc_muzzleflash); ! 1305: gi.WriteShort (ent-g_edicts); ! 1306: gi.WriteByte (MZ_SHOTGUN | is_silenced); ! 1307: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1308: ! 1309: ent->client->ps.gunframe++; ! 1310: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1311: ! 1312: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1313: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1314: } ! 1315: ! 1316: void Weapon_Shotgun (edict_t *ent) ! 1317: { ! 1318: static int pause_frames[] = {22, 28, 34, 0}; ! 1319: static int fire_frames[] = {8, 9, 0}; ! 1320: ! 1321: Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); ! 1322: ! 1323: ! 1324: // RAFAEL ! 1325: if (is_quadfire) ! 1326: Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); ! 1327: } ! 1328: ! 1329: ! 1330: void weapon_supershotgun_fire (edict_t *ent) ! 1331: { ! 1332: vec3_t start; ! 1333: vec3_t forward, right; ! 1334: vec3_t offset; ! 1335: vec3_t v; ! 1336: int damage = 6; ! 1337: int kick = 12; ! 1338: ! 1339: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1340: ! 1341: VectorScale (forward, -2, ent->client->kick_origin); ! 1342: ent->client->kick_angles[0] = -2; ! 1343: ! 1344: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1345: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1346: ! 1347: if (is_quad) ! 1348: { ! 1349: damage *= 4; ! 1350: kick *= 4; ! 1351: } ! 1352: ! 1353: v[PITCH] = ent->client->v_angle[PITCH]; ! 1354: v[YAW] = ent->client->v_angle[YAW] - 5; ! 1355: v[ROLL] = ent->client->v_angle[ROLL]; ! 1356: AngleVectors (v, forward, NULL, NULL); ! 1357: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); ! 1358: v[YAW] = ent->client->v_angle[YAW] + 5; ! 1359: AngleVectors (v, forward, NULL, NULL); ! 1360: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); ! 1361: ! 1362: // send muzzle flash ! 1363: gi.WriteByte (svc_muzzleflash); ! 1364: gi.WriteShort (ent-g_edicts); ! 1365: gi.WriteByte (MZ_SSHOTGUN | is_silenced); ! 1366: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1367: ! 1368: ent->client->ps.gunframe++; ! 1369: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1370: ! 1371: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1372: ent->client->pers.inventory[ent->client->ammo_index] -= 2; ! 1373: } ! 1374: ! 1375: void Weapon_SuperShotgun (edict_t *ent) ! 1376: { ! 1377: static int pause_frames[] = {29, 42, 57, 0}; ! 1378: static int fire_frames[] = {7, 0}; ! 1379: ! 1380: Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); ! 1381: ! 1382: ! 1383: // RAFAEL ! 1384: if (is_quadfire) ! 1385: Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); ! 1386: } ! 1387: ! 1388: ! 1389: ! 1390: /* ! 1391: ====================================================================== ! 1392: ! 1393: RAILGUN ! 1394: ! 1395: ====================================================================== ! 1396: */ ! 1397: ! 1398: void weapon_railgun_fire (edict_t *ent) ! 1399: { ! 1400: vec3_t start; ! 1401: vec3_t forward, right; ! 1402: vec3_t offset; ! 1403: int damage; ! 1404: int kick; ! 1405: ! 1406: if (deathmatch->value) ! 1407: { // normal damage is too extreme in dm ! 1408: damage = 100; ! 1409: kick = 200; ! 1410: } ! 1411: else ! 1412: { ! 1413: damage = 150; ! 1414: kick = 250; ! 1415: } ! 1416: ! 1417: if (is_quad) ! 1418: { ! 1419: damage *= 4; ! 1420: kick *= 4; ! 1421: } ! 1422: ! 1423: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1424: ! 1425: VectorScale (forward, -3, ent->client->kick_origin); ! 1426: ent->client->kick_angles[0] = -3; ! 1427: ! 1428: VectorSet(offset, 0, 7, ent->viewheight-8); ! 1429: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1430: fire_rail (ent, start, forward, damage, kick); ! 1431: ! 1432: // send muzzle flash ! 1433: gi.WriteByte (svc_muzzleflash); ! 1434: gi.WriteShort (ent-g_edicts); ! 1435: gi.WriteByte (MZ_RAILGUN | is_silenced); ! 1436: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1437: ! 1438: ent->client->ps.gunframe++; ! 1439: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1440: ! 1441: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1442: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1443: } ! 1444: ! 1445: ! 1446: void Weapon_Railgun (edict_t *ent) ! 1447: { ! 1448: static int pause_frames[] = {56, 0}; ! 1449: static int fire_frames[] = {4, 0}; ! 1450: ! 1451: Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); ! 1452: ! 1453: ! 1454: // RAFAEL ! 1455: if (is_quadfire) ! 1456: Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); ! 1457: } ! 1458: ! 1459: ! 1460: /* ! 1461: ====================================================================== ! 1462: ! 1463: BFG10K ! 1464: ! 1465: ====================================================================== ! 1466: */ ! 1467: ! 1468: void weapon_bfg_fire (edict_t *ent) ! 1469: { ! 1470: vec3_t offset, start; ! 1471: vec3_t forward, right; ! 1472: int damage; ! 1473: float damage_radius = 1000; ! 1474: ! 1475: if (deathmatch->value) ! 1476: damage = 200; ! 1477: else ! 1478: damage = 500; ! 1479: ! 1480: if (ent->client->ps.gunframe == 9) ! 1481: { ! 1482: // send muzzle flash ! 1483: gi.WriteByte (svc_muzzleflash); ! 1484: gi.WriteShort (ent-g_edicts); ! 1485: gi.WriteByte (MZ_BFG | is_silenced); ! 1486: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1487: ! 1488: ent->client->ps.gunframe++; ! 1489: ! 1490: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1491: return; ! 1492: } ! 1493: ! 1494: // cells can go down during windup (from power armor hits), so ! 1495: // check again and abort firing if we don't have enough now ! 1496: if (ent->client->pers.inventory[ent->client->ammo_index] < 50) ! 1497: { ! 1498: ent->client->ps.gunframe++; ! 1499: return; ! 1500: } ! 1501: ! 1502: if (is_quad) ! 1503: damage *= 4; ! 1504: ! 1505: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1506: ! 1507: VectorScale (forward, -2, ent->client->kick_origin); ! 1508: ! 1509: // make a big pitch kick with an inverse fall ! 1510: ent->client->v_dmg_pitch = -40; ! 1511: ent->client->v_dmg_roll = crandom()*8; ! 1512: ent->client->v_dmg_time = level.time + DAMAGE_TIME; ! 1513: ! 1514: VectorSet(offset, 8, 8, ent->viewheight-8); ! 1515: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1516: fire_bfg (ent, start, forward, damage, 400, damage_radius); ! 1517: ! 1518: ent->client->ps.gunframe++; ! 1519: ! 1520: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1521: ! 1522: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1523: ent->client->pers.inventory[ent->client->ammo_index] -= 50; ! 1524: } ! 1525: ! 1526: void Weapon_BFG (edict_t *ent) ! 1527: { ! 1528: static int pause_frames[] = {39, 45, 50, 55, 0}; ! 1529: static int fire_frames[] = {9, 17, 0}; ! 1530: ! 1531: Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); ! 1532: ! 1533: // RAFAEL ! 1534: if (is_quadfire) ! 1535: Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); ! 1536: } ! 1537: ! 1538: ! 1539: //====================================================================== ! 1540: ! 1541: ! 1542: // RAFAEL ! 1543: /* ! 1544: RipperGun ! 1545: */ ! 1546: ! 1547: void weapon_ionripper_fire (edict_t *ent) ! 1548: { ! 1549: vec3_t start; ! 1550: vec3_t forward, right; ! 1551: vec3_t offset; ! 1552: vec3_t tempang; ! 1553: int damage; ! 1554: int kick; ! 1555: ! 1556: if (deathmatch->value) ! 1557: { ! 1558: // tone down for deathmatch ! 1559: damage = 30; ! 1560: kick = 40; ! 1561: } ! 1562: else ! 1563: { ! 1564: damage = 50; ! 1565: kick = 60; ! 1566: } ! 1567: ! 1568: if (is_quad) ! 1569: { ! 1570: damage *= 4; ! 1571: kick *= 4; ! 1572: } ! 1573: ! 1574: VectorCopy (ent->client->v_angle, tempang); ! 1575: tempang[YAW] += crandom(); ! 1576: ! 1577: AngleVectors (tempang, forward, right, NULL); ! 1578: ! 1579: VectorScale (forward, -3, ent->client->kick_origin); ! 1580: ent->client->kick_angles[0] = -3; ! 1581: ! 1582: // VectorSet (offset, 0, 7, ent->viewheight - 8); ! 1583: VectorSet (offset, 16, 7, ent->viewheight - 8); ! 1584: ! 1585: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1586: ! 1587: fire_ionripper (ent, start, forward, damage, 500, EF_IONRIPPER); ! 1588: ! 1589: // send muzzle flash ! 1590: gi.WriteByte (svc_muzzleflash); ! 1591: gi.WriteShort (ent - g_edicts); ! 1592: gi.WriteByte (MZ_IONRIPPER | is_silenced); ! 1593: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1594: ! 1595: ent->client->ps.gunframe++; ! 1596: PlayerNoise (ent, start, PNOISE_WEAPON); ! 1597: ! 1598: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1599: ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity; ! 1600: ! 1601: if (ent->client->pers.inventory[ent->client->ammo_index] < 0) ! 1602: ent->client->pers.inventory[ent->client->ammo_index] = 0; ! 1603: } ! 1604: ! 1605: ! 1606: void Weapon_Ionripper (edict_t *ent) ! 1607: { ! 1608: static int pause_frames[] = {36, 0}; ! 1609: static int fire_frames[] = {5, 0}; ! 1610: ! 1611: Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire); ! 1612: ! 1613: if (is_quadfire) ! 1614: Weapon_Generic (ent, 4, 6, 36, 39, pause_frames, fire_frames, weapon_ionripper_fire); ! 1615: } ! 1616: ! 1617: ! 1618: // ! 1619: // Phalanx ! 1620: // ! 1621: ! 1622: void weapon_phalanx_fire (edict_t *ent) ! 1623: { ! 1624: vec3_t start; ! 1625: vec3_t forward, right, up; ! 1626: vec3_t offset; ! 1627: vec3_t v; ! 1628: int kick = 12; ! 1629: int damage; ! 1630: float damage_radius; ! 1631: int radius_damage; ! 1632: ! 1633: damage = 70 + (int)(random() * 10.0); ! 1634: radius_damage = 120; ! 1635: damage_radius = 120; ! 1636: ! 1637: if (is_quad) ! 1638: { ! 1639: damage *= 4; ! 1640: radius_damage *= 4; ! 1641: } ! 1642: ! 1643: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1644: ! 1645: VectorScale (forward, -2, ent->client->kick_origin); ! 1646: ent->client->kick_angles[0] = -2; ! 1647: ! 1648: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1649: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1650: ! 1651: if (ent->client->ps.gunframe == 8) ! 1652: { ! 1653: v[PITCH] = ent->client->v_angle[PITCH]; ! 1654: v[YAW] = ent->client->v_angle[YAW] - 1.5; ! 1655: v[ROLL] = ent->client->v_angle[ROLL]; ! 1656: AngleVectors (v, forward, right, up); ! 1657: ! 1658: radius_damage = 30; ! 1659: damage_radius = 120; ! 1660: ! 1661: fire_plasma (ent, start, forward, damage, 725, damage_radius, radius_damage); ! 1662: ! 1663: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1664: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1665: } ! 1666: else ! 1667: { ! 1668: v[PITCH] = ent->client->v_angle[PITCH]; ! 1669: v[YAW] = ent->client->v_angle[YAW] + 1.5; ! 1670: v[ROLL] = ent->client->v_angle[ROLL]; ! 1671: AngleVectors (v, forward, right, up); ! 1672: fire_plasma (ent, start, forward, damage, 725, damage_radius, radius_damage); ! 1673: ! 1674: // send muzzle flash ! 1675: gi.WriteByte (svc_muzzleflash); ! 1676: gi.WriteShort (ent-g_edicts); ! 1677: gi.WriteByte (MZ_PHALANX | is_silenced); ! 1678: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1679: ! 1680: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1681: } ! 1682: ! 1683: ent->client->ps.gunframe++; ! 1684: ! 1685: } ! 1686: ! 1687: void Weapon_Phalanx (edict_t *ent) ! 1688: { ! 1689: static int pause_frames[] = {29, 42, 55, 0}; ! 1690: static int fire_frames[] = {7, 8, 0}; ! 1691: ! 1692: Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire); ! 1693: ! 1694: if (is_quadfire) ! 1695: Weapon_Generic (ent, 5, 20, 58, 63, pause_frames, fire_frames, weapon_phalanx_fire); ! 1696: ! 1697: } ! 1698: ! 1699: /* ! 1700: ====================================================================== ! 1701: ! 1702: TRAP ! 1703: ! 1704: ====================================================================== ! 1705: */ ! 1706: ! 1707: #define TRAP_TIMER 5.0 ! 1708: #define TRAP_MINSPEED 300 ! 1709: #define TRAP_MAXSPEED 700 ! 1710: ! 1711: void weapon_trap_fire (edict_t *ent, qboolean held) ! 1712: { ! 1713: vec3_t offset; ! 1714: vec3_t forward, right; ! 1715: vec3_t start; ! 1716: int damage = 125; ! 1717: float timer; ! 1718: int speed; ! 1719: float radius; ! 1720: ! 1721: radius = damage+40; ! 1722: if (is_quad) ! 1723: damage *= 4; ! 1724: ! 1725: VectorSet(offset, 8, 8, ent->viewheight-8); ! 1726: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1727: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1728: ! 1729: timer = ent->client->grenade_time - level.time; ! 1730: speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); ! 1731: // fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); ! 1732: fire_trap (ent, start, forward, damage, speed, timer, radius, held); ! 1733: ! 1734: // you don't get infinite traps! ZOID ! 1735: // if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1736: ! 1737: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1738: ! 1739: ent->client->grenade_time = level.time + 1.0; ! 1740: } ! 1741: ! 1742: void Weapon_Trap (edict_t *ent) ! 1743: { ! 1744: if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) ! 1745: { ! 1746: ChangeWeapon (ent); ! 1747: return; ! 1748: } ! 1749: ! 1750: if (ent->client->weaponstate == WEAPON_ACTIVATING) ! 1751: { ! 1752: ent->client->weaponstate = WEAPON_READY; ! 1753: ent->client->ps.gunframe = 16; ! 1754: return; ! 1755: } ! 1756: ! 1757: if (ent->client->weaponstate == WEAPON_READY) ! 1758: { ! 1759: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) ! 1760: { ! 1761: ent->client->latched_buttons &= ~BUTTON_ATTACK; ! 1762: if (ent->client->pers.inventory[ent->client->ammo_index]) ! 1763: { ! 1764: ent->client->ps.gunframe = 1; ! 1765: ent->client->weaponstate = WEAPON_FIRING; ! 1766: ent->client->grenade_time = 0; ! 1767: } ! 1768: else ! 1769: { ! 1770: if (level.time >= ent->pain_debounce_time) ! 1771: { ! 1772: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 1773: ent->pain_debounce_time = level.time + 1; ! 1774: } ! 1775: NoAmmoWeaponChange (ent); ! 1776: } ! 1777: return; ! 1778: } ! 1779: ! 1780: if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) ! 1781: { ! 1782: if (rand()&15) ! 1783: return; ! 1784: } ! 1785: ! 1786: if (++ent->client->ps.gunframe > 48) ! 1787: ent->client->ps.gunframe = 16; ! 1788: return; ! 1789: } ! 1790: ! 1791: if (ent->client->weaponstate == WEAPON_FIRING) ! 1792: { ! 1793: if (ent->client->ps.gunframe == 5) ! 1794: // RAFAEL 16-APR-98 ! 1795: // gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); ! 1796: gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/trapcock.wav"), 1, ATTN_NORM, 0); ! 1797: // END 16-APR-98 ! 1798: ! 1799: if (ent->client->ps.gunframe == 11) ! 1800: { ! 1801: if (!ent->client->grenade_time) ! 1802: { ! 1803: ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; ! 1804: // RAFAEL 16-APR-98 ! 1805: ent->client->weapon_sound = gi.soundindex("weapons/traploop.wav"); ! 1806: // END 16-APR-98 ! 1807: } ! 1808: ! 1809: // they waited too long, detonate it in their hand ! 1810: if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) ! 1811: { ! 1812: ent->client->weapon_sound = 0; ! 1813: weapon_trap_fire (ent, true); ! 1814: ent->client->grenade_blew_up = true; ! 1815: } ! 1816: ! 1817: if (ent->client->buttons & BUTTON_ATTACK) ! 1818: return; ! 1819: ! 1820: if (ent->client->grenade_blew_up) ! 1821: { ! 1822: if (level.time >= ent->client->grenade_time) ! 1823: { ! 1824: ent->client->ps.gunframe = 15; ! 1825: ent->client->grenade_blew_up = false; ! 1826: } ! 1827: else ! 1828: { ! 1829: return; ! 1830: } ! 1831: } ! 1832: } ! 1833: ! 1834: if (ent->client->ps.gunframe == 12) ! 1835: { ! 1836: ent->client->weapon_sound = 0; ! 1837: weapon_trap_fire (ent, false); ! 1838: if (ent->client->pers.inventory[ent->client->ammo_index] == 0) ! 1839: NoAmmoWeaponChange (ent); ! 1840: } ! 1841: ! 1842: if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) ! 1843: return; ! 1844: ! 1845: ent->client->ps.gunframe++; ! 1846: ! 1847: if (ent->client->ps.gunframe == 16) ! 1848: { ! 1849: ent->client->grenade_time = 0; ! 1850: ent->client->weaponstate = WEAPON_READY; ! 1851: } ! 1852: } ! 1853: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.