P_PSPR.C 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870
  1. // P_pspr.c
  2. #include "DoomDef.h"
  3. #include "P_local.h"
  4. #include "soundst.h"
  5. // Macros
  6. #define LOWERSPEED FRACUNIT*6
  7. #define RAISESPEED FRACUNIT*6
  8. #define WEAPONBOTTOM 128*FRACUNIT
  9. #define WEAPONTOP 32*FRACUNIT
  10. #define FLAME_THROWER_TICS 10*35
  11. #define MAGIC_JUNK 1234
  12. #define MAX_MACE_SPOTS 8
  13. static int MaceSpotCount;
  14. static struct
  15. {
  16. fixed_t x;
  17. fixed_t y;
  18. } MaceSpots[MAX_MACE_SPOTS];
  19. fixed_t bulletslope;
  20. static int WeaponAmmoUsePL1[NUMWEAPONS] = {
  21. 0, // staff
  22. USE_GWND_AMMO_1, // gold wand
  23. USE_CBOW_AMMO_1, // crossbow
  24. USE_BLSR_AMMO_1, // blaster
  25. USE_SKRD_AMMO_1, // skull rod
  26. USE_PHRD_AMMO_1, // phoenix rod
  27. USE_MACE_AMMO_1, // mace
  28. 0, // gauntlets
  29. 0 // beak
  30. };
  31. static int WeaponAmmoUsePL2[NUMWEAPONS] = {
  32. 0, // staff
  33. USE_GWND_AMMO_2, // gold wand
  34. USE_CBOW_AMMO_2, // crossbow
  35. USE_BLSR_AMMO_2, // blaster
  36. USE_SKRD_AMMO_2, // skull rod
  37. USE_PHRD_AMMO_2, // phoenix rod
  38. USE_MACE_AMMO_2, // mace
  39. 0, // gauntlets
  40. 0 // beak
  41. };
  42. weaponinfo_t wpnlev1info[NUMWEAPONS] =
  43. {
  44. { // Staff
  45. am_noammo, // ammo
  46. S_STAFFUP, // upstate
  47. S_STAFFDOWN, // downstate
  48. S_STAFFREADY, // readystate
  49. S_STAFFATK1_1, // atkstate
  50. S_STAFFATK1_1, // holdatkstate
  51. S_NULL // flashstate
  52. },
  53. { // Gold wand
  54. am_goldwand, // ammo
  55. S_GOLDWANDUP, // upstate
  56. S_GOLDWANDDOWN, // downstate
  57. S_GOLDWANDREADY, // readystate
  58. S_GOLDWANDATK1_1, // atkstate
  59. S_GOLDWANDATK1_1, // holdatkstate
  60. S_NULL // flashstate
  61. },
  62. { // Crossbow
  63. am_crossbow, // ammo
  64. S_CRBOWUP, // upstate
  65. S_CRBOWDOWN, // downstate
  66. S_CRBOW1, // readystate
  67. S_CRBOWATK1_1, // atkstate
  68. S_CRBOWATK1_1, // holdatkstate
  69. S_NULL // flashstate
  70. },
  71. { // Blaster
  72. am_blaster, // ammo
  73. S_BLASTERUP, // upstate
  74. S_BLASTERDOWN, // downstate
  75. S_BLASTERREADY, // readystate
  76. S_BLASTERATK1_1, // atkstate
  77. S_BLASTERATK1_3, // holdatkstate
  78. S_NULL // flashstate
  79. },
  80. { // Skull rod
  81. am_skullrod, // ammo
  82. S_HORNRODUP, // upstate
  83. S_HORNRODDOWN, // downstate
  84. S_HORNRODREADY, // readystae
  85. S_HORNRODATK1_1, // atkstate
  86. S_HORNRODATK1_1, // holdatkstate
  87. S_NULL // flashstate
  88. },
  89. { // Phoenix rod
  90. am_phoenixrod, // ammo
  91. S_PHOENIXUP, // upstate
  92. S_PHOENIXDOWN, // downstate
  93. S_PHOENIXREADY, // readystate
  94. S_PHOENIXATK1_1, // atkstate
  95. S_PHOENIXATK1_1, // holdatkstate
  96. S_NULL // flashstate
  97. },
  98. { // Mace
  99. am_mace, // ammo
  100. S_MACEUP, // upstate
  101. S_MACEDOWN, // downstate
  102. S_MACEREADY, // readystate
  103. S_MACEATK1_1, // atkstate
  104. S_MACEATK1_2, // holdatkstate
  105. S_NULL // flashstate
  106. },
  107. { // Gauntlets
  108. am_noammo, // ammo
  109. S_GAUNTLETUP, // upstate
  110. S_GAUNTLETDOWN, // downstate
  111. S_GAUNTLETREADY, // readystate
  112. S_GAUNTLETATK1_1, // atkstate
  113. S_GAUNTLETATK1_3, // holdatkstate
  114. S_NULL // flashstate
  115. },
  116. { // Beak
  117. am_noammo, // ammo
  118. S_BEAKUP, // upstate
  119. S_BEAKDOWN, // downstate
  120. S_BEAKREADY, // readystate
  121. S_BEAKATK1_1, // atkstate
  122. S_BEAKATK1_1, // holdatkstate
  123. S_NULL // flashstate
  124. }
  125. };
  126. weaponinfo_t wpnlev2info[NUMWEAPONS] =
  127. {
  128. { // Staff
  129. am_noammo, // ammo
  130. S_STAFFUP2, // upstate
  131. S_STAFFDOWN2, // downstate
  132. S_STAFFREADY2_1, // readystate
  133. S_STAFFATK2_1, // atkstate
  134. S_STAFFATK2_1, // holdatkstate
  135. S_NULL // flashstate
  136. },
  137. { // Gold wand
  138. am_goldwand, // ammo
  139. S_GOLDWANDUP, // upstate
  140. S_GOLDWANDDOWN, // downstate
  141. S_GOLDWANDREADY, // readystate
  142. S_GOLDWANDATK2_1, // atkstate
  143. S_GOLDWANDATK2_1, // holdatkstate
  144. S_NULL // flashstate
  145. },
  146. { // Crossbow
  147. am_crossbow, // ammo
  148. S_CRBOWUP, // upstate
  149. S_CRBOWDOWN, // downstate
  150. S_CRBOW1, // readystate
  151. S_CRBOWATK2_1, // atkstate
  152. S_CRBOWATK2_1, // holdatkstate
  153. S_NULL // flashstate
  154. },
  155. { // Blaster
  156. am_blaster, // ammo
  157. S_BLASTERUP, // upstate
  158. S_BLASTERDOWN, // downstate
  159. S_BLASTERREADY, // readystate
  160. S_BLASTERATK2_1, // atkstate
  161. S_BLASTERATK2_3, // holdatkstate
  162. S_NULL // flashstate
  163. },
  164. { // Skull rod
  165. am_skullrod, // ammo
  166. S_HORNRODUP, // upstate
  167. S_HORNRODDOWN, // downstate
  168. S_HORNRODREADY, // readystae
  169. S_HORNRODATK2_1, // atkstate
  170. S_HORNRODATK2_1, // holdatkstate
  171. S_NULL // flashstate
  172. },
  173. { // Phoenix rod
  174. am_phoenixrod, // ammo
  175. S_PHOENIXUP, // upstate
  176. S_PHOENIXDOWN, // downstate
  177. S_PHOENIXREADY, // readystate
  178. S_PHOENIXATK2_1, // atkstate
  179. S_PHOENIXATK2_2, // holdatkstate
  180. S_NULL // flashstate
  181. },
  182. { // Mace
  183. am_mace, // ammo
  184. S_MACEUP, // upstate
  185. S_MACEDOWN, // downstate
  186. S_MACEREADY, // readystate
  187. S_MACEATK2_1, // atkstate
  188. S_MACEATK2_1, // holdatkstate
  189. S_NULL // flashstate
  190. },
  191. { // Gauntlets
  192. am_noammo, // ammo
  193. S_GAUNTLETUP2, // upstate
  194. S_GAUNTLETDOWN2, // downstate
  195. S_GAUNTLETREADY2_1, // readystate
  196. S_GAUNTLETATK2_1, // atkstate
  197. S_GAUNTLETATK2_3, // holdatkstate
  198. S_NULL // flashstate
  199. },
  200. { // Beak
  201. am_noammo, // ammo
  202. S_BEAKUP, // upstate
  203. S_BEAKDOWN, // downstate
  204. S_BEAKREADY, // readystate
  205. S_BEAKATK2_1, // atkstate
  206. S_BEAKATK2_1, // holdatkstate
  207. S_NULL // flashstate
  208. }
  209. };
  210. //---------------------------------------------------------------------------
  211. //
  212. // PROC P_OpenWeapons
  213. //
  214. // Called at level load before things are loaded.
  215. //
  216. //---------------------------------------------------------------------------
  217. void P_OpenWeapons(void)
  218. {
  219. MaceSpotCount = 0;
  220. }
  221. //---------------------------------------------------------------------------
  222. //
  223. // PROC P_AddMaceSpot
  224. //
  225. //---------------------------------------------------------------------------
  226. void P_AddMaceSpot(mapthing_t *mthing)
  227. {
  228. if(MaceSpotCount == MAX_MACE_SPOTS)
  229. {
  230. I_Error("Too many mace spots.");
  231. }
  232. MaceSpots[MaceSpotCount].x = mthing->x<<FRACBITS;
  233. MaceSpots[MaceSpotCount].y = mthing->y<<FRACBITS;
  234. MaceSpotCount++;
  235. }
  236. //---------------------------------------------------------------------------
  237. //
  238. // PROC P_RepositionMace
  239. //
  240. // Chooses the next spot to place the mace.
  241. //
  242. //---------------------------------------------------------------------------
  243. void P_RepositionMace(mobj_t *mo)
  244. {
  245. int spot;
  246. subsector_t *ss;
  247. P_UnsetThingPosition(mo);
  248. spot = P_Random()%MaceSpotCount;
  249. mo->x = MaceSpots[spot].x;
  250. mo->y = MaceSpots[spot].y;
  251. ss = R_PointInSubsector(mo->x, mo->y);
  252. mo->z = mo->floorz = ss->sector->floorheight;
  253. mo->ceilingz = ss->sector->ceilingheight;
  254. P_SetThingPosition(mo);
  255. }
  256. //---------------------------------------------------------------------------
  257. //
  258. // PROC P_CloseWeapons
  259. //
  260. // Called at level load after things are loaded.
  261. //
  262. //---------------------------------------------------------------------------
  263. void P_CloseWeapons(void)
  264. {
  265. int spot;
  266. if(!MaceSpotCount)
  267. { // No maces placed
  268. return;
  269. }
  270. if(!deathmatch && P_Random() < 64)
  271. { // Sometimes doesn't show up if not in deathmatch
  272. return;
  273. }
  274. spot = P_Random()%MaceSpotCount;
  275. P_SpawnMobj(MaceSpots[spot].x, MaceSpots[spot].y, ONFLOORZ, MT_WMACE);
  276. }
  277. //---------------------------------------------------------------------------
  278. //
  279. // PROC P_SetPsprite
  280. //
  281. //---------------------------------------------------------------------------
  282. void P_SetPsprite(player_t *player, int position, statenum_t stnum)
  283. {
  284. pspdef_t *psp;
  285. state_t *state;
  286. psp = &player->psprites[position];
  287. do
  288. {
  289. if(!stnum)
  290. { // Object removed itself.
  291. psp->state = NULL;
  292. break;
  293. }
  294. state = &states[stnum];
  295. psp->state = state;
  296. psp->tics = state->tics; // could be 0
  297. if(state->misc1)
  298. { // Set coordinates.
  299. psp->sx = state->misc1<<FRACBITS;
  300. psp->sy = state->misc2<<FRACBITS;
  301. }
  302. if(state->action)
  303. { // Call action routine.
  304. state->action(player, psp);
  305. if(!psp->state)
  306. {
  307. break;
  308. }
  309. }
  310. stnum = psp->state->nextstate;
  311. } while(!psp->tics); // An initial state of 0 could cycle through.
  312. }
  313. /*
  314. =================
  315. =
  316. = P_CalcSwing
  317. =
  318. =================
  319. */
  320. /*
  321. fixed_t swingx, swingy;
  322. void P_CalcSwing (player_t *player)
  323. {
  324. fixed_t swing;
  325. int angle;
  326. // OPTIMIZE: tablify this
  327. swing = player->bob;
  328. angle = (FINEANGLES/70*leveltime)&FINEMASK;
  329. swingx = FixedMul ( swing, finesine[angle]);
  330. angle = (FINEANGLES/70*leveltime+FINEANGLES/2)&FINEMASK;
  331. swingy = -FixedMul ( swingx, finesine[angle]);
  332. }
  333. */
  334. //---------------------------------------------------------------------------
  335. //
  336. // PROC P_ActivateBeak
  337. //
  338. //---------------------------------------------------------------------------
  339. void P_ActivateBeak(player_t *player)
  340. {
  341. player->pendingweapon = wp_nochange;
  342. player->readyweapon = wp_beak;
  343. player->psprites[ps_weapon].sy = WEAPONTOP;
  344. P_SetPsprite(player, ps_weapon, S_BEAKREADY);
  345. }
  346. //---------------------------------------------------------------------------
  347. //
  348. // PROC P_PostChickenWeapon
  349. //
  350. //---------------------------------------------------------------------------
  351. void P_PostChickenWeapon(player_t *player, weapontype_t weapon)
  352. {
  353. if(weapon == wp_beak)
  354. { // Should never happen
  355. weapon = wp_staff;
  356. }
  357. player->pendingweapon = wp_nochange;
  358. player->readyweapon = weapon;
  359. player->psprites[ps_weapon].sy = WEAPONBOTTOM;
  360. P_SetPsprite(player, ps_weapon, wpnlev1info[weapon].upstate);
  361. }
  362. //---------------------------------------------------------------------------
  363. //
  364. // PROC P_BringUpWeapon
  365. //
  366. // Starts bringing the pending weapon up from the bottom of the screen.
  367. //
  368. //---------------------------------------------------------------------------
  369. void P_BringUpWeapon(player_t *player)
  370. {
  371. statenum_t new;
  372. if(player->pendingweapon == wp_nochange)
  373. {
  374. player->pendingweapon = player->readyweapon;
  375. }
  376. if(player->pendingweapon == wp_gauntlets)
  377. {
  378. S_StartSound(player->mo, sfx_gntact);
  379. }
  380. if(player->powers[pw_weaponlevel2])
  381. {
  382. new = wpnlev2info[player->pendingweapon].upstate;
  383. }
  384. else
  385. {
  386. new = wpnlev1info[player->pendingweapon].upstate;
  387. }
  388. player->pendingweapon = wp_nochange;
  389. player->psprites[ps_weapon].sy = WEAPONBOTTOM;
  390. P_SetPsprite(player, ps_weapon, new);
  391. }
  392. //---------------------------------------------------------------------------
  393. //
  394. // FUNC P_CheckAmmo
  395. //
  396. // Returns true if there is enough ammo to shoot. If not, selects the
  397. // next weapon to use.
  398. //
  399. //---------------------------------------------------------------------------
  400. boolean P_CheckAmmo(player_t *player)
  401. {
  402. ammotype_t ammo;
  403. int *ammoUse;
  404. int count;
  405. ammo = wpnlev1info[player->readyweapon].ammo;
  406. if(player->powers[pw_weaponlevel2] && !deathmatch)
  407. {
  408. ammoUse = WeaponAmmoUsePL2;
  409. }
  410. else
  411. {
  412. ammoUse = WeaponAmmoUsePL1;
  413. }
  414. count = ammoUse[player->readyweapon];
  415. if(ammo == am_noammo || player->ammo[ammo] >= count)
  416. {
  417. return(true);
  418. }
  419. // out of ammo, pick a weapon to change to
  420. do
  421. {
  422. if(player->weaponowned[wp_skullrod]
  423. && player->ammo[am_skullrod] > ammoUse[wp_skullrod])
  424. {
  425. player->pendingweapon = wp_skullrod;
  426. }
  427. else if(player->weaponowned[wp_blaster]
  428. && player->ammo[am_blaster] > ammoUse[wp_blaster])
  429. {
  430. player->pendingweapon = wp_blaster;
  431. }
  432. else if(player->weaponowned[wp_crossbow]
  433. && player->ammo[am_crossbow] > ammoUse[wp_crossbow])
  434. {
  435. player->pendingweapon = wp_crossbow;
  436. }
  437. else if(player->weaponowned[wp_mace]
  438. && player->ammo[am_mace] > ammoUse[wp_mace])
  439. {
  440. player->pendingweapon = wp_mace;
  441. }
  442. else if(player->ammo[am_goldwand] > ammoUse[wp_goldwand])
  443. {
  444. player->pendingweapon = wp_goldwand;
  445. }
  446. else if(player->weaponowned[wp_gauntlets])
  447. {
  448. player->pendingweapon = wp_gauntlets;
  449. }
  450. else if(player->weaponowned[wp_phoenixrod]
  451. && player->ammo[am_phoenixrod] > ammoUse[wp_phoenixrod])
  452. {
  453. player->pendingweapon = wp_phoenixrod;
  454. }
  455. else
  456. {
  457. player->pendingweapon = wp_staff;
  458. }
  459. } while(player->pendingweapon == wp_nochange);
  460. if(player->powers[pw_weaponlevel2])
  461. {
  462. P_SetPsprite(player, ps_weapon,
  463. wpnlev2info[player->readyweapon].downstate);
  464. }
  465. else
  466. {
  467. P_SetPsprite(player, ps_weapon,
  468. wpnlev1info[player->readyweapon].downstate);
  469. }
  470. return(false);
  471. }
  472. //---------------------------------------------------------------------------
  473. //
  474. // PROC P_FireWeapon
  475. //
  476. //---------------------------------------------------------------------------
  477. void P_FireWeapon(player_t *player)
  478. {
  479. weaponinfo_t *wpinfo;
  480. statenum_t attackState;
  481. if(!P_CheckAmmo(player))
  482. {
  483. return;
  484. }
  485. P_SetMobjState(player->mo, S_PLAY_ATK2);
  486. wpinfo = player->powers[pw_weaponlevel2] ? &wpnlev2info[0]
  487. : &wpnlev1info[0];
  488. attackState = player->refire ? wpinfo[player->readyweapon].holdatkstate
  489. : wpinfo[player->readyweapon].atkstate;
  490. P_SetPsprite(player, ps_weapon, attackState);
  491. P_NoiseAlert(player->mo, player->mo);
  492. if(player->readyweapon == wp_gauntlets && !player->refire)
  493. { // Play the sound for the initial gauntlet attack
  494. S_StartSound(player->mo, sfx_gntuse);
  495. }
  496. }
  497. //---------------------------------------------------------------------------
  498. //
  499. // PROC P_DropWeapon
  500. //
  501. // The player died, so put the weapon away.
  502. //
  503. //---------------------------------------------------------------------------
  504. void P_DropWeapon(player_t *player)
  505. {
  506. if(player->powers[pw_weaponlevel2])
  507. {
  508. P_SetPsprite(player, ps_weapon,
  509. wpnlev2info[player->readyweapon].downstate);
  510. }
  511. else
  512. {
  513. P_SetPsprite(player, ps_weapon,
  514. wpnlev1info[player->readyweapon].downstate);
  515. }
  516. }
  517. //---------------------------------------------------------------------------
  518. //
  519. // PROC A_WeaponReady
  520. //
  521. // The player can fire the weapon or change to another weapon at this time.
  522. //
  523. //---------------------------------------------------------------------------
  524. void A_WeaponReady(player_t *player, pspdef_t *psp)
  525. {
  526. int angle;
  527. if(player->chickenTics)
  528. { // Change to the chicken beak
  529. P_ActivateBeak(player);
  530. return;
  531. }
  532. // Change player from attack state
  533. if(player->mo->state == &states[S_PLAY_ATK1]
  534. || player->mo->state == &states[S_PLAY_ATK2])
  535. {
  536. P_SetMobjState(player->mo, S_PLAY);
  537. }
  538. // Check for staff PL2 active sound
  539. if((player->readyweapon == wp_staff)
  540. && (psp->state == &states[S_STAFFREADY2_1])
  541. && P_Random() < 128)
  542. {
  543. S_StartSound(player->mo, sfx_stfcrk);
  544. }
  545. // Put the weapon away if the player has a pending weapon or has
  546. // died.
  547. if(player->pendingweapon != wp_nochange || !player->health)
  548. {
  549. if(player->powers[pw_weaponlevel2])
  550. {
  551. P_SetPsprite(player, ps_weapon,
  552. wpnlev2info[player->readyweapon].downstate);
  553. }
  554. else
  555. {
  556. P_SetPsprite(player, ps_weapon,
  557. wpnlev1info[player->readyweapon].downstate);
  558. }
  559. return;
  560. }
  561. // Check for fire. The phoenix rod does not auto fire.
  562. if(player->cmd.buttons&BT_ATTACK)
  563. {
  564. if(!player->attackdown || (player->readyweapon != wp_phoenixrod))
  565. {
  566. player->attackdown = true;
  567. P_FireWeapon(player);
  568. return;
  569. }
  570. }
  571. else
  572. {
  573. player->attackdown = false;
  574. }
  575. // Bob the weapon based on movement speed.
  576. angle = (128*leveltime)&FINEMASK;
  577. psp->sx = FRACUNIT+FixedMul(player->bob, finecosine[angle]);
  578. angle &= FINEANGLES/2-1;
  579. psp->sy = WEAPONTOP+FixedMul(player->bob, finesine[angle]);
  580. }
  581. //---------------------------------------------------------------------------
  582. //
  583. // PROC P_UpdateBeak
  584. //
  585. //---------------------------------------------------------------------------
  586. void P_UpdateBeak(player_t *player, pspdef_t *psp)
  587. {
  588. psp->sy = WEAPONTOP+(player->chickenPeck<<(FRACBITS-1));
  589. }
  590. //---------------------------------------------------------------------------
  591. //
  592. // PROC A_BeakReady
  593. //
  594. //---------------------------------------------------------------------------
  595. void A_BeakReady(player_t *player, pspdef_t *psp)
  596. {
  597. if(player->cmd.buttons&BT_ATTACK)
  598. { // Chicken beak attack
  599. player->attackdown = true;
  600. P_SetMobjState(player->mo, S_CHICPLAY_ATK1);
  601. if(player->powers[pw_weaponlevel2])
  602. {
  603. P_SetPsprite(player, ps_weapon, S_BEAKATK2_1);
  604. }
  605. else
  606. {
  607. P_SetPsprite(player, ps_weapon, S_BEAKATK1_1);
  608. }
  609. P_NoiseAlert(player->mo, player->mo);
  610. }
  611. else
  612. {
  613. if(player->mo->state == &states[S_CHICPLAY_ATK1])
  614. { // Take out of attack state
  615. P_SetMobjState(player->mo, S_CHICPLAY);
  616. }
  617. player->attackdown = false;
  618. }
  619. }
  620. //---------------------------------------------------------------------------
  621. //
  622. // PROC A_ReFire
  623. //
  624. // The player can re fire the weapon without lowering it entirely.
  625. //
  626. //---------------------------------------------------------------------------
  627. void A_ReFire(player_t *player, pspdef_t *psp)
  628. {
  629. if((player->cmd.buttons&BT_ATTACK)
  630. && player->pendingweapon == wp_nochange && player->health)
  631. {
  632. player->refire++;
  633. P_FireWeapon(player);
  634. }
  635. else
  636. {
  637. player->refire = 0;
  638. P_CheckAmmo(player);
  639. }
  640. }
  641. //---------------------------------------------------------------------------
  642. //
  643. // PROC A_Lower
  644. //
  645. //---------------------------------------------------------------------------
  646. void A_Lower(player_t *player, pspdef_t *psp)
  647. {
  648. if(player->chickenTics)
  649. {
  650. psp->sy = WEAPONBOTTOM;
  651. }
  652. else
  653. {
  654. psp->sy += LOWERSPEED;
  655. }
  656. if(psp->sy < WEAPONBOTTOM)
  657. { // Not lowered all the way yet
  658. return;
  659. }
  660. if(player->playerstate == PST_DEAD)
  661. { // Player is dead, so don't bring up a pending weapon
  662. psp->sy = WEAPONBOTTOM;
  663. return;
  664. }
  665. if(!player->health)
  666. { // Player is dead, so keep the weapon off screen
  667. P_SetPsprite(player, ps_weapon, S_NULL);
  668. return;
  669. }
  670. player->readyweapon = player->pendingweapon;
  671. P_BringUpWeapon(player);
  672. }
  673. //---------------------------------------------------------------------------
  674. //
  675. // PROC A_BeakRaise
  676. //
  677. //---------------------------------------------------------------------------
  678. void A_BeakRaise(player_t *player, pspdef_t *psp)
  679. {
  680. psp->sy = WEAPONTOP;
  681. P_SetPsprite(player, ps_weapon,
  682. wpnlev1info[player->readyweapon].readystate);
  683. }
  684. //---------------------------------------------------------------------------
  685. //
  686. // PROC A_Raise
  687. //
  688. //---------------------------------------------------------------------------
  689. void A_Raise(player_t *player, pspdef_t *psp)
  690. {
  691. psp->sy -= RAISESPEED;
  692. if(psp->sy > WEAPONTOP)
  693. { // Not raised all the way yet
  694. return;
  695. }
  696. psp->sy = WEAPONTOP;
  697. if(player->powers[pw_weaponlevel2])
  698. {
  699. P_SetPsprite(player, ps_weapon,
  700. wpnlev2info[player->readyweapon].readystate);
  701. }
  702. else
  703. {
  704. P_SetPsprite(player, ps_weapon,
  705. wpnlev1info[player->readyweapon].readystate);
  706. }
  707. }
  708. /*
  709. ===============
  710. =
  711. = P_BulletSlope
  712. =
  713. = Sets a slope so a near miss is at aproximately the height of the
  714. = intended target
  715. =
  716. ===============
  717. */
  718. void P_BulletSlope (mobj_t *mo)
  719. {
  720. angle_t an;
  721. //
  722. // see which target is to be aimed at
  723. //
  724. an = mo->angle;
  725. bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  726. if (!linetarget)
  727. {
  728. an += 1<<26;
  729. bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  730. if (!linetarget)
  731. {
  732. an -= 2<<26;
  733. bulletslope = P_AimLineAttack (mo, an, 16*64*FRACUNIT);
  734. }
  735. if (!linetarget)
  736. {
  737. an += 2<<26;
  738. bulletslope = (mo->player->lookdir<<FRACBITS)/173;
  739. }
  740. }
  741. }
  742. //****************************************************************************
  743. //
  744. // WEAPON ATTACKS
  745. //
  746. //****************************************************************************
  747. //----------------------------------------------------------------------------
  748. //
  749. // PROC A_BeakAttackPL1
  750. //
  751. //----------------------------------------------------------------------------
  752. void A_BeakAttackPL1(player_t *player, pspdef_t *psp)
  753. {
  754. angle_t angle;
  755. int damage;
  756. int slope;
  757. damage = 1+(P_Random()&3);
  758. angle = player->mo->angle;
  759. slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  760. PuffType = MT_BEAKPUFF;
  761. P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  762. if(linetarget)
  763. {
  764. player->mo->angle = R_PointToAngle2(player->mo->x,
  765. player->mo->y, linetarget->x, linetarget->y);
  766. }
  767. S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
  768. player->chickenPeck = 12;
  769. psp->tics -= P_Random()&7;
  770. }
  771. //----------------------------------------------------------------------------
  772. //
  773. // PROC A_BeakAttackPL2
  774. //
  775. //----------------------------------------------------------------------------
  776. void A_BeakAttackPL2(player_t *player, pspdef_t *psp)
  777. {
  778. angle_t angle;
  779. int damage;
  780. int slope;
  781. damage = HITDICE(4);
  782. angle = player->mo->angle;
  783. slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  784. PuffType = MT_BEAKPUFF;
  785. P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  786. if(linetarget)
  787. {
  788. player->mo->angle = R_PointToAngle2(player->mo->x,
  789. player->mo->y, linetarget->x, linetarget->y);
  790. }
  791. S_StartSound(player->mo, sfx_chicpk1+(P_Random()%3));
  792. player->chickenPeck = 12;
  793. psp->tics -= P_Random()&3;
  794. }
  795. //----------------------------------------------------------------------------
  796. //
  797. // PROC A_StaffAttackPL1
  798. //
  799. //----------------------------------------------------------------------------
  800. void A_StaffAttackPL1(player_t *player, pspdef_t *psp)
  801. {
  802. angle_t angle;
  803. int damage;
  804. int slope;
  805. damage = 5+(P_Random()&15);
  806. angle = player->mo->angle;
  807. angle += (P_Random()-P_Random())<<18;
  808. slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  809. PuffType = MT_STAFFPUFF;
  810. P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  811. if(linetarget)
  812. {
  813. //S_StartSound(player->mo, sfx_stfhit);
  814. // turn to face target
  815. player->mo->angle = R_PointToAngle2(player->mo->x,
  816. player->mo->y, linetarget->x, linetarget->y);
  817. }
  818. }
  819. //----------------------------------------------------------------------------
  820. //
  821. // PROC A_StaffAttackPL2
  822. //
  823. //----------------------------------------------------------------------------
  824. void A_StaffAttackPL2(player_t *player, pspdef_t *psp)
  825. {
  826. angle_t angle;
  827. int damage;
  828. int slope;
  829. // P_inter.c:P_DamageMobj() handles target momentums
  830. damage = 18+(P_Random()&63);
  831. angle = player->mo->angle;
  832. angle += (P_Random()-P_Random())<<18;
  833. slope = P_AimLineAttack(player->mo, angle, MELEERANGE);
  834. PuffType = MT_STAFFPUFF2;
  835. P_LineAttack(player->mo, angle, MELEERANGE, slope, damage);
  836. if(linetarget)
  837. {
  838. //S_StartSound(player->mo, sfx_stfpow);
  839. // turn to face target
  840. player->mo->angle = R_PointToAngle2(player->mo->x,
  841. player->mo->y, linetarget->x, linetarget->y);
  842. }
  843. }
  844. //----------------------------------------------------------------------------
  845. //
  846. // PROC A_FireBlasterPL1
  847. //
  848. //----------------------------------------------------------------------------
  849. void A_FireBlasterPL1(player_t *player, pspdef_t *psp)
  850. {
  851. mobj_t *mo;
  852. angle_t angle;
  853. int damage;
  854. mo = player->mo;
  855. S_StartSound(mo, sfx_gldhit);
  856. player->ammo[am_blaster] -= USE_BLSR_AMMO_1;
  857. P_BulletSlope(mo);
  858. damage = HITDICE(4);
  859. angle = mo->angle;
  860. if(player->refire)
  861. {
  862. angle += (P_Random()-P_Random())<<18;
  863. }
  864. PuffType = MT_BLASTERPUFF1;
  865. P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  866. S_StartSound(player->mo, sfx_blssht);
  867. }
  868. //----------------------------------------------------------------------------
  869. //
  870. // PROC A_FireBlasterPL2
  871. //
  872. //----------------------------------------------------------------------------
  873. void A_FireBlasterPL2(player_t *player, pspdef_t *psp)
  874. {
  875. mobj_t *mo;
  876. player->ammo[am_blaster] -=
  877. deathmatch ? USE_BLSR_AMMO_1 : USE_BLSR_AMMO_2;
  878. mo = P_SpawnPlayerMissile(player->mo, MT_BLASTERFX1);
  879. if(mo)
  880. {
  881. mo->thinker.function = P_BlasterMobjThinker;
  882. }
  883. S_StartSound(player->mo, sfx_blssht);
  884. }
  885. //----------------------------------------------------------------------------
  886. //
  887. // PROC A_FireGoldWandPL1
  888. //
  889. //----------------------------------------------------------------------------
  890. void A_FireGoldWandPL1(player_t *player, pspdef_t *psp)
  891. {
  892. mobj_t *mo;
  893. angle_t angle;
  894. int damage;
  895. mo = player->mo;
  896. player->ammo[am_goldwand] -= USE_GWND_AMMO_1;
  897. P_BulletSlope(mo);
  898. damage = 7+(P_Random()&7);
  899. angle = mo->angle;
  900. if(player->refire)
  901. {
  902. angle += (P_Random()-P_Random())<<18;
  903. }
  904. PuffType = MT_GOLDWANDPUFF1;
  905. P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  906. S_StartSound(player->mo, sfx_gldhit);
  907. }
  908. //----------------------------------------------------------------------------
  909. //
  910. // PROC A_FireGoldWandPL2
  911. //
  912. //----------------------------------------------------------------------------
  913. void A_FireGoldWandPL2(player_t *player, pspdef_t *psp)
  914. {
  915. int i;
  916. mobj_t *mo;
  917. angle_t angle;
  918. int damage;
  919. fixed_t momz;
  920. mo = player->mo;
  921. player->ammo[am_goldwand] -=
  922. deathmatch ? USE_GWND_AMMO_1 : USE_GWND_AMMO_2;
  923. PuffType = MT_GOLDWANDPUFF2;
  924. P_BulletSlope(mo);
  925. momz = FixedMul(mobjinfo[MT_GOLDWANDFX2].speed, bulletslope);
  926. P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle-(ANG45/8), momz);
  927. P_SpawnMissileAngle(mo, MT_GOLDWANDFX2, mo->angle+(ANG45/8), momz);
  928. angle = mo->angle-(ANG45/8);
  929. for(i = 0; i < 5; i++)
  930. {
  931. damage = 1+(P_Random()&7);
  932. P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
  933. angle += ((ANG45/8)*2)/4;
  934. }
  935. S_StartSound(player->mo, sfx_gldhit);
  936. }
  937. //----------------------------------------------------------------------------
  938. //
  939. // PROC A_FireMacePL1B
  940. //
  941. //----------------------------------------------------------------------------
  942. void A_FireMacePL1B(player_t *player, pspdef_t *psp)
  943. {
  944. mobj_t *pmo;
  945. mobj_t *ball;
  946. angle_t angle;
  947. if(player->ammo[am_mace] < USE_MACE_AMMO_1)
  948. {
  949. return;
  950. }
  951. player->ammo[am_mace] -= USE_MACE_AMMO_1;
  952. pmo = player->mo;
  953. ball = P_SpawnMobj(pmo->x, pmo->y, pmo->z+28*FRACUNIT
  954. - FOOTCLIPSIZE*(pmo->flags2&MF2_FEETARECLIPPED != 0), MT_MACEFX2);
  955. ball->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
  956. angle = pmo->angle;
  957. ball->target = pmo;
  958. ball->angle = angle;
  959. ball->z += (player->lookdir)<<(FRACBITS-4);
  960. angle >>= ANGLETOFINESHIFT;
  961. ball->momx = (pmo->momx>>1)
  962. +FixedMul(ball->info->speed, finecosine[angle]);
  963. ball->momy = (pmo->momy>>1)
  964. +FixedMul(ball->info->speed, finesine[angle]);
  965. S_StartSound(ball, sfx_lobsht);
  966. P_CheckMissileSpawn(ball);
  967. }
  968. //----------------------------------------------------------------------------
  969. //
  970. // PROC A_FireMacePL1
  971. //
  972. //----------------------------------------------------------------------------
  973. void A_FireMacePL1(player_t *player, pspdef_t *psp)
  974. {
  975. mobj_t *ball;
  976. if(P_Random() < 28)
  977. {
  978. A_FireMacePL1B(player, psp);
  979. return;
  980. }
  981. if(player->ammo[am_mace] < USE_MACE_AMMO_1)
  982. {
  983. return;
  984. }
  985. player->ammo[am_mace] -= USE_MACE_AMMO_1;
  986. psp->sx = ((P_Random()&3)-2)*FRACUNIT;
  987. psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
  988. ball = P_SPMAngle(player->mo, MT_MACEFX1, player->mo->angle
  989. +(((P_Random()&7)-4)<<24));
  990. if(ball)
  991. {
  992. ball->special1 = 16; // tics till dropoff
  993. }
  994. }
  995. //----------------------------------------------------------------------------
  996. //
  997. // PROC A_MacePL1Check
  998. //
  999. //----------------------------------------------------------------------------
  1000. void A_MacePL1Check(mobj_t *ball)
  1001. {
  1002. angle_t angle;
  1003. if(ball->special1 == 0)
  1004. {
  1005. return;
  1006. }
  1007. ball->special1 -= 4;
  1008. if(ball->special1 > 0)
  1009. {
  1010. return;
  1011. }
  1012. ball->special1 = 0;
  1013. ball->flags2 |= MF2_LOGRAV;
  1014. angle = ball->angle>>ANGLETOFINESHIFT;
  1015. ball->momx = FixedMul(7*FRACUNIT, finecosine[angle]);
  1016. ball->momy = FixedMul(7*FRACUNIT, finesine[angle]);
  1017. ball->momz -= ball->momz>>1;
  1018. }
  1019. //----------------------------------------------------------------------------
  1020. //
  1021. // PROC A_MaceBallImpact
  1022. //
  1023. //----------------------------------------------------------------------------
  1024. void A_MaceBallImpact(mobj_t *ball)
  1025. {
  1026. if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1027. { // Landed in some sort of liquid
  1028. P_RemoveMobj(ball);
  1029. return;
  1030. }
  1031. if((ball->health != MAGIC_JUNK) && (ball->z <= ball->floorz)
  1032. && ball->momz)
  1033. { // Bounce
  1034. ball->health = MAGIC_JUNK;
  1035. ball->momz = (ball->momz*192)>>8;
  1036. ball->flags2 &= ~MF2_FLOORBOUNCE;
  1037. P_SetMobjState(ball, ball->info->spawnstate);
  1038. S_StartSound(ball, sfx_bounce);
  1039. }
  1040. else
  1041. { // Explode
  1042. ball->flags |= MF_NOGRAVITY;
  1043. ball->flags2 &= ~MF2_LOGRAV;
  1044. S_StartSound(ball, sfx_lobhit);
  1045. }
  1046. }
  1047. //----------------------------------------------------------------------------
  1048. //
  1049. // PROC A_MaceBallImpact2
  1050. //
  1051. //----------------------------------------------------------------------------
  1052. void A_MaceBallImpact2(mobj_t *ball)
  1053. {
  1054. mobj_t *tiny;
  1055. angle_t angle;
  1056. if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1057. { // Landed in some sort of liquid
  1058. P_RemoveMobj(ball);
  1059. return;
  1060. }
  1061. if((ball->z != ball->floorz) || (ball->momz < 2*FRACUNIT))
  1062. { // Explode
  1063. ball->momx = ball->momy = ball->momz = 0;
  1064. ball->flags |= MF_NOGRAVITY;
  1065. ball->flags2 &= ~(MF2_LOGRAV|MF2_FLOORBOUNCE);
  1066. }
  1067. else
  1068. { // Bounce
  1069. ball->momz = (ball->momz*192)>>8;
  1070. P_SetMobjState(ball, ball->info->spawnstate);
  1071. tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
  1072. angle = ball->angle+ANG90;
  1073. tiny->target = ball->target;
  1074. tiny->angle = angle;
  1075. angle >>= ANGLETOFINESHIFT;
  1076. tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
  1077. finecosine[angle]);
  1078. tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
  1079. finesine[angle]);
  1080. tiny->momz = ball->momz;
  1081. P_CheckMissileSpawn(tiny);
  1082. tiny = P_SpawnMobj(ball->x, ball->y, ball->z, MT_MACEFX3);
  1083. angle = ball->angle-ANG90;
  1084. tiny->target = ball->target;
  1085. tiny->angle = angle;
  1086. angle >>= ANGLETOFINESHIFT;
  1087. tiny->momx = (ball->momx>>1)+FixedMul(ball->momz-FRACUNIT,
  1088. finecosine[angle]);
  1089. tiny->momy = (ball->momy>>1)+FixedMul(ball->momz-FRACUNIT,
  1090. finesine[angle]);
  1091. tiny->momz = ball->momz;
  1092. P_CheckMissileSpawn(tiny);
  1093. }
  1094. }
  1095. //----------------------------------------------------------------------------
  1096. //
  1097. // PROC A_FireMacePL2
  1098. //
  1099. //----------------------------------------------------------------------------
  1100. void A_FireMacePL2(player_t *player, pspdef_t *psp)
  1101. {
  1102. mobj_t *mo;
  1103. player->ammo[am_mace] -=
  1104. deathmatch ? USE_MACE_AMMO_1 : USE_MACE_AMMO_2;
  1105. mo = P_SpawnPlayerMissile(player->mo, MT_MACEFX4);
  1106. if(mo)
  1107. {
  1108. mo->momx += player->mo->momx;
  1109. mo->momy += player->mo->momy;
  1110. mo->momz = 2*FRACUNIT+((player->lookdir)<<(FRACBITS-5));
  1111. if(linetarget)
  1112. {
  1113. mo->special1 = (int)linetarget;
  1114. }
  1115. }
  1116. S_StartSound(player->mo, sfx_lobsht);
  1117. }
  1118. //----------------------------------------------------------------------------
  1119. //
  1120. // PROC A_DeathBallImpact
  1121. //
  1122. //----------------------------------------------------------------------------
  1123. void A_DeathBallImpact(mobj_t *ball)
  1124. {
  1125. int i;
  1126. mobj_t *target;
  1127. angle_t angle;
  1128. boolean newAngle;
  1129. if((ball->z <= ball->floorz) && (P_HitFloor(ball) != FLOOR_SOLID))
  1130. { // Landed in some sort of liquid
  1131. P_RemoveMobj(ball);
  1132. return;
  1133. }
  1134. if((ball->z <= ball->floorz) && ball->momz)
  1135. { // Bounce
  1136. newAngle = false;
  1137. target = (mobj_t *)ball->special1;
  1138. if(target)
  1139. {
  1140. if(!(target->flags&MF_SHOOTABLE))
  1141. { // Target died
  1142. ball->special1 = 0;
  1143. }
  1144. else
  1145. { // Seek
  1146. angle = R_PointToAngle2(ball->x, ball->y,
  1147. target->x, target->y);
  1148. newAngle = true;
  1149. }
  1150. }
  1151. else
  1152. { // Find new target
  1153. angle = 0;
  1154. for(i = 0; i < 16; i++)
  1155. {
  1156. P_AimLineAttack(ball, angle, 10*64*FRACUNIT);
  1157. if(linetarget && ball->target != linetarget)
  1158. {
  1159. ball->special1 = (int)linetarget;
  1160. angle = R_PointToAngle2(ball->x, ball->y,
  1161. linetarget->x, linetarget->y);
  1162. newAngle = true;
  1163. break;
  1164. }
  1165. angle += ANGLE_45/2;
  1166. }
  1167. }
  1168. if(newAngle)
  1169. {
  1170. ball->angle = angle;
  1171. angle >>= ANGLETOFINESHIFT;
  1172. ball->momx = FixedMul(ball->info->speed, finecosine[angle]);
  1173. ball->momy = FixedMul(ball->info->speed, finesine[angle]);
  1174. }
  1175. P_SetMobjState(ball, ball->info->spawnstate);
  1176. S_StartSound(ball, sfx_pstop);
  1177. }
  1178. else
  1179. { // Explode
  1180. ball->flags |= MF_NOGRAVITY;
  1181. ball->flags2 &= ~MF2_LOGRAV;
  1182. S_StartSound(ball, sfx_phohit);
  1183. }
  1184. }
  1185. //----------------------------------------------------------------------------
  1186. //
  1187. // PROC A_SpawnRippers
  1188. //
  1189. //----------------------------------------------------------------------------
  1190. void A_SpawnRippers(mobj_t *actor)
  1191. {
  1192. int i;
  1193. angle_t angle;
  1194. mobj_t *ripper;
  1195. for(i = 0; i < 8; i++)
  1196. {
  1197. ripper = P_SpawnMobj(actor->x, actor->y, actor->z, MT_RIPPER);
  1198. angle = i*ANG45;
  1199. ripper->target = actor->target;
  1200. ripper->angle = angle;
  1201. angle >>= ANGLETOFINESHIFT;
  1202. ripper->momx = FixedMul(ripper->info->speed, finecosine[angle]);
  1203. ripper->momy = FixedMul(ripper->info->speed, finesine[angle]);
  1204. P_CheckMissileSpawn(ripper);
  1205. }
  1206. }
  1207. //----------------------------------------------------------------------------
  1208. //
  1209. // PROC A_FireCrossbowPL1
  1210. //
  1211. //----------------------------------------------------------------------------
  1212. void A_FireCrossbowPL1(player_t *player, pspdef_t *psp)
  1213. {
  1214. mobj_t *pmo;
  1215. pmo = player->mo;
  1216. player->ammo[am_crossbow] -= USE_CBOW_AMMO_1;
  1217. P_SpawnPlayerMissile(pmo, MT_CRBOWFX1);
  1218. P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/10));
  1219. P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/10));
  1220. }
  1221. //----------------------------------------------------------------------------
  1222. //
  1223. // PROC A_FireCrossbowPL2
  1224. //
  1225. //----------------------------------------------------------------------------
  1226. void A_FireCrossbowPL2(player_t *player, pspdef_t *psp)
  1227. {
  1228. mobj_t *pmo;
  1229. pmo = player->mo;
  1230. player->ammo[am_crossbow] -=
  1231. deathmatch ? USE_CBOW_AMMO_1 : USE_CBOW_AMMO_2;
  1232. P_SpawnPlayerMissile(pmo, MT_CRBOWFX2);
  1233. P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle-(ANG45/10));
  1234. P_SPMAngle(pmo, MT_CRBOWFX2, pmo->angle+(ANG45/10));
  1235. P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle-(ANG45/5));
  1236. P_SPMAngle(pmo, MT_CRBOWFX3, pmo->angle+(ANG45/5));
  1237. }
  1238. //----------------------------------------------------------------------------
  1239. //
  1240. // PROC A_BoltSpark
  1241. //
  1242. //----------------------------------------------------------------------------
  1243. void A_BoltSpark(mobj_t *bolt)
  1244. {
  1245. mobj_t *spark;
  1246. if(P_Random() > 50)
  1247. {
  1248. spark = P_SpawnMobj(bolt->x, bolt->y, bolt->z, MT_CRBOWFX4);
  1249. spark->x += (P_Random()-P_Random())<<10;
  1250. spark->y += (P_Random()-P_Random())<<10;
  1251. }
  1252. }
  1253. //----------------------------------------------------------------------------
  1254. //
  1255. // PROC A_FireSkullRodPL1
  1256. //
  1257. //----------------------------------------------------------------------------
  1258. void A_FireSkullRodPL1(player_t *player, pspdef_t *psp)
  1259. {
  1260. mobj_t *mo;
  1261. if(player->ammo[am_skullrod] < USE_SKRD_AMMO_1)
  1262. {
  1263. return;
  1264. }
  1265. player->ammo[am_skullrod] -= USE_SKRD_AMMO_1;
  1266. mo = P_SpawnPlayerMissile(player->mo, MT_HORNRODFX1);
  1267. // Randomize the first frame
  1268. if(mo && P_Random() > 128)
  1269. {
  1270. P_SetMobjState(mo, S_HRODFX1_2);
  1271. }
  1272. }
  1273. //----------------------------------------------------------------------------
  1274. //
  1275. // PROC A_FireSkullRodPL2
  1276. //
  1277. // The special2 field holds the player number that shot the rain missile.
  1278. // The special1 field is used for the seeking routines, then as a counter
  1279. // for the sound looping.
  1280. //
  1281. //----------------------------------------------------------------------------
  1282. void A_FireSkullRodPL2(player_t *player, pspdef_t *psp)
  1283. {
  1284. player->ammo[am_skullrod] -=
  1285. deathmatch ? USE_SKRD_AMMO_1 : USE_SKRD_AMMO_2;
  1286. P_SpawnPlayerMissile(player->mo, MT_HORNRODFX2);
  1287. // Use MissileMobj instead of the return value from
  1288. // P_SpawnPlayerMissile because we need to give info to the mobj
  1289. // even if it exploded immediately.
  1290. if(netgame)
  1291. { // Multi-player game
  1292. MissileMobj->special2 = P_GetPlayerNum(player);
  1293. }
  1294. else
  1295. { // Always use red missiles in single player games
  1296. MissileMobj->special2 = 2;
  1297. }
  1298. if(linetarget)
  1299. {
  1300. MissileMobj->special1 = (int)linetarget;
  1301. }
  1302. S_StartSound(MissileMobj, sfx_hrnpow);
  1303. }
  1304. //----------------------------------------------------------------------------
  1305. //
  1306. // PROC A_SkullRodPL2Seek
  1307. //
  1308. //----------------------------------------------------------------------------
  1309. void A_SkullRodPL2Seek(mobj_t *actor)
  1310. {
  1311. P_SeekerMissile(actor, ANGLE_1*10, ANGLE_1*30);
  1312. }
  1313. //----------------------------------------------------------------------------
  1314. //
  1315. // PROC A_AddPlayerRain
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. void A_AddPlayerRain(mobj_t *actor)
  1319. {
  1320. int playerNum;
  1321. player_t *player;
  1322. playerNum = netgame ? actor->special2 : 0;
  1323. if(!playeringame[playerNum])
  1324. { // Player left the game
  1325. return;
  1326. }
  1327. player = &players[playerNum];
  1328. if(player->health <= 0)
  1329. { // Player is dead
  1330. return;
  1331. }
  1332. if(player->rain1 && player->rain2)
  1333. { // Terminate an active rain
  1334. if(player->rain1->health < player->rain2->health)
  1335. {
  1336. if(player->rain1->health > 16)
  1337. {
  1338. player->rain1->health = 16;
  1339. }
  1340. player->rain1 = NULL;
  1341. }
  1342. else
  1343. {
  1344. if(player->rain2->health > 16)
  1345. {
  1346. player->rain2->health = 16;
  1347. }
  1348. player->rain2 = NULL;
  1349. }
  1350. }
  1351. // Add rain mobj to list
  1352. if(player->rain1)
  1353. {
  1354. player->rain2 = actor;
  1355. }
  1356. else
  1357. {
  1358. player->rain1 = actor;
  1359. }
  1360. }
  1361. //----------------------------------------------------------------------------
  1362. //
  1363. // PROC A_SkullRodStorm
  1364. //
  1365. //----------------------------------------------------------------------------
  1366. void A_SkullRodStorm(mobj_t *actor)
  1367. {
  1368. fixed_t x;
  1369. fixed_t y;
  1370. mobj_t *mo;
  1371. int playerNum;
  1372. player_t *player;
  1373. if(actor->health-- == 0)
  1374. {
  1375. P_SetMobjState(actor, S_NULL);
  1376. playerNum = netgame ? actor->special2 : 0;
  1377. if(!playeringame[playerNum])
  1378. { // Player left the game
  1379. return;
  1380. }
  1381. player = &players[playerNum];
  1382. if(player->health <= 0)
  1383. { // Player is dead
  1384. return;
  1385. }
  1386. if(player->rain1 == actor)
  1387. {
  1388. player->rain1 = NULL;
  1389. }
  1390. else if(player->rain2 == actor)
  1391. {
  1392. player->rain2 = NULL;
  1393. }
  1394. return;
  1395. }
  1396. if(P_Random() < 25)
  1397. { // Fudge rain frequency
  1398. return;
  1399. }
  1400. x = actor->x+((P_Random()&127)-64)*FRACUNIT;
  1401. y = actor->y+((P_Random()&127)-64)*FRACUNIT;
  1402. mo = P_SpawnMobj(x, y, ONCEILINGZ, MT_RAINPLR1+actor->special2);
  1403. mo->target = actor->target;
  1404. mo->momx = 1; // Force collision detection
  1405. mo->momz = -mo->info->speed;
  1406. mo->special2 = actor->special2; // Transfer player number
  1407. P_CheckMissileSpawn(mo);
  1408. if(!(actor->special1&31))
  1409. {
  1410. S_StartSound(actor, sfx_ramrain);
  1411. }
  1412. actor->special1++;
  1413. }
  1414. //----------------------------------------------------------------------------
  1415. //
  1416. // PROC A_RainImpact
  1417. //
  1418. //----------------------------------------------------------------------------
  1419. void A_RainImpact(mobj_t *actor)
  1420. {
  1421. if(actor->z > actor->floorz)
  1422. {
  1423. P_SetMobjState(actor, S_RAINAIRXPLR1_1+actor->special2);
  1424. }
  1425. else if(P_Random() < 40)
  1426. {
  1427. P_HitFloor(actor);
  1428. }
  1429. }
  1430. //----------------------------------------------------------------------------
  1431. //
  1432. // PROC A_HideInCeiling
  1433. //
  1434. //----------------------------------------------------------------------------
  1435. void A_HideInCeiling(mobj_t *actor)
  1436. {
  1437. actor->z = actor->ceilingz+4*FRACUNIT;
  1438. }
  1439. //----------------------------------------------------------------------------
  1440. //
  1441. // PROC A_FirePhoenixPL1
  1442. //
  1443. //----------------------------------------------------------------------------
  1444. void A_FirePhoenixPL1(player_t *player, pspdef_t *psp)
  1445. {
  1446. angle_t angle;
  1447. player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_1;
  1448. P_SpawnPlayerMissile(player->mo, MT_PHOENIXFX1);
  1449. //P_SpawnPlayerMissile(player->mo, MT_MNTRFX2);
  1450. angle = player->mo->angle+ANG180;
  1451. angle >>= ANGLETOFINESHIFT;
  1452. player->mo->momx += FixedMul(4*FRACUNIT, finecosine[angle]);
  1453. player->mo->momy += FixedMul(4*FRACUNIT, finesine[angle]);
  1454. }
  1455. //----------------------------------------------------------------------------
  1456. //
  1457. // PROC A_PhoenixPuff
  1458. //
  1459. //----------------------------------------------------------------------------
  1460. void A_PhoenixPuff(mobj_t *actor)
  1461. {
  1462. mobj_t *puff;
  1463. angle_t angle;
  1464. P_SeekerMissile(actor, ANGLE_1*5, ANGLE_1*10);
  1465. puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
  1466. angle = actor->angle+ANG90;
  1467. angle >>= ANGLETOFINESHIFT;
  1468. puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
  1469. puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
  1470. puff->momz = 0;
  1471. puff = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PHOENIXPUFF);
  1472. angle = actor->angle-ANG90;
  1473. angle >>= ANGLETOFINESHIFT;
  1474. puff->momx = FixedMul(FRACUNIT*1.3, finecosine[angle]);
  1475. puff->momy = FixedMul(FRACUNIT*1.3, finesine[angle]);
  1476. puff->momz = 0;
  1477. }
  1478. //----------------------------------------------------------------------------
  1479. //
  1480. // PROC A_InitPhoenixPL2
  1481. //
  1482. //----------------------------------------------------------------------------
  1483. void A_InitPhoenixPL2(player_t *player, pspdef_t *psp)
  1484. {
  1485. player->flamecount = FLAME_THROWER_TICS;
  1486. }
  1487. //----------------------------------------------------------------------------
  1488. //
  1489. // PROC A_FirePhoenixPL2
  1490. //
  1491. // Flame thrower effect.
  1492. //
  1493. //----------------------------------------------------------------------------
  1494. void A_FirePhoenixPL2(player_t *player, pspdef_t *psp)
  1495. {
  1496. mobj_t *mo;
  1497. mobj_t *pmo;
  1498. angle_t angle;
  1499. fixed_t x, y, z;
  1500. fixed_t slope;
  1501. if(--player->flamecount == 0)
  1502. { // Out of flame
  1503. P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4);
  1504. player->refire = 0;
  1505. return;
  1506. }
  1507. pmo = player->mo;
  1508. angle = pmo->angle;
  1509. x = pmo->x+((P_Random()-P_Random())<<9);
  1510. y = pmo->y+((P_Random()-P_Random())<<9);
  1511. z = pmo->z+26*FRACUNIT+((player->lookdir)<<FRACBITS)/173;
  1512. if(pmo->flags2&MF2_FEETARECLIPPED)
  1513. {
  1514. z -= FOOTCLIPSIZE;
  1515. }
  1516. slope = ((player->lookdir)<<FRACBITS)/173+(FRACUNIT/10);
  1517. mo = P_SpawnMobj(x, y, z, MT_PHOENIXFX2);
  1518. mo->target = pmo;
  1519. mo->angle = angle;
  1520. mo->momx = pmo->momx+FixedMul(mo->info->speed,
  1521. finecosine[angle>>ANGLETOFINESHIFT]);
  1522. mo->momy = pmo->momy+FixedMul(mo->info->speed,
  1523. finesine[angle>>ANGLETOFINESHIFT]);
  1524. mo->momz = FixedMul(mo->info->speed, slope);
  1525. if(!player->refire || !(leveltime%38))
  1526. {
  1527. S_StartSound(player->mo, sfx_phopow);
  1528. }
  1529. P_CheckMissileSpawn(mo);
  1530. }
  1531. //----------------------------------------------------------------------------
  1532. //
  1533. // PROC A_ShutdownPhoenixPL2
  1534. //
  1535. //----------------------------------------------------------------------------
  1536. void A_ShutdownPhoenixPL2(player_t *player, pspdef_t *psp)
  1537. {
  1538. player->ammo[am_phoenixrod] -= USE_PHRD_AMMO_2;
  1539. }
  1540. //----------------------------------------------------------------------------
  1541. //
  1542. // PROC A_FlameEnd
  1543. //
  1544. //----------------------------------------------------------------------------
  1545. void A_FlameEnd(mobj_t *actor)
  1546. {
  1547. actor->momz += 1.5*FRACUNIT;
  1548. }
  1549. //----------------------------------------------------------------------------
  1550. //
  1551. // PROC A_FloatPuff
  1552. //
  1553. //----------------------------------------------------------------------------
  1554. void A_FloatPuff(mobj_t *puff)
  1555. {
  1556. puff->momz += 1.8*FRACUNIT;
  1557. }
  1558. //---------------------------------------------------------------------------
  1559. //
  1560. // PROC A_GauntletAttack
  1561. //
  1562. //---------------------------------------------------------------------------
  1563. void A_GauntletAttack(player_t *player, pspdef_t *psp)
  1564. {
  1565. angle_t angle;
  1566. int damage;
  1567. int slope;
  1568. int randVal;
  1569. fixed_t dist;
  1570. psp->sx = ((P_Random()&3)-2)*FRACUNIT;
  1571. psp->sy = WEAPONTOP+(P_Random()&3)*FRACUNIT;
  1572. angle = player->mo->angle;
  1573. if(player->powers[pw_weaponlevel2])
  1574. {
  1575. damage = HITDICE(2);
  1576. dist = 4*MELEERANGE;
  1577. angle += (P_Random()-P_Random())<<17;
  1578. PuffType = MT_GAUNTLETPUFF2;
  1579. }
  1580. else
  1581. {
  1582. damage = HITDICE(2);
  1583. dist = MELEERANGE+1;
  1584. angle += (P_Random()-P_Random())<<18;
  1585. PuffType = MT_GAUNTLETPUFF1;
  1586. }
  1587. slope = P_AimLineAttack(player->mo, angle, dist);
  1588. P_LineAttack(player->mo, angle, dist, slope, damage);
  1589. if(!linetarget)
  1590. {
  1591. if(P_Random() > 64)
  1592. {
  1593. player->extralight = !player->extralight;
  1594. }
  1595. S_StartSound(player->mo, sfx_gntful);
  1596. return;
  1597. }
  1598. randVal = P_Random();
  1599. if(randVal < 64)
  1600. {
  1601. player->extralight = 0;
  1602. }
  1603. else if(randVal < 160)
  1604. {
  1605. player->extralight = 1;
  1606. }
  1607. else
  1608. {
  1609. player->extralight = 2;
  1610. }
  1611. if(player->powers[pw_weaponlevel2])
  1612. {
  1613. P_GiveBody(player, damage>>1);
  1614. S_StartSound(player->mo, sfx_gntpow);
  1615. }
  1616. else
  1617. {
  1618. S_StartSound(player->mo, sfx_gnthit);
  1619. }
  1620. // turn to face target
  1621. angle = R_PointToAngle2(player->mo->x, player->mo->y,
  1622. linetarget->x, linetarget->y);
  1623. if(angle-player->mo->angle > ANG180)
  1624. {
  1625. if(angle-player->mo->angle < -ANG90/20)
  1626. player->mo->angle = angle+ANG90/21;
  1627. else
  1628. player->mo->angle -= ANG90/20;
  1629. }
  1630. else
  1631. {
  1632. if(angle-player->mo->angle > ANG90/20)
  1633. player->mo->angle = angle-ANG90/21;
  1634. else
  1635. player->mo->angle += ANG90/20;
  1636. }
  1637. player->mo->flags |= MF_JUSTATTACKED;
  1638. }
  1639. void A_Light0(player_t *player, pspdef_t *psp)
  1640. {
  1641. player->extralight = 0;
  1642. }
  1643. void A_Light1(player_t *player, pspdef_t *psp)
  1644. {
  1645. player->extralight = 1;
  1646. }
  1647. void A_Light2(player_t *player, pspdef_t *psp)
  1648. {
  1649. player->extralight = 2;
  1650. }
  1651. //------------------------------------------------------------------------
  1652. //
  1653. // PROC P_SetupPsprites
  1654. //
  1655. // Called at start of level for each player
  1656. //
  1657. //------------------------------------------------------------------------
  1658. void P_SetupPsprites(player_t *player)
  1659. {
  1660. int i;
  1661. // Remove all psprites
  1662. for(i = 0; i < NUMPSPRITES; i++)
  1663. {
  1664. player->psprites[i].state = NULL;
  1665. }
  1666. // Spawn the ready weapon
  1667. player->pendingweapon = player->readyweapon;
  1668. P_BringUpWeapon(player);
  1669. }
  1670. //------------------------------------------------------------------------
  1671. //
  1672. // PROC P_MovePsprites
  1673. //
  1674. // Called every tic by player thinking routine
  1675. //
  1676. //------------------------------------------------------------------------
  1677. void P_MovePsprites(player_t *player)
  1678. {
  1679. int i;
  1680. pspdef_t *psp;
  1681. state_t *state;
  1682. psp = &player->psprites[0];
  1683. for(i = 0; i < NUMPSPRITES; i++, psp++)
  1684. {
  1685. if((state = psp->state) != 0) // a null state means not active
  1686. {
  1687. // drop tic count and possibly change state
  1688. if(psp->tics != -1) // a -1 tic count never changes
  1689. {
  1690. psp->tics--;
  1691. if(!psp->tics)
  1692. {
  1693. P_SetPsprite(player, i, psp->state->nextstate);
  1694. }
  1695. }
  1696. }
  1697. }
  1698. player->psprites[ps_flash].sx = player->psprites[ps_weapon].sx;
  1699. player->psprites[ps_flash].sy = player->psprites[ps_weapon].sy;
  1700. }