|
|
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: 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: 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)) ! 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 || instantweap->value) ! 400: { ! 401: ent->client->weaponstate = WEAPON_READY; ! 402: ent->client->ps.gunframe = FRAME_IDLE_FIRST; ! 403: // we go recursive here to instant ready the weapon ! 404: Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, ! 405: FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, ! 406: fire_frames, fire); ! 407: return; ! 408: } ! 409: ! 410: ent->client->ps.gunframe++; ! 411: return; ! 412: } ! 413: ! 414: if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) ! 415: { ! 416: ent->client->weaponstate = WEAPON_DROPPING; ! 417: if (instantweap->value) { ! 418: ChangeWeapon(ent); ! 419: return; ! 420: } else ! 421: ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST; ! 422: ! 423: if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) ! 424: { ! 425: ent->client->anim_priority = ANIM_REVERSE; ! 426: if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 427: { ! 428: ent->s.frame = FRAME_crpain4+1; ! 429: ent->client->anim_end = FRAME_crpain1; ! 430: } ! 431: else ! 432: { ! 433: ent->s.frame = FRAME_pain304+1; ! 434: ent->client->anim_end = FRAME_pain301; ! 435: ! 436: } ! 437: } ! 438: return; ! 439: } ! 440: ! 441: if (ent->client->weaponstate == WEAPON_READY) ! 442: { ! 443: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) ! 444: { ! 445: ent->client->latched_buttons &= ~BUTTON_ATTACK; ! 446: if ((!ent->client->ammo_index) || ! 447: ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) ! 448: { ! 449: ent->client->ps.gunframe = FRAME_FIRE_FIRST; ! 450: ent->client->weaponstate = WEAPON_FIRING; ! 451: ! 452: // start the animation ! 453: ent->client->anim_priority = ANIM_ATTACK; ! 454: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 455: { ! 456: ent->s.frame = FRAME_crattak1-1; ! 457: ent->client->anim_end = FRAME_crattak9; ! 458: } ! 459: else ! 460: { ! 461: ent->s.frame = FRAME_attack1-1; ! 462: ent->client->anim_end = FRAME_attack8; ! 463: } ! 464: } ! 465: else ! 466: { ! 467: if (level.time >= ent->pain_debounce_time) ! 468: { ! 469: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 470: ent->pain_debounce_time = level.time + 1; ! 471: } ! 472: NoAmmoWeaponChange (ent); ! 473: } ! 474: } ! 475: else ! 476: { ! 477: if (ent->client->ps.gunframe == FRAME_IDLE_LAST) ! 478: { ! 479: ent->client->ps.gunframe = FRAME_IDLE_FIRST; ! 480: return; ! 481: } ! 482: ! 483: if (pause_frames) ! 484: { ! 485: for (n = 0; pause_frames[n]; n++) ! 486: { ! 487: if (ent->client->ps.gunframe == pause_frames[n]) ! 488: { ! 489: if (rand()&15) ! 490: return; ! 491: } ! 492: } ! 493: } ! 494: ! 495: ent->client->ps.gunframe++; ! 496: return; ! 497: } ! 498: } ! 499: ! 500: if (ent->client->weaponstate == WEAPON_FIRING) ! 501: { ! 502: for (n = 0; fire_frames[n]; n++) ! 503: { ! 504: if (ent->client->ps.gunframe == fire_frames[n]) ! 505: { ! 506: //ZOID ! 507: if (!CTFApplyStrengthSound(ent)) ! 508: //ZOID ! 509: if (ent->client->quad_framenum > level.framenum) ! 510: gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0); ! 511: //ZOID ! 512: CTFApplyHasteSound(ent); ! 513: //ZOID ! 514: ! 515: fire (ent); ! 516: break; ! 517: } ! 518: } ! 519: ! 520: if (!fire_frames[n]) ! 521: ent->client->ps.gunframe++; ! 522: ! 523: if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1) ! 524: ent->client->weaponstate = WEAPON_READY; ! 525: } ! 526: } ! 527: ! 528: //ZOID ! 529: 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)) ! 530: { ! 531: int oldstate = ent->client->weaponstate; ! 532: ! 533: Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, ! 534: FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, ! 535: fire_frames, fire); ! 536: ! 537: // run the weapon frame again if hasted ! 538: if (stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 && ! 539: ent->client->weaponstate == WEAPON_FIRING) ! 540: return; ! 541: ! 542: if ((CTFApplyHaste(ent) || ! 543: (Q_stricmp(ent->client->pers.weapon->pickup_name, "Grapple") == 0 && ! 544: ent->client->weaponstate != WEAPON_FIRING)) ! 545: && oldstate == ent->client->weaponstate) { ! 546: Weapon_Generic2 (ent, FRAME_ACTIVATE_LAST, FRAME_FIRE_LAST, ! 547: FRAME_IDLE_LAST, FRAME_DEACTIVATE_LAST, pause_frames, ! 548: fire_frames, fire); ! 549: } ! 550: } ! 551: //ZOID ! 552: ! 553: /* ! 554: ====================================================================== ! 555: ! 556: GRENADE ! 557: ! 558: ====================================================================== ! 559: */ ! 560: ! 561: #define GRENADE_TIMER 3.0 ! 562: #define GRENADE_MINSPEED 400 ! 563: #define GRENADE_MAXSPEED 800 ! 564: ! 565: void weapon_grenade_fire (edict_t *ent, qboolean held) ! 566: { ! 567: vec3_t offset; ! 568: vec3_t forward, right; ! 569: vec3_t start; ! 570: int damage = 125; ! 571: float timer; ! 572: int speed; ! 573: float radius; ! 574: ! 575: radius = damage+40; ! 576: if (is_quad) ! 577: damage *= 4; ! 578: ! 579: VectorSet(offset, 8, 8, ent->viewheight-8); ! 580: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 581: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 582: ! 583: timer = ent->client->grenade_time - level.time; ! 584: speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER); ! 585: fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held); ! 586: ! 587: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 588: ent->client->pers.inventory[ent->client->ammo_index]--; ! 589: ! 590: ent->client->grenade_time = level.time + 1.0; ! 591: ! 592: if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses ! 593: { ! 594: return; ! 595: } ! 596: ! 597: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 598: { ! 599: ent->client->anim_priority = ANIM_ATTACK; ! 600: ent->s.frame = FRAME_crattak1-1; ! 601: ent->client->anim_end = FRAME_crattak3; ! 602: } ! 603: else ! 604: { ! 605: ent->client->anim_priority = ANIM_REVERSE; ! 606: ent->s.frame = FRAME_wave08; ! 607: ent->client->anim_end = FRAME_wave01; ! 608: } ! 609: } ! 610: ! 611: void Weapon_Grenade (edict_t *ent) ! 612: { ! 613: if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) ! 614: { ! 615: ChangeWeapon (ent); ! 616: return; ! 617: } ! 618: ! 619: if (ent->client->weaponstate == WEAPON_ACTIVATING) ! 620: { ! 621: ent->client->weaponstate = WEAPON_READY; ! 622: ent->client->ps.gunframe = 16; ! 623: return; ! 624: } ! 625: ! 626: if (ent->client->weaponstate == WEAPON_READY) ! 627: { ! 628: if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) ) ! 629: { ! 630: ent->client->latched_buttons &= ~BUTTON_ATTACK; ! 631: if (ent->client->pers.inventory[ent->client->ammo_index]) ! 632: { ! 633: ent->client->ps.gunframe = 1; ! 634: ent->client->weaponstate = WEAPON_FIRING; ! 635: ent->client->grenade_time = 0; ! 636: } ! 637: else ! 638: { ! 639: if (level.time >= ent->pain_debounce_time) ! 640: { ! 641: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 642: ent->pain_debounce_time = level.time + 1; ! 643: } ! 644: NoAmmoWeaponChange (ent); ! 645: } ! 646: return; ! 647: } ! 648: ! 649: if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) ! 650: { ! 651: if (rand()&15) ! 652: return; ! 653: } ! 654: ! 655: if (++ent->client->ps.gunframe > 48) ! 656: ent->client->ps.gunframe = 16; ! 657: return; ! 658: } ! 659: ! 660: if (ent->client->weaponstate == WEAPON_FIRING) ! 661: { ! 662: if (ent->client->ps.gunframe == 5) ! 663: gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0); ! 664: ! 665: if (ent->client->ps.gunframe == 11) ! 666: { ! 667: if (!ent->client->grenade_time) ! 668: { ! 669: ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2; ! 670: ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav"); ! 671: } ! 672: ! 673: // they waited too long, detonate it in their hand ! 674: if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) ! 675: { ! 676: ent->client->weapon_sound = 0; ! 677: weapon_grenade_fire (ent, true); ! 678: ent->client->grenade_blew_up = true; ! 679: } ! 680: ! 681: if (ent->client->buttons & BUTTON_ATTACK) ! 682: return; ! 683: ! 684: if (ent->client->grenade_blew_up) ! 685: { ! 686: if (level.time >= ent->client->grenade_time) ! 687: { ! 688: ent->client->ps.gunframe = 15; ! 689: ent->client->grenade_blew_up = false; ! 690: } ! 691: else ! 692: { ! 693: return; ! 694: } ! 695: } ! 696: } ! 697: ! 698: if (ent->client->ps.gunframe == 12) ! 699: { ! 700: ent->client->weapon_sound = 0; ! 701: weapon_grenade_fire (ent, false); ! 702: } ! 703: ! 704: if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time)) ! 705: return; ! 706: ! 707: ent->client->ps.gunframe++; ! 708: ! 709: if (ent->client->ps.gunframe == 16) ! 710: { ! 711: ent->client->grenade_time = 0; ! 712: ent->client->weaponstate = WEAPON_READY; ! 713: } ! 714: } ! 715: } ! 716: ! 717: /* ! 718: ====================================================================== ! 719: ! 720: GRENADE LAUNCHER ! 721: ! 722: ====================================================================== ! 723: */ ! 724: ! 725: void weapon_grenadelauncher_fire (edict_t *ent) ! 726: { ! 727: vec3_t offset; ! 728: vec3_t forward, right; ! 729: vec3_t start; ! 730: int damage = 120; ! 731: float radius; ! 732: ! 733: radius = damage+40; ! 734: if (is_quad) ! 735: damage *= 4; ! 736: ! 737: VectorSet(offset, 8, 8, ent->viewheight-8); ! 738: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 739: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 740: ! 741: VectorScale (forward, -2, ent->client->kick_origin); ! 742: ent->client->kick_angles[0] = -1; ! 743: ! 744: fire_grenade (ent, start, forward, damage, 600, 2.5, radius); ! 745: ! 746: gi.WriteByte (svc_muzzleflash); ! 747: gi.WriteShort (ent-g_edicts); ! 748: gi.WriteByte (MZ_GRENADE | is_silenced); ! 749: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 750: ! 751: ent->client->ps.gunframe++; ! 752: ! 753: PlayerNoise(ent, start, PNOISE_WEAPON); ! 754: ! 755: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 756: ent->client->pers.inventory[ent->client->ammo_index]--; ! 757: } ! 758: ! 759: void Weapon_GrenadeLauncher (edict_t *ent) ! 760: { ! 761: static int pause_frames[] = {34, 51, 59, 0}; ! 762: static int fire_frames[] = {6, 0}; ! 763: ! 764: Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire); ! 765: } ! 766: ! 767: /* ! 768: ====================================================================== ! 769: ! 770: ROCKET ! 771: ! 772: ====================================================================== ! 773: */ ! 774: ! 775: void Weapon_RocketLauncher_Fire (edict_t *ent) ! 776: { ! 777: vec3_t offset, start; ! 778: vec3_t forward, right; ! 779: int damage; ! 780: float damage_radius; ! 781: int radius_damage; ! 782: ! 783: damage = 100 + (int)(random() * 20.0); ! 784: radius_damage = 120; ! 785: damage_radius = 120; ! 786: if (is_quad) ! 787: { ! 788: damage *= 4; ! 789: radius_damage *= 4; ! 790: } ! 791: ! 792: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 793: ! 794: VectorScale (forward, -2, ent->client->kick_origin); ! 795: ent->client->kick_angles[0] = -1; ! 796: ! 797: VectorSet(offset, 8, 8, ent->viewheight-8); ! 798: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 799: fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage); ! 800: ! 801: // send muzzle flash ! 802: gi.WriteByte (svc_muzzleflash); ! 803: gi.WriteShort (ent-g_edicts); ! 804: gi.WriteByte (MZ_ROCKET | is_silenced); ! 805: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 806: ! 807: ent->client->ps.gunframe++; ! 808: ! 809: PlayerNoise(ent, start, PNOISE_WEAPON); ! 810: ! 811: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 812: ent->client->pers.inventory[ent->client->ammo_index]--; ! 813: } ! 814: ! 815: void Weapon_RocketLauncher (edict_t *ent) ! 816: { ! 817: static int pause_frames[] = {25, 33, 42, 50, 0}; ! 818: static int fire_frames[] = {5, 0}; ! 819: ! 820: Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire); ! 821: } ! 822: ! 823: ! 824: /* ! 825: ====================================================================== ! 826: ! 827: BLASTER / HYPERBLASTER ! 828: ! 829: ====================================================================== ! 830: */ ! 831: ! 832: void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect) ! 833: { ! 834: vec3_t forward, right; ! 835: vec3_t start; ! 836: vec3_t offset; ! 837: ! 838: if (is_quad) ! 839: damage *= 4; ! 840: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 841: VectorSet(offset, 24, 8, ent->viewheight-8); ! 842: VectorAdd (offset, g_offset, offset); ! 843: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 844: ! 845: VectorScale (forward, -2, ent->client->kick_origin); ! 846: ent->client->kick_angles[0] = -1; ! 847: ! 848: fire_blaster (ent, start, forward, damage, 1000, effect, hyper); ! 849: ! 850: // send muzzle flash ! 851: gi.WriteByte (svc_muzzleflash); ! 852: gi.WriteShort (ent-g_edicts); ! 853: if (hyper) ! 854: gi.WriteByte (MZ_HYPERBLASTER | is_silenced); ! 855: else ! 856: gi.WriteByte (MZ_BLASTER | is_silenced); ! 857: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 858: ! 859: PlayerNoise(ent, start, PNOISE_WEAPON); ! 860: } ! 861: ! 862: ! 863: void Weapon_Blaster_Fire (edict_t *ent) ! 864: { ! 865: int damage; ! 866: ! 867: if (deathmatch->value) ! 868: damage = 15; ! 869: else ! 870: damage = 10; ! 871: Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER); ! 872: ent->client->ps.gunframe++; ! 873: } ! 874: ! 875: void Weapon_Blaster (edict_t *ent) ! 876: { ! 877: static int pause_frames[] = {19, 32, 0}; ! 878: static int fire_frames[] = {5, 0}; ! 879: ! 880: Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire); ! 881: } ! 882: ! 883: ! 884: void Weapon_HyperBlaster_Fire (edict_t *ent) ! 885: { ! 886: float rotation; ! 887: vec3_t offset; ! 888: int effect; ! 889: int damage; ! 890: ! 891: ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav"); ! 892: ! 893: if (!(ent->client->buttons & BUTTON_ATTACK)) ! 894: { ! 895: ent->client->ps.gunframe++; ! 896: } ! 897: else ! 898: { ! 899: if (! ent->client->pers.inventory[ent->client->ammo_index] ) ! 900: { ! 901: if (level.time >= ent->pain_debounce_time) ! 902: { ! 903: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 904: ent->pain_debounce_time = level.time + 1; ! 905: } ! 906: NoAmmoWeaponChange (ent); ! 907: } ! 908: else ! 909: { ! 910: rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6; ! 911: offset[0] = -4 * sin(rotation); ! 912: offset[1] = 0; ! 913: offset[2] = 4 * cos(rotation); ! 914: ! 915: if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9)) ! 916: effect = EF_HYPERBLASTER; ! 917: else ! 918: effect = 0; ! 919: if (deathmatch->value) ! 920: damage = 15; ! 921: else ! 922: damage = 20; ! 923: Blaster_Fire (ent, offset, damage, true, effect); ! 924: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 925: ent->client->pers.inventory[ent->client->ammo_index]--; ! 926: ! 927: ent->client->anim_priority = ANIM_ATTACK; ! 928: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 929: { ! 930: ent->s.frame = FRAME_crattak1 - 1; ! 931: ent->client->anim_end = FRAME_crattak9; ! 932: } ! 933: else ! 934: { ! 935: ent->s.frame = FRAME_attack1 - 1; ! 936: ent->client->anim_end = FRAME_attack8; ! 937: } ! 938: } ! 939: ! 940: ent->client->ps.gunframe++; ! 941: if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index]) ! 942: ent->client->ps.gunframe = 6; ! 943: } ! 944: ! 945: if (ent->client->ps.gunframe == 12) ! 946: { ! 947: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0); ! 948: ent->client->weapon_sound = 0; ! 949: } ! 950: ! 951: } ! 952: ! 953: void Weapon_HyperBlaster (edict_t *ent) ! 954: { ! 955: static int pause_frames[] = {0}; ! 956: static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0}; ! 957: ! 958: Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire); ! 959: } ! 960: ! 961: /* ! 962: ====================================================================== ! 963: ! 964: MACHINEGUN / CHAINGUN ! 965: ! 966: ====================================================================== ! 967: */ ! 968: ! 969: void Machinegun_Fire (edict_t *ent) ! 970: { ! 971: int i; ! 972: vec3_t start; ! 973: vec3_t forward, right; ! 974: vec3_t angles; ! 975: int damage = 8; ! 976: int kick = 2; ! 977: vec3_t offset; ! 978: ! 979: if (!(ent->client->buttons & BUTTON_ATTACK)) ! 980: { ! 981: ent->client->machinegun_shots = 0; ! 982: ent->client->ps.gunframe++; ! 983: return; ! 984: } ! 985: ! 986: if (ent->client->ps.gunframe == 5) ! 987: ent->client->ps.gunframe = 4; ! 988: else ! 989: ent->client->ps.gunframe = 5; ! 990: ! 991: if (ent->client->pers.inventory[ent->client->ammo_index] < 1) ! 992: { ! 993: ent->client->ps.gunframe = 6; ! 994: if (level.time >= ent->pain_debounce_time) ! 995: { ! 996: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 997: ent->pain_debounce_time = level.time + 1; ! 998: } ! 999: NoAmmoWeaponChange (ent); ! 1000: return; ! 1001: } ! 1002: ! 1003: if (is_quad) ! 1004: { ! 1005: damage *= 4; ! 1006: kick *= 4; ! 1007: } ! 1008: ! 1009: for (i=1 ; i<3 ; i++) ! 1010: { ! 1011: ent->client->kick_origin[i] = crandom() * 0.35; ! 1012: ent->client->kick_angles[i] = crandom() * 0.7; ! 1013: } ! 1014: ent->client->kick_origin[0] = crandom() * 0.35; ! 1015: ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5; ! 1016: ! 1017: // raise the gun as it is firing ! 1018: if (!deathmatch->value) ! 1019: { ! 1020: ent->client->machinegun_shots++; ! 1021: if (ent->client->machinegun_shots > 9) ! 1022: ent->client->machinegun_shots = 9; ! 1023: } ! 1024: ! 1025: // get start / end positions ! 1026: VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles); ! 1027: AngleVectors (angles, forward, right, NULL); ! 1028: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1029: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1030: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN); ! 1031: ! 1032: gi.WriteByte (svc_muzzleflash); ! 1033: gi.WriteShort (ent-g_edicts); ! 1034: gi.WriteByte (MZ_MACHINEGUN | is_silenced); ! 1035: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1036: ! 1037: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1038: ! 1039: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1040: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1041: ! 1042: ent->client->anim_priority = ANIM_ATTACK; ! 1043: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 1044: { ! 1045: ent->s.frame = FRAME_crattak1 - (int) (random()+0.25); ! 1046: ent->client->anim_end = FRAME_crattak9; ! 1047: } ! 1048: else ! 1049: { ! 1050: ent->s.frame = FRAME_attack1 - (int) (random()+0.25); ! 1051: ent->client->anim_end = FRAME_attack8; ! 1052: } ! 1053: } ! 1054: ! 1055: void Weapon_Machinegun (edict_t *ent) ! 1056: { ! 1057: static int pause_frames[] = {23, 45, 0}; ! 1058: static int fire_frames[] = {4, 5, 0}; ! 1059: ! 1060: Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire); ! 1061: } ! 1062: ! 1063: void Chaingun_Fire (edict_t *ent) ! 1064: { ! 1065: int i; ! 1066: int shots; ! 1067: vec3_t start; ! 1068: vec3_t forward, right, up; ! 1069: float r, u; ! 1070: vec3_t offset; ! 1071: int damage; ! 1072: int kick = 2; ! 1073: ! 1074: if (deathmatch->value) ! 1075: damage = 6; ! 1076: else ! 1077: damage = 8; ! 1078: ! 1079: if (ent->client->ps.gunframe == 5) ! 1080: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0); ! 1081: ! 1082: if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) ! 1083: { ! 1084: ent->client->ps.gunframe = 32; ! 1085: ent->client->weapon_sound = 0; ! 1086: return; ! 1087: } ! 1088: else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK) ! 1089: && ent->client->pers.inventory[ent->client->ammo_index]) ! 1090: { ! 1091: ent->client->ps.gunframe = 15; ! 1092: } ! 1093: else ! 1094: { ! 1095: ent->client->ps.gunframe++; ! 1096: } ! 1097: ! 1098: if (ent->client->ps.gunframe == 22) ! 1099: { ! 1100: ent->client->weapon_sound = 0; ! 1101: gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0); ! 1102: } ! 1103: else ! 1104: { ! 1105: ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav"); ! 1106: } ! 1107: ! 1108: ent->client->anim_priority = ANIM_ATTACK; ! 1109: if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) ! 1110: { ! 1111: ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1); ! 1112: ent->client->anim_end = FRAME_crattak9; ! 1113: } ! 1114: else ! 1115: { ! 1116: ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1); ! 1117: ent->client->anim_end = FRAME_attack8; ! 1118: } ! 1119: ! 1120: if (ent->client->ps.gunframe <= 9) ! 1121: shots = 1; ! 1122: else if (ent->client->ps.gunframe <= 14) ! 1123: { ! 1124: if (ent->client->buttons & BUTTON_ATTACK) ! 1125: shots = 2; ! 1126: else ! 1127: shots = 1; ! 1128: } ! 1129: else ! 1130: shots = 3; ! 1131: ! 1132: if (ent->client->pers.inventory[ent->client->ammo_index] < shots) ! 1133: shots = ent->client->pers.inventory[ent->client->ammo_index]; ! 1134: ! 1135: if (!shots) ! 1136: { ! 1137: if (level.time >= ent->pain_debounce_time) ! 1138: { ! 1139: gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0); ! 1140: ent->pain_debounce_time = level.time + 1; ! 1141: } ! 1142: NoAmmoWeaponChange (ent); ! 1143: return; ! 1144: } ! 1145: ! 1146: if (is_quad) ! 1147: { ! 1148: damage *= 4; ! 1149: kick *= 4; ! 1150: } ! 1151: ! 1152: for (i=0 ; i<3 ; i++) ! 1153: { ! 1154: ent->client->kick_origin[i] = crandom() * 0.35; ! 1155: ent->client->kick_angles[i] = crandom() * 0.7; ! 1156: } ! 1157: ! 1158: for (i=0 ; i<shots ; i++) ! 1159: { ! 1160: // get start / end positions ! 1161: AngleVectors (ent->client->v_angle, forward, right, up); ! 1162: r = 7 + crandom()*4; ! 1163: u = crandom()*4; ! 1164: VectorSet(offset, 0, r, u + ent->viewheight-8); ! 1165: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1166: ! 1167: fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN); ! 1168: } ! 1169: ! 1170: // send muzzle flash ! 1171: gi.WriteByte (svc_muzzleflash); ! 1172: gi.WriteShort (ent-g_edicts); ! 1173: gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced); ! 1174: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1175: ! 1176: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1177: ! 1178: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1179: ent->client->pers.inventory[ent->client->ammo_index] -= shots; ! 1180: } ! 1181: ! 1182: ! 1183: void Weapon_Chaingun (edict_t *ent) ! 1184: { ! 1185: static int pause_frames[] = {38, 43, 51, 61, 0}; ! 1186: static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0}; ! 1187: ! 1188: Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire); ! 1189: } ! 1190: ! 1191: ! 1192: /* ! 1193: ====================================================================== ! 1194: ! 1195: SHOTGUN / SUPERSHOTGUN ! 1196: ! 1197: ====================================================================== ! 1198: */ ! 1199: ! 1200: void weapon_shotgun_fire (edict_t *ent) ! 1201: { ! 1202: vec3_t start; ! 1203: vec3_t forward, right; ! 1204: vec3_t offset; ! 1205: int damage = 4; ! 1206: int kick = 8; ! 1207: ! 1208: if (ent->client->ps.gunframe == 9) ! 1209: { ! 1210: ent->client->ps.gunframe++; ! 1211: return; ! 1212: } ! 1213: ! 1214: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1215: ! 1216: VectorScale (forward, -2, ent->client->kick_origin); ! 1217: ent->client->kick_angles[0] = -2; ! 1218: ! 1219: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1220: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1221: ! 1222: if (is_quad) ! 1223: { ! 1224: damage *= 4; ! 1225: kick *= 4; ! 1226: } ! 1227: ! 1228: if (deathmatch->value) ! 1229: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN); ! 1230: else ! 1231: fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN); ! 1232: ! 1233: // send muzzle flash ! 1234: gi.WriteByte (svc_muzzleflash); ! 1235: gi.WriteShort (ent-g_edicts); ! 1236: gi.WriteByte (MZ_SHOTGUN | is_silenced); ! 1237: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1238: ! 1239: ent->client->ps.gunframe++; ! 1240: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1241: ! 1242: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1243: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1244: } ! 1245: ! 1246: void Weapon_Shotgun (edict_t *ent) ! 1247: { ! 1248: static int pause_frames[] = {22, 28, 34, 0}; ! 1249: static int fire_frames[] = {8, 9, 0}; ! 1250: ! 1251: Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire); ! 1252: } ! 1253: ! 1254: ! 1255: void weapon_supershotgun_fire (edict_t *ent) ! 1256: { ! 1257: vec3_t start; ! 1258: vec3_t forward, right; ! 1259: vec3_t offset; ! 1260: vec3_t v; ! 1261: int damage = 6; ! 1262: int kick = 12; ! 1263: ! 1264: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1265: ! 1266: VectorScale (forward, -2, ent->client->kick_origin); ! 1267: ent->client->kick_angles[0] = -2; ! 1268: ! 1269: VectorSet(offset, 0, 8, ent->viewheight-8); ! 1270: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1271: ! 1272: if (is_quad) ! 1273: { ! 1274: damage *= 4; ! 1275: kick *= 4; ! 1276: } ! 1277: ! 1278: v[PITCH] = ent->client->v_angle[PITCH]; ! 1279: v[YAW] = ent->client->v_angle[YAW] - 5; ! 1280: v[ROLL] = ent->client->v_angle[ROLL]; ! 1281: AngleVectors (v, forward, NULL, NULL); ! 1282: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); ! 1283: v[YAW] = ent->client->v_angle[YAW] + 5; ! 1284: AngleVectors (v, forward, NULL, NULL); ! 1285: fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN); ! 1286: ! 1287: // send muzzle flash ! 1288: gi.WriteByte (svc_muzzleflash); ! 1289: gi.WriteShort (ent-g_edicts); ! 1290: gi.WriteByte (MZ_SSHOTGUN | is_silenced); ! 1291: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1292: ! 1293: ent->client->ps.gunframe++; ! 1294: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1295: ! 1296: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1297: ent->client->pers.inventory[ent->client->ammo_index] -= 2; ! 1298: } ! 1299: ! 1300: void Weapon_SuperShotgun (edict_t *ent) ! 1301: { ! 1302: static int pause_frames[] = {29, 42, 57, 0}; ! 1303: static int fire_frames[] = {7, 0}; ! 1304: ! 1305: Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire); ! 1306: } ! 1307: ! 1308: ! 1309: ! 1310: /* ! 1311: ====================================================================== ! 1312: ! 1313: RAILGUN ! 1314: ! 1315: ====================================================================== ! 1316: */ ! 1317: ! 1318: void weapon_railgun_fire (edict_t *ent) ! 1319: { ! 1320: vec3_t start; ! 1321: vec3_t forward, right; ! 1322: vec3_t offset; ! 1323: int damage; ! 1324: int kick; ! 1325: ! 1326: if (deathmatch->value) ! 1327: { // normal damage is too extreme in dm ! 1328: damage = 100; ! 1329: kick = 200; ! 1330: } ! 1331: else ! 1332: { ! 1333: damage = 150; ! 1334: kick = 250; ! 1335: } ! 1336: ! 1337: if (is_quad) ! 1338: { ! 1339: damage *= 4; ! 1340: kick *= 4; ! 1341: } ! 1342: ! 1343: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1344: ! 1345: VectorScale (forward, -3, ent->client->kick_origin); ! 1346: ent->client->kick_angles[0] = -3; ! 1347: ! 1348: VectorSet(offset, 0, 7, ent->viewheight-8); ! 1349: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1350: fire_rail (ent, start, forward, damage, kick); ! 1351: ! 1352: // send muzzle flash ! 1353: gi.WriteByte (svc_muzzleflash); ! 1354: gi.WriteShort (ent-g_edicts); ! 1355: gi.WriteByte (MZ_RAILGUN | is_silenced); ! 1356: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1357: ! 1358: ent->client->ps.gunframe++; ! 1359: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1360: ! 1361: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1362: ent->client->pers.inventory[ent->client->ammo_index]--; ! 1363: } ! 1364: ! 1365: ! 1366: void Weapon_Railgun (edict_t *ent) ! 1367: { ! 1368: static int pause_frames[] = {56, 0}; ! 1369: static int fire_frames[] = {4, 0}; ! 1370: ! 1371: Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire); ! 1372: } ! 1373: ! 1374: ! 1375: /* ! 1376: ====================================================================== ! 1377: ! 1378: BFG10K ! 1379: ! 1380: ====================================================================== ! 1381: */ ! 1382: ! 1383: void weapon_bfg_fire (edict_t *ent) ! 1384: { ! 1385: vec3_t offset, start; ! 1386: vec3_t forward, right; ! 1387: int damage; ! 1388: float damage_radius = 1000; ! 1389: ! 1390: if (deathmatch->value) ! 1391: damage = 200; ! 1392: else ! 1393: damage = 500; ! 1394: ! 1395: if (ent->client->ps.gunframe == 9) ! 1396: { ! 1397: // send muzzle flash ! 1398: gi.WriteByte (svc_muzzleflash); ! 1399: gi.WriteShort (ent-g_edicts); ! 1400: gi.WriteByte (MZ_BFG | is_silenced); ! 1401: gi.multicast (ent->s.origin, MULTICAST_PVS); ! 1402: ! 1403: ent->client->ps.gunframe++; ! 1404: ! 1405: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1406: return; ! 1407: } ! 1408: ! 1409: // cells can go down during windup (from power armor hits), so ! 1410: // check again and abort firing if we don't have enough now ! 1411: if (ent->client->pers.inventory[ent->client->ammo_index] < 50) ! 1412: { ! 1413: ent->client->ps.gunframe++; ! 1414: return; ! 1415: } ! 1416: ! 1417: if (is_quad) ! 1418: damage *= 4; ! 1419: ! 1420: AngleVectors (ent->client->v_angle, forward, right, NULL); ! 1421: ! 1422: VectorScale (forward, -2, ent->client->kick_origin); ! 1423: ! 1424: // make a big pitch kick with an inverse fall ! 1425: ent->client->v_dmg_pitch = -40; ! 1426: ent->client->v_dmg_roll = crandom()*8; ! 1427: ent->client->v_dmg_time = level.time + DAMAGE_TIME; ! 1428: ! 1429: VectorSet(offset, 8, 8, ent->viewheight-8); ! 1430: P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start); ! 1431: fire_bfg (ent, start, forward, damage, 400, damage_radius); ! 1432: ! 1433: ent->client->ps.gunframe++; ! 1434: ! 1435: PlayerNoise(ent, start, PNOISE_WEAPON); ! 1436: ! 1437: if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) ) ! 1438: ent->client->pers.inventory[ent->client->ammo_index] -= 50; ! 1439: } ! 1440: ! 1441: void Weapon_BFG (edict_t *ent) ! 1442: { ! 1443: static int pause_frames[] = {39, 45, 50, 55, 0}; ! 1444: static int fire_frames[] = {9, 17, 0}; ! 1445: ! 1446: Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire); ! 1447: } ! 1448: ! 1449: ! 1450: //======================================================================
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.