|
|
1.1.1.2 ! root 1: /* ! 2: Copyright (C) 1997-2001 Id Software, Inc. ! 3: ! 4: This program is free software; you can redistribute it and/or ! 5: modify it under the terms of the GNU General Public License ! 6: as published by the Free Software Foundation; either version 2 ! 7: of the License, or (at your option) any later version. ! 8: ! 9: This program is distributed in the hope that it will be useful, ! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ! 12: ! 13: See the GNU General Public License for more details. ! 14: ! 15: You should have received a copy of the GNU General Public License ! 16: along with this program; if not, write to the Free Software ! 17: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ! 18: ! 19: */ 1.1 root 20: // g_weapon.c 21: 22: #include "g_local.h" 23: #include "m_player.h" 24: 25: 26: static qboolean is_quad; 27: static byte is_silenced; 28: 29: 30: void weapon_grenade_fire (edict_t *ent, qboolean held); 31: 32: 33: void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result) 34: { 35: vec3_t _distance; 36: 37: VectorCopy (distance, _distance); 38: if (client->pers.hand == LEFT_HANDED) 39: _distance[1] *= -1; 40: else if (client->pers.hand == CENTER_HANDED) 41: _distance[1] = 0; 42: G_ProjectSource (point, _distance, forward, right, result); 43: } 44: 45: 46: /* 47: =============== 48: PlayerNoise 49: 50: Each player can have two noise objects associated with it: 51: a personal noise (jumping, pain, weapon firing), and a weapon 52: target noise (bullet wall impacts) 53: 54: Monsters that don't directly see the player can move 55: to a noise in hopes of seeing the player from there. 56: =============== 57: */ 58: void PlayerNoise(edict_t *who, vec3_t where, int type) 59: { 60: edict_t *noise; 61: 62: if (type == PNOISE_WEAPON) 63: { 64: if (who->client->silencer_shots) 65: { 66: who->client->silencer_shots--; 67: return; 68: } 69: } 70: 71: if (deathmatch->value) 72: return; 73: 74: if (who->flags & FL_NOTARGET) 75: return; 76: 77: 78: if (!who->mynoise) 79: { 80: noise = G_Spawn(); 81: noise->classname = "player_noise"; 82: VectorSet (noise->mins, -8, -8, -8); 83: VectorSet (noise->maxs, 8, 8, 8); 84: noise->owner = who; 85: noise->svflags = SVF_NOCLIENT; 86: who->mynoise = noise; 87: 88: noise = G_Spawn(); 89: noise->classname = "player_noise"; 90: VectorSet (noise->mins, -8, -8, -8); 91: VectorSet (noise->maxs, 8, 8, 8); 92: noise->owner = who; 93: noise->svflags = SVF_NOCLIENT; 94: who->mynoise2 = noise; 95: } 96: 97: if (type == PNOISE_SELF || type == PNOISE_WEAPON) 98: { 99: noise = who->mynoise; 100: level.sound_entity = noise; 101: level.sound_entity_framenum = level.framenum; 102: } 103: else // type == PNOISE_IMPACT 104: { 105: noise = who->mynoise2; 106: level.sound2_entity = noise; 107: level.sound2_entity_framenum = level.framenum; 108: } 109: 110: VectorCopy (where, noise->s.origin); 111: VectorSubtract (where, noise->maxs, noise->absmin); 112: VectorAdd (where, noise->maxs, noise->absmax); 113: noise->teleport_time = level.time; 114: gi.linkentity (noise); 115: } 116: 117: 118: qboolean Pickup_Weapon (edict_t *ent, edict_t *other) 119: { 120: int index; 121: gitem_t *ammo; 122: 123: index = ITEM_INDEX(ent->item); 124: 125: if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value) 126: && other->client->pers.inventory[index]) 127: { 128: if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) ) 129: return false; // leave the weapon for others to pickup 130: } 131: 132: other->client->pers.inventory[index]++; 133: 134: if (!(ent->spawnflags & DROPPED_ITEM) ) 135: { 136: // give them some ammo with it 137: ammo = FindItem (ent->item->ammo); 138: if ( (int)dmflags->value & DF_INFINITE_AMMO ) 139: Add_Ammo (other, ammo, 1000); 140: else 141: Add_Ammo (other, ammo, ammo->quantity); 142: 143: if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) ) 144: { 145: if (deathmatch->value) 146: { 147: if ((int)(dmflags->value) & DF_WEAPONS_STAY) 148: ent->flags |= FL_RESPAWN; 149: else 150: SetRespawn (ent, 30); 151: } 152: if (coop->value) 153: ent->flags |= FL_RESPAWN; 154: } 155: } 156: 157: if (other->client->pers.weapon != ent->item && 158: (other->client->pers.inventory[index] == 1) && 159: ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) ) 160: other->client->newweapon = ent->item; 161: 162: return true; 163: } 164: 165: 166: /* 167: =============== 168: ChangeWeapon 169: 170: The old weapon has been dropped all the way, so make the new one 171: current 172: =============== 173: */ 174: void ChangeWeapon (edict_t *ent) 175: { 176: int i; 177: 178: if (ent->client->grenade_time) 179: { 180: ent->client->grenade_time = level.time; 181: ent->client->weapon_sound = 0; 182: weapon_grenade_fire (ent, false); 183: ent->client->grenade_time = 0; 184: } 185: 186: ent->client->pers.lastweapon = ent->client->pers.weapon; 187: ent->client->pers.weapon = ent->client->newweapon; 188: ent->client->newweapon = NULL; 189: ent->client->machinegun_shots = 0; 190: 191: // set visible model 192: if (ent->s.modelindex == 255) { 193: if (ent->client->pers.weapon) 194: i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8); 195: else 196: i = 0; 197: ent->s.skinnum = (ent - g_edicts - 1) | i; 198: } 199: 200: if (ent->client->pers.weapon && ent->client->pers.weapon->ammo) 201: ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo)); 202: else 203: ent->client->ammo_index = 0; 204: 205: if (!ent->client->pers.weapon) 206: { // dead 207: ent->client->ps.gunindex = 0; 208: return; 209: } 210: 211: ent->client->weaponstate = WEAPON_ACTIVATING; 212: ent->client->ps.gunframe = 0; 213: ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model); 214: 215: ent->client->anim_priority = ANIM_PAIN; 216: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) 217: { 218: ent->s.frame = FRAME_crpain1; 219: ent->client->anim_end = FRAME_crpain4; 220: } 221: else 222: { 223: ent->s.frame = FRAME_pain301; 224: ent->client->anim_end = FRAME_pain304; 225: 226: } 227: } 228: 229: /* 230: ================= 231: NoAmmoWeaponChange 232: ================= 233: */ 234: void NoAmmoWeaponChange (edict_t *ent) 235: { 236: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))] 237: && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] ) 238: { 239: ent->client->newweapon = FindItem ("railgun"); 240: return; 241: } 242: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] 243: && ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] ) 244: { 245: ent->client->newweapon = FindItem ("hyperblaster"); 246: return; 247: } 248: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] 249: && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] ) 250: { 251: ent->client->newweapon = FindItem ("chaingun"); 252: return; 253: } 254: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))] 255: && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] ) 256: { 257: ent->client->newweapon = FindItem ("machinegun"); 258: return; 259: } 260: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1 261: && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] ) 262: { 263: ent->client->newweapon = FindItem ("super shotgun"); 264: return; 265: } 266: if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] 267: && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] ) 268: { 269: ent->client->newweapon = FindItem ("shotgun"); 270: return; 271: } 272: ent->client->newweapon = FindItem ("blaster"); 273: } 274: 275: /* 276: ================= 277: Think_Weapon 278: 279: Called by ClientBeginServerFrame and ClientThink 280: ================= 281: */ 282: void Think_Weapon (edict_t *ent) 283: { 284: // if just died, put the weapon away 285: if (ent->health < 1) 286: { 287: ent->client->newweapon = NULL; 288: ChangeWeapon (ent); 289: } 290: 291: // call active weapon think routine 292: if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) 293: { 294: is_quad = (ent->client->quad_framenum > level.framenum); 295: if (ent->client->silencer_shots) 296: is_silenced = MZ_SILENCED; 297: else 298: is_silenced = 0; 299: ent->client->pers.weapon->weaponthink (ent); 300: } 301: } 302: 303: 304: /* 305: ================ 306: Use_Weapon 307: 308: Make the weapon ready if there is ammo 309: ================ 310: */ 311: void Use_Weapon (edict_t *ent, gitem_t *item) 312: { 313: int ammo_index; 314: gitem_t *ammo_item; 315: 316: // see if we're already using it 317: if (item == ent->client->pers.weapon) 318: return; 319: 320: if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) 321: { 322: ammo_item = FindItem(item->ammo); 323: ammo_index = ITEM_INDEX(ammo_item); 324: 325: if (!ent->client->pers.inventory[ammo_index]) 326: { 327: gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name); 328: return; 329: } 330: 331: if (ent->client->pers.inventory[ammo_index] < item->quantity) 332: { 333: gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name); 334: return; 335: } 336: } 337: 338: // change to this weapon when down 339: ent->client->newweapon = item; 340: } 341: 342: 343: 344: /* 345: ================ 346: Drop_Weapon 347: ================ 348: */ 349: void Drop_Weapon (edict_t *ent, gitem_t *item) 350: { 351: int index; 352: 353: if ((int)(dmflags->value) & DF_WEAPONS_STAY) 354: return; 355: 356: index = ITEM_INDEX(item); 357: // see if we're already using it 358: if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) ) 359: { 360: gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n"); 361: return; 362: } 363: 364: Drop_Item (ent, item); 365: ent->client->pers.inventory[index]--; 366: } 367: 368: 369: /* 370: ================ 371: Weapon_Generic 372: 373: A generic function to handle the basics of weapon thinking 374: ================ 375: */ 376: #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1) 377: #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1) 378: #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1) 379: 380: static void Weapon_Generic2 (edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent)) 381: { 382: int n; 383: 384: if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses 385: { 386: return; 387: } 388: 389: if (ent->client->weaponstate == WEAPON_DROPPING) 390: { 391: if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) 392: { 393: ChangeWeapon (ent); 394: return; 395: } 396: else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4) 397: { 398: ent->client->anim_priority = ANIM_REVERSE; 399: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) 400: { 401: ent->s.frame = FRAME_crpain4+1; 402: ent->client->anim_end = FRAME_crpain1; 403: } 404: else 405: { 406: ent->s.frame = FRAME_pain304+1; 407: ent->client->anim_end = FRAME_pain301; 408: 409: } 410: } 411: 412: ent->client->ps.gunframe++; 413: return; 414: } 415: 416: if (ent->client->weaponstate == WEAPON_ACTIVATING) 417: { 418: if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST || instantweap->value) 419: { 420: ent->client->weaponstate = WEAPON_READY; 421: ent->client->ps.gunframe = FRAME_IDLE_FIRST; 422: return; 423: } 424: 425: ent->client->ps.gunframe++; 426: return; 427: } 428: 429: if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) 430: { 431: ent->client->weaponstate = WEAPON_DROPPING; 432: if (instantweap->value) { 433: ChangeWeapon(ent); 434: return; 435: } else 436: ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; 437: 438: if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) 439: { 440: ent->client->anim_priority = ANIM_REVERSE; 441: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) 442: { 443: ent->s.frame = FRAME_crpain4+1; 444: ent->client->anim_end = FRAME_crpain1; 445: } 446: else 447: { 448: ent->s.frame = FRAME_pain304+1; 449: ent->client->anim_end = FRAME_pain301; 450: 451: } 452: } 453: return; 454: } 455: 456: if (ent->client->weaponstate == WEAPON_READY) 457: { 458: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) 459: { 460: ent->client->latched_buttons &= ~BUTTON_ATTACK; 461: if ((!ent->client->ammo_index) || 462: ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) 463: { 464: ent->client->ps.gunframe = FRAME_FIRE_FIRST; 465: ent->client->weaponstate = WEAPON_FIRING; 466: 467: // start the animation 468: ent->client->anim_priority = ANIM_ATTACK; 469: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) 470: { 471: ent->s.frame = FRAME_crattak1-1; 472: ent->client->anim_end = FRAME_crattak9; 473: } 474: else 475: { 476: ent->s.frame = FRAME_attack1-1; 477: ent->client->anim_end = FRAME_attack8; 478: } 479: } 480: else 481: { 482: if (level.time >= ent->pain_debounce_time) 483: { 484: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); 485: ent->pain_debounce_time = level.time + 1; 486: } 487: NoAmmoWeaponChange (ent); 488: } 489: } 490: else 491: { 492: if (ent->client->ps.gunframe == FRAME_IDLE_LAST) 493: { 494: ent->client->ps.gunframe = FRAME_IDLE_FIRST; 495: return; 496: } 497: 498: if (pause_frames) 499: { 500: for (n = 0; pause_frames[n]; n++) 501: { 502: if (ent->client->ps.gunframe == pause_frames[n]) 503: { 504: if (rand()&15) 505: return; 506: } 507: } 508: } 509: 510: ent->client->ps.gunframe++; 511: return; 512: } 513: } 514: 515: if (ent->client->weaponstate == WEAPON_FIRING) 516: { 517: for (n = 0; fire_frames[n]; n++) 518: { 519: if (ent->client->ps.gunframe == fire_frames[n]) 520: { 521: //ZOID 522: if (!CTFApplyStrengthSound(ent)) 523: //ZOID 524: if (ent->client->quad_framenum > level.framenum) 525: gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); 526: //ZOID 527: CTFApplyHasteSound(ent); 528: //ZOID 529: 530: fire (ent); 531: break; 532: } 533: } 534: 535: if (!fire_frames[n]) 536: ent->client->ps.gunframe++; 537: 538: if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) 539: ent->client->weaponstate = WEAPON_READY; 540: } 541: } 542: 543: //ZOID 544: 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)) 545: { 546: int oldstate = ent->client->weaponstate; 547: 548: Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, 549: FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, 550: fire_frames, fire); 551: 552: // run the weapon frame again if hasted 553: if (stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 && 554: ent->client->weaponstate == WEAPON_FIRING) 555: return; 556: 557: if ((CTFApplyHaste(ent) || 558: (Q_stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 && 559: ent->client->weaponstate != WEAPON_FIRING)) 560: && oldstate == ent->client->weaponstate) { 561: Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, 562: FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, 563: fire_frames, fire); 564: } 565: } 566: //ZOID 567: 568: /* 569: ====================================================================== 570: 571: GRENADE 572: 573: ====================================================================== 574: */ 575: 576: #define GRENADE_TIMER 3.0 577: #define GRENADE_MINSPEED 400 578: #define GRENADE_MAXSPEED 800 579: 580: void weapon_grenade_fire (edict_t *ent, qboolean held) 581: { 582: vec3_t offset; 583: vec3_t forward, right; 584: vec3_t start; 585: int damage = 125; 586: float timer; 587: int speed; 588: float radius; 589: 590: radius = damage+40; 591: if (is_quad) 592: damage *= 4; 593: 594: VectorSet(offset, 8, 8, ent->viewheight-8); 595: AngleVectors (ent->client->v_angle, forward, right, NULL); 596: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 597: 598: timer = ent->client->grenade_time - level.time; 599: speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); 600: fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); 601: 602: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 603: ent->client->pers.inventory[ent->client->ammo_index]--; 604: 605: ent->client->grenade_time = level.time + 1.0; 606: 607: if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses 608: { 609: return; 610: } 611: 612: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) 613: { 614: ent->client->anim_priority = ANIM_ATTACK; 615: ent->s.frame = FRAME_crattak1-1; 616: ent->client->anim_end = FRAME_crattak3; 617: } 618: else 619: { 620: ent->client->anim_priority = ANIM_REVERSE; 621: ent->s.frame = FRAME_wave08; 622: ent->client->anim_end = FRAME_wave01; 623: } 624: } 625: 626: void Weapon_Grenade (edict_t *ent) 627: { 628: if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) 629: { 630: ChangeWeapon (ent); 631: return; 632: } 633: 634: if (ent->client->weaponstate == WEAPON_ACTIVATING) 635: { 636: ent->client->weaponstate = WEAPON_READY; 637: ent->client->ps.gunframe = 16; 638: return; 639: } 640: 641: if (ent->client->weaponstate == WEAPON_READY) 642: { 643: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) 644: { 645: ent->client->latched_buttons &= ~BUTTON_ATTACK; 646: if (ent->client->pers.inventory[ent->client->ammo_index]) 647: { 648: ent->client->ps.gunframe = 1; 649: ent->client->weaponstate = WEAPON_FIRING; 650: ent->client->grenade_time = 0; 651: } 652: else 653: { 654: if (level.time >= ent->pain_debounce_time) 655: { 656: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); 657: ent->pain_debounce_time = level.time + 1; 658: } 659: NoAmmoWeaponChange (ent); 660: } 661: return; 662: } 663: 664: if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) 665: { 666: if (rand()&15) 667: return; 668: } 669: 670: if (++ent->client->ps.gunframe > 48) 671: ent->client->ps.gunframe = 16; 672: return; 673: } 674: 675: if (ent->client->weaponstate == WEAPON_FIRING) 676: { 677: if (ent->client->ps.gunframe == 5) 678: gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); 679: 680: if (ent->client->ps.gunframe == 11) 681: { 682: if (!ent->client->grenade_time) 683: { 684: ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; 685: ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); 686: } 687: 688: // they waited too long, detonate it in their hand 689: if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) 690: { 691: ent->client->weapon_sound = 0; 692: weapon_grenade_fire (ent, true); 693: ent->client->grenade_blew_up = true; 694: } 695: 696: if (ent->client->buttons & BUTTON_ATTACK) 697: return; 698: 699: if (ent->client->grenade_blew_up) 700: { 701: if (level.time >= ent->client->grenade_time) 702: { 703: ent->client->ps.gunframe = 15; 704: ent->client->grenade_blew_up = false; 705: } 706: else 707: { 708: return; 709: } 710: } 711: } 712: 713: if (ent->client->ps.gunframe == 12) 714: { 715: ent->client->weapon_sound = 0; 716: weapon_grenade_fire (ent, false); 717: } 718: 719: if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) 720: return; 721: 722: ent->client->ps.gunframe++; 723: 724: if (ent->client->ps.gunframe == 16) 725: { 726: ent->client->grenade_time = 0; 727: ent->client->weaponstate = WEAPON_READY; 728: } 729: } 730: } 731: 732: /* 733: ====================================================================== 734: 735: GRENADE LAUNCHER 736: 737: ====================================================================== 738: */ 739: 740: void weapon_grenadelauncher_fire (edict_t *ent) 741: { 742: vec3_t offset; 743: vec3_t forward, right; 744: vec3_t start; 745: int damage = 120; 746: float radius; 747: 748: radius = damage+40; 749: if (is_quad) 750: damage *= 4; 751: 752: VectorSet(offset, 8, 8, ent->viewheight-8); 753: AngleVectors (ent->client->v_angle, forward, right, NULL); 754: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 755: 756: VectorScale (forward, -2, ent->client->kick_origin); 757: ent->client->kick_angles[0] = -1; 758: 759: fire_grenade (ent, start, forward, damage, 600, 2.5, radius); 760: 761: gi.WriteByte (svc_muzzleflash); 762: gi.WriteShort (ent-g_edicts); 763: gi.WriteByte (MZ_GRENADE | is_silenced); 764: gi.multicast (ent->s.origin, MULTICAST_PVS); 765: 766: ent->client->ps.gunframe++; 767: 768: PlayerNoise(ent, start, PNOISE_WEAPON); 769: 770: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 771: ent->client->pers.inventory[ent->client->ammo_index]--; 772: } 773: 774: void Weapon_GrenadeLauncher (edict_t *ent) 775: { 776: static int pause_frames[] = {34, 51, 59, 0}; 777: static int fire_frames[] = {6, 0}; 778: 779: Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); 780: } 781: 782: /* 783: ====================================================================== 784: 785: ROCKET 786: 787: ====================================================================== 788: */ 789: 790: void Weapon_RocketLauncher_Fire (edict_t *ent) 791: { 792: vec3_t offset, start; 793: vec3_t forward, right; 794: int damage; 795: float damage_radius; 796: int radius_damage; 797: 798: damage = 100 + (int)(random() * 20.0); 799: radius_damage = 120; 800: damage_radius = 120; 801: if (is_quad) 802: { 803: damage *= 4; 804: radius_damage *= 4; 805: } 806: 807: AngleVectors (ent->client->v_angle, forward, right, NULL); 808: 809: VectorScale (forward, -2, ent->client->kick_origin); 810: ent->client->kick_angles[0] = -1; 811: 812: VectorSet(offset, 8, 8, ent->viewheight-8); 813: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 814: fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage); 815: 816: // send muzzle flash 817: gi.WriteByte (svc_muzzleflash); 818: gi.WriteShort (ent-g_edicts); 819: gi.WriteByte (MZ_ROCKET | is_silenced); 820: gi.multicast (ent->s.origin, MULTICAST_PVS); 821: 822: ent->client->ps.gunframe++; 823: 824: PlayerNoise(ent, start, PNOISE_WEAPON); 825: 826: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 827: ent->client->pers.inventory[ent->client->ammo_index]--; 828: } 829: 830: void Weapon_RocketLauncher (edict_t *ent) 831: { 832: static int pause_frames[] = {25, 33, 42, 50, 0}; 833: static int fire_frames[] = {5, 0}; 834: 835: Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); 836: } 837: 838: 839: /* 840: ====================================================================== 841: 842: BLASTER / HYPERBLASTER 843: 844: ====================================================================== 845: */ 846: 847: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect) 848: { 849: vec3_t forward, right; 850: vec3_t start; 851: vec3_t offset; 852: 853: if (is_quad) 854: damage *= 4; 855: AngleVectors (ent->client->v_angle, forward, right, NULL); 856: VectorSet(offset, 24, 8, ent->viewheight-8); 857: VectorAdd (offset, g_offset, offset); 858: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 859: 860: VectorScale (forward, -2, ent->client->kick_origin); 861: ent->client->kick_angles[0] = -1; 862: 863: fire_blaster (ent, start, forward, damage, 1000, effect, hyper); 864: 865: // send muzzle flash 866: gi.WriteByte (svc_muzzleflash); 867: gi.WriteShort (ent-g_edicts); 868: if (hyper) 869: gi.WriteByte (MZ_HYPERBLASTER | is_silenced); 870: else 871: gi.WriteByte (MZ_BLASTER | is_silenced); 872: gi.multicast (ent->s.origin, MULTICAST_PVS); 873: 874: PlayerNoise(ent, start, PNOISE_WEAPON); 875: } 876: 877: 878: void Weapon_Blaster_Fire (edict_t *ent) 879: { 880: int damage; 881: 882: if (deathmatch->value) 883: damage = 15; 884: else 885: damage = 10; 886: Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER); 887: ent->client->ps.gunframe++; 888: } 889: 890: void Weapon_Blaster (edict_t *ent) 891: { 892: static int pause_frames[] = {19, 32, 0}; 893: static int fire_frames[] = {5, 0}; 894: 895: Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); 896: } 897: 898: 899: void Weapon_HyperBlaster_Fire (edict_t *ent) 900: { 901: float rotation; 902: vec3_t offset; 903: int effect; 904: int damage; 905: 906: ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); 907: 908: if (!(ent->client->buttons & BUTTON_ATTACK)) 909: { 910: ent->client->ps.gunframe++; 911: } 912: else 913: { 914: if (! ent->client->pers.inventory[ent->client->ammo_index] ) 915: { 916: if (level.time >= ent->pain_debounce_time) 917: { 918: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); 919: ent->pain_debounce_time = level.time + 1; 920: } 921: NoAmmoWeaponChange (ent); 922: } 923: else 924: { 925: rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; 926: offset[0] = -4 * sin(rotation); 927: offset[1] = 0; 928: offset[2] = 4 * cos(rotation); 929: 930: if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) 931: effect = EF_HYPERBLASTER; 932: else 933: effect = 0; 934: if (deathmatch->value) 935: damage = 15; 936: else 937: damage = 20; 938: Blaster_Fire (ent, offset, damage, true, effect); 939: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 940: ent->client->pers.inventory[ent->client->ammo_index]--; 941: 942: ent->client->anim_priority = ANIM_ATTACK; 943: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) 944: { 945: ent->s.frame = FRAME_crattak1 - 1; 946: ent->client->anim_end = FRAME_crattak9; 947: } 948: else 949: { 950: ent->s.frame = FRAME_attack1 - 1; 951: ent->client->anim_end = FRAME_attack8; 952: } 953: } 954: 955: ent->client->ps.gunframe++; 956: if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index]) 957: ent->client->ps.gunframe = 6; 958: } 959: 960: if (ent->client->ps.gunframe == 12) 961: { 962: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); 963: ent->client->weapon_sound = 0; 964: } 965: 966: } 967: 968: void Weapon_HyperBlaster (edict_t *ent) 969: { 970: static int pause_frames[] = {0}; 971: static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; 972: 973: Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); 974: } 975: 976: /* 977: ====================================================================== 978: 979: MACHINEGUN / CHAINGUN 980: 981: ====================================================================== 982: */ 983: 984: void Machinegun_Fire (edict_t *ent) 985: { 986: int i; 987: vec3_t start; 988: vec3_t forward, right; 989: vec3_t angles; 990: int damage = 8; 991: int kick = 2; 992: vec3_t offset; 993: 994: if (!(ent->client->buttons & BUTTON_ATTACK)) 995: { 996: ent->client->machinegun_shots = 0; 997: ent->client->ps.gunframe++; 998: return; 999: } 1000: 1001: if (ent->client->ps.gunframe == 5) 1002: ent->client->ps.gunframe = 4; 1003: else 1004: ent->client->ps.gunframe = 5; 1005: 1006: if (ent->client->pers.inventory[ent->client->ammo_index] < 1) 1007: { 1008: ent->client->ps.gunframe = 6; 1009: if (level.time >= ent->pain_debounce_time) 1010: { 1011: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); 1012: ent->pain_debounce_time = level.time + 1; 1013: } 1014: NoAmmoWeaponChange (ent); 1015: return; 1016: } 1017: 1018: if (is_quad) 1019: { 1020: damage *= 4; 1021: kick *= 4; 1022: } 1023: 1024: for (i=1 ; i<3 ; i++) 1025: { 1026: ent->client->kick_origin[i] = crandom() * 0.35; 1027: ent->client->kick_angles[i] = crandom() * 0.7; 1028: } 1029: ent->client->kick_origin[0] = crandom() * 0.35; 1030: ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; 1031: 1032: // raise the gun as it is firing 1033: if (!deathmatch->value) 1034: { 1035: ent->client->machinegun_shots++; 1036: if (ent->client->machinegun_shots > 9) 1037: ent->client->machinegun_shots = 9; 1038: } 1039: 1040: // get start / end positions 1041: VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); 1042: AngleVectors (angles, forward, right, NULL); 1043: VectorSet(offset, 0, 8, ent->viewheight-8); 1044: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1045: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); 1046: 1047: gi.WriteByte (svc_muzzleflash); 1048: gi.WriteShort (ent-g_edicts); 1049: gi.WriteByte (MZ_MACHINEGUN | is_silenced); 1050: gi.multicast (ent->s.origin, MULTICAST_PVS); 1051: 1052: PlayerNoise(ent, start, PNOISE_WEAPON); 1053: 1054: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1055: ent->client->pers.inventory[ent->client->ammo_index]--; 1056: 1057: ent->client->anim_priority = ANIM_ATTACK; 1058: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) 1059: { 1060: ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); 1061: ent->client->anim_end = FRAME_crattak9; 1062: } 1063: else 1064: { 1065: ent->s.frame = FRAME_attack1 - (int) (random()+0.25); 1066: ent->client->anim_end = FRAME_attack8; 1067: } 1068: } 1069: 1070: void Weapon_Machinegun (edict_t *ent) 1071: { 1072: static int pause_frames[] = {23, 45, 0}; 1073: static int fire_frames[] = {4, 5, 0}; 1074: 1075: Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); 1076: } 1077: 1078: void Chaingun_Fire (edict_t *ent) 1079: { 1080: int i; 1081: int shots; 1082: vec3_t start; 1083: vec3_t forward, right, up; 1084: float r, u; 1085: vec3_t offset; 1086: int damage; 1087: int kick = 2; 1088: 1089: if (deathmatch->value) 1090: damage = 6; 1091: else 1092: damage = 8; 1093: 1094: if (ent->client->ps.gunframe == 5) 1095: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); 1096: 1097: if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) 1098: { 1099: ent->client->ps.gunframe = 32; 1100: ent->client->weapon_sound = 0; 1101: return; 1102: } 1103: else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) 1104: && ent->client->pers.inventory[ent->client->ammo_index]) 1105: { 1106: ent->client->ps.gunframe = 15; 1107: } 1108: else 1109: { 1110: ent->client->ps.gunframe++; 1111: } 1112: 1113: if (ent->client->ps.gunframe == 22) 1114: { 1115: ent->client->weapon_sound = 0; 1116: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); 1117: } 1118: else 1119: { 1120: ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); 1121: } 1122: 1123: ent->client->anim_priority = ANIM_ATTACK; 1124: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) 1125: { 1126: ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); 1127: ent->client->anim_end = FRAME_crattak9; 1128: } 1129: else 1130: { 1131: ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); 1132: ent->client->anim_end = FRAME_attack8; 1133: } 1134: 1135: if (ent->client->ps.gunframe <= 9) 1136: shots = 1; 1137: else if (ent->client->ps.gunframe <= 14) 1138: { 1139: if (ent->client->buttons & BUTTON_ATTACK) 1140: shots = 2; 1141: else 1142: shots = 1; 1143: } 1144: else 1145: shots = 3; 1146: 1147: if (ent->client->pers.inventory[ent->client->ammo_index] < shots) 1148: shots = ent->client->pers.inventory[ent->client->ammo_index]; 1149: 1150: if (!shots) 1151: { 1152: if (level.time >= ent->pain_debounce_time) 1153: { 1154: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); 1155: ent->pain_debounce_time = level.time + 1; 1156: } 1157: NoAmmoWeaponChange (ent); 1158: return; 1159: } 1160: 1161: if (is_quad) 1162: { 1163: damage *= 4; 1164: kick *= 4; 1165: } 1166: 1167: for (i=0 ; i<3 ; i++) 1168: { 1169: ent->client->kick_origin[i] = crandom() * 0.35; 1170: ent->client->kick_angles[i] = crandom() * 0.7; 1171: } 1172: 1173: for (i=0 ; i<shots ; i++) 1174: { 1175: // get start / end positions 1176: AngleVectors (ent->client->v_angle, forward, right, up); 1177: r = 7 + crandom()*4; 1178: u = crandom()*4; 1179: VectorSet(offset, 0, r, u + ent->viewheight-8); 1180: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1181: 1182: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); 1183: } 1184: 1185: // send muzzle flash 1186: gi.WriteByte (svc_muzzleflash); 1187: gi.WriteShort (ent-g_edicts); 1188: gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); 1189: gi.multicast (ent->s.origin, MULTICAST_PVS); 1190: 1191: PlayerNoise(ent, start, PNOISE_WEAPON); 1192: 1193: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1194: ent->client->pers.inventory[ent->client->ammo_index] -= shots; 1195: } 1196: 1197: 1198: void Weapon_Chaingun (edict_t *ent) 1199: { 1200: static int pause_frames[] = {38, 43, 51, 61, 0}; 1201: static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; 1202: 1203: Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); 1204: } 1205: 1206: 1207: /* 1208: ====================================================================== 1209: 1210: SHOTGUN / SUPERSHOTGUN 1211: 1212: ====================================================================== 1213: */ 1214: 1215: void weapon_shotgun_fire (edict_t *ent) 1216: { 1217: vec3_t start; 1218: vec3_t forward, right; 1219: vec3_t offset; 1220: int damage = 4; 1221: int kick = 8; 1222: 1223: if (ent->client->ps.gunframe == 9) 1224: { 1225: ent->client->ps.gunframe++; 1226: return; 1227: } 1228: 1229: AngleVectors (ent->client->v_angle, forward, right, NULL); 1230: 1231: VectorScale (forward, -2, ent->client->kick_origin); 1232: ent->client->kick_angles[0] = -2; 1233: 1234: VectorSet(offset, 0, 8, ent->viewheight-8); 1235: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1236: 1237: if (is_quad) 1238: { 1239: damage *= 4; 1240: kick *= 4; 1241: } 1242: 1243: if (deathmatch->value) 1244: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN); 1245: else 1246: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); 1247: 1248: // send muzzle flash 1249: gi.WriteByte (svc_muzzleflash); 1250: gi.WriteShort (ent-g_edicts); 1251: gi.WriteByte (MZ_SHOTGUN | is_silenced); 1252: gi.multicast (ent->s.origin, MULTICAST_PVS); 1253: 1254: ent->client->ps.gunframe++; 1255: PlayerNoise(ent, start, PNOISE_WEAPON); 1256: 1257: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1258: ent->client->pers.inventory[ent->client->ammo_index]--; 1259: } 1260: 1261: void Weapon_Shotgun (edict_t *ent) 1262: { 1263: static int pause_frames[] = {22, 28, 34, 0}; 1264: static int fire_frames[] = {8, 9, 0}; 1265: 1266: Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); 1267: } 1268: 1269: 1270: void weapon_supershotgun_fire (edict_t *ent) 1271: { 1272: vec3_t start; 1273: vec3_t forward, right; 1274: vec3_t offset; 1275: vec3_t v; 1276: int damage = 6; 1277: int kick = 12; 1278: 1279: AngleVectors (ent->client->v_angle, forward, right, NULL); 1280: 1281: VectorScale (forward, -2, ent->client->kick_origin); 1282: ent->client->kick_angles[0] = -2; 1283: 1284: VectorSet(offset, 0, 8, ent->viewheight-8); 1285: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1286: 1287: if (is_quad) 1288: { 1289: damage *= 4; 1290: kick *= 4; 1291: } 1292: 1293: v[PITCH] = ent->client->v_angle[PITCH]; 1294: v[YAW] = ent->client->v_angle[YAW] - 5; 1295: v[ROLL] = ent->client->v_angle[ROLL]; 1296: AngleVectors (v, forward, NULL, NULL); 1297: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); 1298: v[YAW] = ent->client->v_angle[YAW] + 5; 1299: AngleVectors (v, forward, NULL, NULL); 1300: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); 1301: 1302: // send muzzle flash 1303: gi.WriteByte (svc_muzzleflash); 1304: gi.WriteShort (ent-g_edicts); 1305: gi.WriteByte (MZ_SSHOTGUN | is_silenced); 1306: gi.multicast (ent->s.origin, MULTICAST_PVS); 1307: 1308: ent->client->ps.gunframe++; 1309: PlayerNoise(ent, start, PNOISE_WEAPON); 1310: 1311: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1312: ent->client->pers.inventory[ent->client->ammo_index] -= 2; 1313: } 1314: 1315: void Weapon_SuperShotgun (edict_t *ent) 1316: { 1317: static int pause_frames[] = {29, 42, 57, 0}; 1318: static int fire_frames[] = {7, 0}; 1319: 1320: Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); 1321: } 1322: 1323: 1324: 1325: /* 1326: ====================================================================== 1327: 1328: RAILGUN 1329: 1330: ====================================================================== 1331: */ 1332: 1333: void weapon_railgun_fire (edict_t *ent) 1334: { 1335: vec3_t start; 1336: vec3_t forward, right; 1337: vec3_t offset; 1338: int damage; 1339: int kick; 1340: 1341: if (deathmatch->value) 1342: { // normal damage is too extreme in dm 1343: damage = 100; 1344: kick = 200; 1345: } 1346: else 1347: { 1348: damage = 150; 1349: kick = 250; 1350: } 1351: 1352: if (is_quad) 1353: { 1354: damage *= 4; 1355: kick *= 4; 1356: } 1357: 1358: AngleVectors (ent->client->v_angle, forward, right, NULL); 1359: 1360: VectorScale (forward, -3, ent->client->kick_origin); 1361: ent->client->kick_angles[0] = -3; 1362: 1363: VectorSet(offset, 0, 7, ent->viewheight-8); 1364: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1365: fire_rail (ent, start, forward, damage, kick); 1366: 1367: // send muzzle flash 1368: gi.WriteByte (svc_muzzleflash); 1369: gi.WriteShort (ent-g_edicts); 1370: gi.WriteByte (MZ_RAILGUN | is_silenced); 1371: gi.multicast (ent->s.origin, MULTICAST_PVS); 1372: 1373: ent->client->ps.gunframe++; 1374: PlayerNoise(ent, start, PNOISE_WEAPON); 1375: 1376: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1377: ent->client->pers.inventory[ent->client->ammo_index]--; 1378: } 1379: 1380: 1381: void Weapon_Railgun (edict_t *ent) 1382: { 1383: static int pause_frames[] = {56, 0}; 1384: static int fire_frames[] = {4, 0}; 1385: 1386: Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); 1387: } 1388: 1389: 1390: /* 1391: ====================================================================== 1392: 1393: BFG10K 1394: 1395: ====================================================================== 1396: */ 1397: 1398: void weapon_bfg_fire (edict_t *ent) 1399: { 1400: vec3_t offset, start; 1401: vec3_t forward, right; 1402: int damage; 1403: float damage_radius = 1000; 1404: 1405: if (deathmatch->value) 1406: damage = 200; 1407: else 1408: damage = 500; 1409: 1410: if (ent->client->ps.gunframe == 9) 1411: { 1412: // send muzzle flash 1413: gi.WriteByte (svc_muzzleflash); 1414: gi.WriteShort (ent-g_edicts); 1415: gi.WriteByte (MZ_BFG | is_silenced); 1416: gi.multicast (ent->s.origin, MULTICAST_PVS); 1417: 1418: ent->client->ps.gunframe++; 1419: 1420: PlayerNoise(ent, start, PNOISE_WEAPON); 1421: return; 1422: } 1423: 1424: // cells can go down during windup (from power armor hits), so 1425: // check again and abort firing if we don't have enough now 1426: if (ent->client->pers.inventory[ent->client->ammo_index] < 50) 1427: { 1428: ent->client->ps.gunframe++; 1429: return; 1430: } 1431: 1432: if (is_quad) 1433: damage *= 4; 1434: 1435: AngleVectors (ent->client->v_angle, forward, right, NULL); 1436: 1437: VectorScale (forward, -2, ent->client->kick_origin); 1438: 1439: // make a big pitch kick with an inverse fall 1440: ent->client->v_dmg_pitch = -40; 1441: ent->client->v_dmg_roll = crandom()*8; 1442: ent->client->v_dmg_time = level.time + DAMAGE_TIME; 1443: 1444: VectorSet(offset, 8, 8, ent->viewheight-8); 1445: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); 1446: fire_bfg (ent, start, forward, damage, 400, damage_radius); 1447: 1448: ent->client->ps.gunframe++; 1449: 1450: PlayerNoise(ent, start, PNOISE_WEAPON); 1451: 1452: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) 1453: ent->client->pers.inventory[ent->client->ammo_index] -= 50; 1454: } 1455: 1456: void Weapon_BFG (edict_t *ent) 1457: { 1458: static int pause_frames[] = {39, 45, 50, 55, 0}; 1459: static int fire_frames[] = {9, 17, 0}; 1460: 1461: Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); 1462: } 1463: 1464: 1465: //======================================================================
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.