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