home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / p_pspr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  17.6 KB  |  880 lines

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