p_pspr.cpp 19 KB

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