DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

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