p_pspr.cpp (19687B)
1 /* 2 =========================================================================== 3 4 Doom 3 BFG Edition GPL Source Code 5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 6 7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code"). 8 9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>. 21 22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below. 23 24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA. 25 26 =========================================================================== 27 */ 28 29 #include "Precompiled.h" 30 #include "globaldata.h" 31 32 #include "doomdef.h" 33 #include "d_event.h" 34 35 36 #include "m_random.h" 37 #include "p_local.h" 38 #include "s_sound.h" 39 40 // State. 41 #include "doomstat.h" 42 43 // Data. 44 #include "sounds.h" 45 46 #include "p_pspr.h" 47 #include "d3xp/Game_local.h" 48 49 extern bool globalNetworking; 50 51 52 53 static const float PISTOL_MAGNITUDE_HIGH = 0.5f; 54 static const int PISTOL_DURATION_HIGH = 250; 55 static const float PISTOL_MAGNITUDE_LOW = 1.0f; 56 static const int PISTOL_DURATION_LOW = 150; 57 58 static const float SHOTGUN_MAGNITUDE_HIGH = 0.5f; 59 static const int SHOTGUN_DURATION_HIGH = 250; 60 static const float SHOTGUN_MAGNITUDE_LOW = 1.0f; 61 static const int SHOTGUN_DURATION_LOW = 350; 62 63 static const float CHAINGUN_MAGNITUDE_HIGH = 0.5f; 64 static const int CHAINGUN_DURATION_HIGH = 250; 65 static const float CHAINGUN_MAGNITUDE_LOW = 1.0f; 66 static const int CHAINGUN_DURATION_LOW = 150; 67 68 static const float PLASMAGUN_MAGNITUDE_HIGH = 0.5f; 69 static const int PLASMAGUN_DURATION_HIGH = 250; 70 static const float PLASMAGUN_MAGNITUDE_LOW = 1.0f; 71 static const int PLASMAGUN_DURATION_LOW = 150; 72 73 static const float SUPERSHOTGUN_MAGNITUDE_HIGH = 1.0f; 74 static const int SUPERSHOTGUN_DURATION_HIGH = 250; 75 static const float SUPERSHOTGUN_MAGNITUDE_LOW = 1.0f; 76 static const int SUPERSHOTGUN_DURATION_LOW = 350; 77 78 static const float ROCKET_MAGNITUDE_HIGH = 1.5f; 79 static const int ROCKET_DURATION_HIGH = 250; 80 static const float ROCKET_MAGNITUDE_LOW = 1.0f; 81 static const int ROCKET_DURATION_LOW = 350; 82 83 static const float BFG_MAGNITUDE_HIGH = 1.5f; 84 static const int BFG_DURATION_HIGH = 250; 85 static const float BFG_MAGNITUDE_LOW = 1.0f; 86 static const int BFG_DURATION_LOW = 400; 87 88 89 static const float SAW_IDL_MAGNITUDE_HIGH = 0.0f; 90 static const int SAW_IDL_DURATION_HIGH = 0; 91 static const float SAW_IDL_MAGNITUDE_LOW = 0.4f; 92 static const int SAW_IDL_DURATION_LOW = 150; 93 94 static const float SAW_ATK_MAGNITUDE_HIGH = 1.0f; 95 static const int SAW_ATK_DURATION_HIGH = 250; 96 static const float SAW_ATK_MAGNITUDE_LOW = 0.0f; 97 static const int SAW_ATK_DURATION_LOW = 0; 98 99 // plasma cells for a bfg attack 100 101 102 // 103 // P_SetPsprite 104 // 105 void 106 P_SetPsprite 107 ( player_t* player, 108 int position, 109 statenum_t stnum ) 110 { 111 pspdef_t* psp; 112 const state_t* state; 113 114 psp = &player->psprites[position]; 115 116 do 117 { 118 if (!stnum) 119 { 120 // object removed itself 121 psp->state = NULL; 122 break; 123 } 124 125 state = &::g->states[stnum]; 126 psp->state = state; 127 psp->tics = state->tics; // could be 0 128 129 if (state->misc1) 130 { 131 // coordinate set 132 psp->sx = state->misc1 << FRACBITS; 133 psp->sy = state->misc2 << FRACBITS; 134 } 135 136 // Call action routine. 137 // Modified handling. 138 if (state->action) 139 { 140 state->action(player, psp); 141 if (!psp->state) 142 break; 143 } 144 145 stnum = psp->state->nextstate; 146 147 } while (!psp->tics); 148 // an initial state of 0 could cycle through 149 } 150 151 152 153 // 154 // P_CalcSwing 155 // 156 157 void P_CalcSwing (player_t* player) 158 { 159 fixed_t swing; 160 int angle; 161 162 // OPTIMIZE: tablify this. 163 // A LUT would allow for different modes, 164 // and add flexibility. 165 166 swing = player->bob; 167 168 angle = (FINEANGLES/70*::g->leveltime)&FINEMASK; 169 ::g->swingx = FixedMul ( swing, finesine[angle]); 170 171 angle = (FINEANGLES/70*::g->leveltime+FINEANGLES/2)&FINEMASK; 172 ::g->swingy = -FixedMul ( ::g->swingx, finesine[angle]); 173 } 174 175 176 177 // 178 // P_BringUpWeapon 179 // Starts bringing the pending weapon up 180 // from the bottom of the screen. 181 // Uses player 182 // 183 void P_BringUpWeapon (player_t* player) 184 { 185 statenum_t newstate; 186 187 if (player->pendingweapon == wp_nochange) 188 player->pendingweapon = player->readyweapon; 189 190 if (player->pendingweapon == wp_chainsaw && (globalNetworking || (player == &::g->players[::g->consoleplayer])) ) 191 S_StartSound (player->mo, sfx_sawup); 192 193 newstate = (statenum_t)(weaponinfo[player->pendingweapon].upstate); 194 195 player->pendingweapon = wp_nochange; 196 player->psprites[ps_weapon].sy = WEAPONBOTTOM; 197 198 P_SetPsprite (player, ps_weapon, newstate); 199 } 200 201 // 202 // P_CheckAmmo 203 // Returns true if there is enough ammo to shoot. 204 // If not, selects the next weapon to use. 205 // 206 qboolean P_CheckAmmo (player_t* player) 207 { 208 ammotype_t ammo; 209 int count; 210 211 ammo = weaponinfo[player->readyweapon].ammo; 212 213 // Minimal amount for one shot varies. 214 if (player->readyweapon == wp_bfg) 215 count = BFGCELLS; 216 else if (player->readyweapon == wp_supershotgun) 217 count = 2; // Double barrel. 218 else 219 count = 1; // Regular. 220 221 // Some do not need ammunition anyway. 222 // Return if current ammunition sufficient. 223 if (ammo == am_noammo || player->ammo[ammo] >= count) 224 return true; 225 226 // Out of ammo, pick a weapon to change to. 227 // Preferences are set here. 228 do 229 { 230 if (player->weaponowned[wp_plasma] 231 && player->ammo[am_cell] 232 && (::g->gamemode != shareware) ) 233 { 234 player->pendingweapon = wp_plasma; 235 } 236 else if (player->weaponowned[wp_supershotgun] 237 && player->ammo[am_shell]>2 238 && (::g->gamemode == commercial) ) 239 { 240 player->pendingweapon = wp_supershotgun; 241 } 242 else if (player->weaponowned[wp_chaingun] 243 && player->ammo[am_clip]) 244 { 245 player->pendingweapon = wp_chaingun; 246 } 247 else if (player->weaponowned[wp_shotgun] 248 && player->ammo[am_shell]) 249 { 250 player->pendingweapon = wp_shotgun; 251 } 252 else if (player->ammo[am_clip]) 253 { 254 player->pendingweapon = wp_pistol; 255 } 256 else if (player->weaponowned[wp_chainsaw]) 257 { 258 player->pendingweapon = wp_chainsaw; 259 } 260 else if (player->weaponowned[wp_missile] 261 && player->ammo[am_misl]) 262 { 263 player->pendingweapon = wp_missile; 264 } 265 else if (player->weaponowned[wp_bfg] 266 && player->ammo[am_cell]>40 267 && (::g->gamemode != shareware) ) 268 { 269 player->pendingweapon = wp_bfg; 270 } 271 else 272 { 273 // If everything fails. 274 player->pendingweapon = wp_fist; 275 } 276 277 } while (player->pendingweapon == wp_nochange); 278 279 // Now set appropriate weapon overlay. 280 P_SetPsprite (player, 281 ps_weapon, 282 (statenum_t)(weaponinfo[player->readyweapon].downstate)); 283 284 return false; 285 } 286 287 288 // 289 // P_FireWeapon. 290 // 291 void P_FireWeapon (player_t* player) 292 { 293 statenum_t newstate; 294 295 if (!P_CheckAmmo (player)) 296 return; 297 298 P_SetMobjState (player->mo, S_PLAY_ATK1); 299 newstate = (statenum_t)weaponinfo[player->readyweapon].atkstate; 300 P_SetPsprite (player, ps_weapon, newstate); 301 P_NoiseAlert (player->mo, player->mo); 302 303 if (player->readyweapon == wp_chainsaw ) 304 { 305 if( ::g->plyr == player ) { 306 } 307 } 308 309 } 310 311 312 313 // 314 // P_DropWeapon 315 // Player died, so put the weapon away. 316 // 317 void P_DropWeapon (player_t* player) 318 { 319 P_SetPsprite (player, 320 ps_weapon, 321 (statenum_t)weaponinfo[player->readyweapon].downstate); 322 } 323 324 325 326 extern "C" { 327 // 328 // A_WeaponReady 329 // The player can fire the weapon 330 // or change to another weapon at this time. 331 // Follows after getting weapon up, 332 // or after previous attack/fire sequence. 333 // 334 void 335 A_WeaponReady 336 ( player_t* player, 337 pspdef_t* psp ) 338 { 339 statenum_t newstate; 340 int angle; 341 342 // get out of attack state 343 if (player->mo->state == &::g->states[S_PLAY_ATK1] 344 || player->mo->state == &::g->states[S_PLAY_ATK2] ) 345 { 346 P_SetMobjState (player->mo, S_PLAY); 347 } 348 349 if (player->readyweapon == wp_chainsaw 350 && psp->state == &::g->states[S_SAW]) 351 { 352 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 353 S_StartSound (player->mo, sfx_sawidl); 354 } 355 356 // check for change 357 // if player is dead, put the weapon away 358 if (player->pendingweapon != wp_nochange || !player->health) 359 { 360 // change weapon 361 // (pending weapon should allready be validated) 362 newstate = (statenum_t)weaponinfo[player->readyweapon].downstate; 363 P_SetPsprite (player, ps_weapon, newstate); 364 return; 365 } 366 367 // check for fire 368 // the missile launcher and bfg do not auto fire 369 if (player->cmd.buttons & BT_ATTACK) 370 { 371 if ( !player->attackdown 372 || (player->readyweapon != wp_missile 373 && player->readyweapon != wp_bfg) ) 374 { 375 player->attackdown = true; 376 P_FireWeapon (player); 377 return; 378 } 379 } 380 else 381 player->attackdown = false; 382 383 // bob the weapon based on movement speed 384 angle = (128*::g->leveltime)&FINEMASK; 385 psp->sx = FRACUNIT + FixedMul (player->bob, finecosine[angle]); 386 angle &= FINEANGLES/2-1; 387 psp->sy = WEAPONTOP + FixedMul (player->bob, finesine[angle]); 388 } 389 390 391 392 // 393 // A_ReFire 394 // The player can re-fire the weapon 395 // without lowering it entirely. 396 // 397 void A_ReFire 398 ( player_t* player, 399 pspdef_t* psp ) 400 { 401 402 // check for fire 403 // (if a weaponchange is pending, let it go through instead) 404 if ( (player->cmd.buttons & BT_ATTACK) 405 && player->pendingweapon == wp_nochange 406 && player->health) 407 { 408 player->refire++; 409 P_FireWeapon (player); 410 } 411 else 412 { 413 player->refire = 0; 414 P_CheckAmmo (player); 415 } 416 } 417 418 419 void 420 A_CheckReload 421 ( player_t* player, 422 pspdef_t* psp ) 423 { 424 P_CheckAmmo (player); 425 #if 0 426 if (player->ammo[am_shell]<2) 427 P_SetPsprite (player, ps_weapon, S_DSNR1); 428 #endif 429 } 430 431 432 433 // 434 // A_Lower 435 // Lowers current weapon, 436 // and changes weapon at bottom. 437 // 438 void 439 A_Lower 440 ( player_t* player, 441 pspdef_t* psp ) 442 { 443 psp->sy += LOWERSPEED; 444 445 // Is already down. 446 if (psp->sy < WEAPONBOTTOM ) 447 return; 448 449 // Player is dead. 450 if (player->playerstate == PST_DEAD) 451 { 452 psp->sy = WEAPONBOTTOM; 453 454 // don't bring weapon back up 455 return; 456 } 457 458 // The old weapon has been lowered off the screen, 459 // so change the weapon and start raising it 460 if (!player->health) 461 { 462 // Player is dead, so keep the weapon off screen. 463 P_SetPsprite (player, ps_weapon, S_NULL); 464 return; 465 } 466 467 player->readyweapon = player->pendingweapon; 468 469 P_BringUpWeapon (player); 470 } 471 472 473 // 474 // A_Raise 475 // 476 void 477 A_Raise 478 ( player_t* player, 479 pspdef_t* psp ) 480 { 481 statenum_t newstate; 482 483 psp->sy -= RAISESPEED; 484 485 if (psp->sy > WEAPONTOP ) 486 return; 487 488 psp->sy = WEAPONTOP; 489 490 // The weapon has been raised all the way, 491 // so change to the ready state. 492 newstate = (statenum_t)weaponinfo[player->readyweapon].readystate; 493 494 P_SetPsprite (player, ps_weapon, newstate); 495 } 496 497 498 499 // 500 // A_GunFlash 501 // 502 void 503 A_GunFlash 504 ( player_t* player, 505 pspdef_t* psp ) 506 { 507 P_SetMobjState (player->mo, S_PLAY_ATK2); 508 P_SetPsprite (player,ps_flash,(statenum_t)weaponinfo[player->readyweapon].flashstate); 509 } 510 511 512 513 // 514 // WEAPON ATTACKS 515 // 516 517 518 // 519 // A_Punch 520 // 521 void 522 A_Punch 523 ( player_t* player, 524 pspdef_t* psp ) 525 { 526 angle_t angle; 527 int damage; 528 int slope; 529 530 damage = (P_Random ()%10+1)<<1; 531 532 if (player->powers[pw_strength]) 533 damage *= 10; 534 535 angle = player->mo->angle; 536 angle += (P_Random()-P_Random())<<18; 537 slope = P_AimLineAttack (player->mo, angle, MELEERANGE); 538 P_LineAttack (player->mo, angle, MELEERANGE, slope, damage); 539 540 // turn to face target 541 if (::g->linetarget) 542 { 543 S_StartSound (player->mo, sfx_punch); 544 player->mo->angle = R_PointToAngle2 (player->mo->x, 545 player->mo->y, 546 ::g->linetarget->x, 547 ::g->linetarget->y); 548 } 549 } 550 551 552 // 553 // A_Saw 554 // 555 void 556 A_Saw 557 ( player_t* player, 558 pspdef_t* psp ) 559 { 560 angle_t angle; 561 int damage; 562 int slope; 563 564 damage = 2*(P_Random ()%10+1); 565 angle = player->mo->angle; 566 angle += (P_Random()-P_Random())<<18; 567 568 // use meleerange + 1 se the puff doesn't skip the flash 569 slope = P_AimLineAttack (player->mo, angle, MELEERANGE+1); 570 P_LineAttack (player->mo, angle, MELEERANGE+1, slope, damage); 571 572 if (!::g->linetarget) 573 { 574 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 575 S_StartSound (player->mo, sfx_sawful); 576 return; 577 } 578 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 579 S_StartSound (player->mo, sfx_sawhit); 580 581 // turn to face target 582 angle = R_PointToAngle2 (player->mo->x, player->mo->y, 583 ::g->linetarget->x, ::g->linetarget->y); 584 if (angle - player->mo->angle > ANG180) 585 { 586 if (angle - player->mo->angle < -ANG90/20) 587 player->mo->angle = angle + ANG90/21; 588 else 589 player->mo->angle -= ANG90/20; 590 } 591 else 592 { 593 if (angle - player->mo->angle > ANG90/20) 594 player->mo->angle = angle - ANG90/21; 595 else 596 player->mo->angle += ANG90/20; 597 } 598 player->mo->flags |= MF_JUSTATTACKED; 599 } 600 601 602 603 // 604 // A_FireMissile 605 // 606 void 607 A_FireMissile 608 ( player_t* player, 609 pspdef_t* psp ) 610 { 611 if( (player->cheats & CF_INFAMMO) == false ) { 612 player->ammo[weaponinfo[player->readyweapon].ammo]--; 613 } 614 P_SpawnPlayerMissile (player->mo, MT_ROCKET); 615 616 if( ::g->plyr == player ) { 617 } 618 619 } 620 621 622 // 623 // A_FireBFG 624 // 625 void 626 A_FireBFG 627 ( player_t* player, 628 pspdef_t* psp ) 629 { 630 if( (player->cheats & CF_INFAMMO) == false ) { 631 player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; 632 } 633 634 P_SpawnPlayerMissile (player->mo, MT_BFG); 635 636 if( ::g->plyr == player ) { 637 } 638 } 639 640 641 642 // 643 // A_FirePlasma 644 // 645 void 646 A_FirePlasma 647 ( player_t* player, 648 pspdef_t* psp ) 649 { 650 if( (player->cheats & CF_INFAMMO) == false ) { 651 player->ammo[weaponinfo[player->readyweapon].ammo]--; 652 } 653 654 P_SetPsprite (player, 655 ps_flash, 656 (statenum_t)(weaponinfo[player->readyweapon].flashstate+(P_Random ()&1)) ); 657 658 P_SpawnPlayerMissile (player->mo, MT_PLASMA); 659 660 if( ::g->plyr == player ) { 661 } 662 } 663 664 665 666 // 667 // P_BulletSlope 668 // Sets a slope so a near miss is at aproximately 669 // the height of the intended target 670 // 671 672 673 void P_BulletSlope (mobj_t* mo) 674 { 675 angle_t an; 676 677 // see which target is to be aimed at 678 an = mo->angle; 679 ::g->bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); 680 681 if (!::g->linetarget) 682 { 683 an += 1<<26; 684 ::g->bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); 685 if (!::g->linetarget) 686 { 687 an -= 2<<26; 688 ::g->bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT); 689 } 690 } 691 } 692 693 694 // 695 // P_GunShot 696 // 697 void 698 P_GunShot 699 ( mobj_t* mo, 700 qboolean accurate ) 701 { 702 angle_t angle; 703 int damage; 704 705 damage = 5*(P_Random ()%3+1); 706 angle = mo->angle; 707 708 if (!accurate) 709 angle += (P_Random()-P_Random())<<18; 710 711 P_LineAttack (mo, angle, MISSILERANGE, ::g->bulletslope, damage); 712 } 713 714 715 // 716 // A_FirePistol 717 // 718 void 719 A_FirePistol 720 ( player_t* player, 721 pspdef_t* psp ) 722 { 723 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 724 S_StartSound (player->mo, sfx_pistol); 725 726 P_SetMobjState (player->mo, S_PLAY_ATK2); 727 if( (player->cheats & CF_INFAMMO ) == false ) { 728 player->ammo[weaponinfo[player->readyweapon].ammo]--; 729 } 730 731 P_SetPsprite (player, 732 ps_flash, 733 (statenum_t)weaponinfo[player->readyweapon].flashstate); 734 735 P_BulletSlope (player->mo); 736 P_GunShot (player->mo, !player->refire); 737 738 if( ::g->plyr == player ) { 739 } 740 } 741 742 743 // 744 // A_FireShotgun 745 // 746 void 747 A_FireShotgun 748 ( player_t* player, 749 pspdef_t* psp ) 750 { 751 int i; 752 753 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 754 S_StartSound (player->mo, sfx_shotgn); 755 P_SetMobjState (player->mo, S_PLAY_ATK2); 756 757 if( ( player->cheats & CF_INFAMMO ) == false ) { 758 player->ammo[weaponinfo[player->readyweapon].ammo]--; 759 } 760 761 P_SetPsprite (player, 762 ps_flash, 763 (statenum_t)weaponinfo[player->readyweapon].flashstate); 764 765 P_BulletSlope (player->mo); 766 767 for (i=0 ; i<7 ; i++) 768 P_GunShot (player->mo, false); 769 770 if( ::g->plyr == player ) { 771 } 772 } 773 774 775 776 // 777 // A_FireShotgun2 778 // 779 void 780 A_FireShotgun2 781 ( player_t* player, 782 pspdef_t* psp ) 783 { 784 int i; 785 angle_t angle; 786 int damage; 787 788 789 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 790 S_StartSound (player->mo, sfx_dshtgn); 791 P_SetMobjState (player->mo, S_PLAY_ATK2); 792 793 if( (player->cheats & CF_INFAMMO) == false ) { 794 player->ammo[weaponinfo[player->readyweapon].ammo]-=2; 795 } 796 797 P_SetPsprite (player, 798 ps_flash, 799 (statenum_t)weaponinfo[player->readyweapon].flashstate); 800 801 P_BulletSlope (player->mo); 802 803 for (i=0 ; i<20 ; i++) 804 { 805 damage = 5*(P_Random ()%3+1); 806 angle = player->mo->angle; 807 angle += (P_Random()-P_Random())<<19; 808 P_LineAttack (player->mo, 809 angle, 810 MISSILERANGE, 811 ::g->bulletslope + ((P_Random()-P_Random())<<5), damage); 812 } 813 814 if( ::g->plyr == player ) { 815 } 816 } 817 818 819 // 820 // A_FireCGun 821 // 822 void 823 A_FireCGun 824 ( player_t* player, 825 pspdef_t* psp ) 826 { 827 if (globalNetworking || (player == &::g->players[::g->consoleplayer])) 828 S_StartSound (player->mo, sfx_pistol); 829 830 if (!player->ammo[weaponinfo[player->readyweapon].ammo]) 831 return; 832 833 P_SetMobjState (player->mo, S_PLAY_ATK2); 834 if( (player->cheats & CF_INFAMMO) == false ) { 835 player->ammo[weaponinfo[player->readyweapon].ammo]--; 836 } 837 P_SetPsprite (player, 838 ps_flash, 839 840 (statenum_t)( 841 weaponinfo[player->readyweapon].flashstate 842 + psp->state 843 - &::g->states[S_CHAIN1] )); 844 845 P_BulletSlope (player->mo); 846 847 P_GunShot (player->mo, !player->refire); 848 849 if( ::g->plyr == player ) { 850 } 851 } 852 853 854 855 // 856 // ? 857 // 858 void A_Light0 (player_t *player, pspdef_t *psp) 859 { 860 player->extralight = 0; 861 } 862 863 void A_Light1 (player_t *player, pspdef_t *psp) 864 { 865 player->extralight = 1; 866 } 867 868 void A_Light2 (player_t *player, pspdef_t *psp) 869 { 870 player->extralight = 2; 871 } 872 873 874 // 875 // A_BFGSpray 876 // Spawn a BFG explosion on every monster in view 877 // 878 void A_BFGSpray (mobj_t* mo, void * ) 879 { 880 int i; 881 int j; 882 int damage; 883 angle_t an; 884 885 // offset angles from its attack angle 886 for (i=0 ; i<40 ; i++) 887 { 888 an = mo->angle - ANG90/2 + ANG90/40*i; 889 890 // mo->target is the originator (player) 891 // of the missile 892 P_AimLineAttack (mo->target, an, 16*64*FRACUNIT); 893 894 if (!::g->linetarget) 895 continue; 896 897 P_SpawnMobj (::g->linetarget->x, 898 ::g->linetarget->y, 899 ::g->linetarget->z + (::g->linetarget->height>>2), 900 MT_EXTRABFG); 901 902 damage = 0; 903 for (j=0;j<15;j++) 904 damage += (P_Random()&7) + 1; 905 906 P_DamageMobj (::g->linetarget, mo->target,mo->target, damage); 907 } 908 } 909 910 911 // 912 // A_BFGsound 913 // 914 void 915 A_BFGsound 916 ( player_t* player, 917 pspdef_t* psp ) 918 { 919 S_StartSound (player->mo, sfx_bfg); 920 } 921 922 }; // extern "C" 923 924 925 // 926 // P_SetupPsprites 927 // Called at start of level for each player. 928 // 929 void P_SetupPsprites (player_t* player) 930 { 931 int i; 932 933 // remove all psprites 934 for (i=0 ; i<NUMPSPRITES ; i++) 935 player->psprites[i].state = NULL; 936 937 // spawn the gun 938 player->pendingweapon = player->readyweapon; 939 P_BringUpWeapon (player); 940 } 941 942 943 944 945 // 946 // P_MovePsprites 947 // Called every tic by player thinking routine. 948 // 949 void P_MovePsprites (player_t* player) 950 { 951 int i; 952 pspdef_t* psp; 953 const state_t* state; 954 955 psp = &player->psprites[0]; 956 for (i=0 ; i<NUMPSPRITES ; i++, psp++) 957 { 958 // a null state means not active 959 if ( (state = psp->state) ) 960 { 961 // drop tic count and possibly change state 962 963 // a -1 tic count never changes 964 if (psp->tics != -1) 965 { 966 psp->tics--; 967 if (!psp->tics) 968 P_SetPsprite (player, i, psp->state->nextstate); 969 } 970 } 971 } 972 973 player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx; 974 player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy; 975 } 976