P_USER.C 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653
  1. //**************************************************************************
  2. //**
  3. //** p_user.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: p_user.c,v $
  6. //** $Revision: 1.123 $
  7. //** $Date: 96/01/05 14:21:01 $
  8. //** $Author: bgokey $
  9. //**
  10. //**************************************************************************
  11. #include "h2def.h"
  12. #include "p_local.h"
  13. #include "soundst.h"
  14. void P_PlayerNextArtifact(player_t *player);
  15. // Macros
  16. #define MAXBOB 0x100000 // 16 pixels of bob
  17. // Data
  18. boolean onground;
  19. int newtorch; // used in the torch flicker effect.
  20. int newtorchdelta;
  21. int PStateNormal[NUMCLASSES] =
  22. {
  23. S_FPLAY,
  24. S_CPLAY,
  25. S_MPLAY,
  26. S_PIGPLAY
  27. };
  28. int PStateRun[NUMCLASSES] =
  29. {
  30. S_FPLAY_RUN1,
  31. S_CPLAY_RUN1,
  32. S_MPLAY_RUN1,
  33. S_PIGPLAY_RUN1
  34. };
  35. int PStateAttack[NUMCLASSES] =
  36. {
  37. S_FPLAY_ATK1,
  38. S_CPLAY_ATK1,
  39. S_MPLAY_ATK1,
  40. S_PIGPLAY_ATK1
  41. };
  42. int PStateAttackEnd[NUMCLASSES] =
  43. {
  44. S_FPLAY_ATK2,
  45. S_CPLAY_ATK3,
  46. S_MPLAY_ATK2,
  47. S_PIGPLAY_ATK1
  48. };
  49. int ArmorMax[NUMCLASSES] = { 20, 18, 16, 1 };
  50. /*
  51. ==================
  52. =
  53. = P_Thrust
  54. =
  55. = moves the given origin along a given angle
  56. =
  57. ==================
  58. */
  59. void P_Thrust(player_t *player, angle_t angle, fixed_t move)
  60. {
  61. angle >>= ANGLETOFINESHIFT;
  62. if(player->powers[pw_flight] && !(player->mo->z <= player->mo->floorz))
  63. {
  64. player->mo->momx += FixedMul(move, finecosine[angle]);
  65. player->mo->momy += FixedMul(move, finesine[angle]);
  66. }
  67. else if(P_GetThingFloorType(player->mo) == FLOOR_ICE) // Friction_Low
  68. {
  69. player->mo->momx += FixedMul(move>>1, finecosine[angle]);
  70. player->mo->momy += FixedMul(move>>1, finesine[angle]);
  71. }
  72. else
  73. {
  74. player->mo->momx += FixedMul(move, finecosine[angle]);
  75. player->mo->momy += FixedMul(move, finesine[angle]);
  76. }
  77. }
  78. /*
  79. ==================
  80. =
  81. = P_CalcHeight
  82. =
  83. = Calculate the walking / running height adjustment
  84. =
  85. ==================
  86. */
  87. void P_CalcHeight (player_t *player)
  88. {
  89. int angle;
  90. fixed_t bob;
  91. //
  92. // regular movement bobbing (needs to be calculated for gun swing even
  93. // if not on ground)
  94. // OPTIMIZE: tablify angle
  95. player->bob = FixedMul (player->mo->momx, player->mo->momx)+
  96. FixedMul (player->mo->momy,player->mo->momy);
  97. player->bob >>= 2;
  98. if (player->bob>MAXBOB)
  99. player->bob = MAXBOB;
  100. if(player->mo->flags2&MF2_FLY && !onground)
  101. {
  102. player->bob = FRACUNIT/2;
  103. }
  104. if ((player->cheats & CF_NOMOMENTUM))
  105. {
  106. player->viewz = player->mo->z + VIEWHEIGHT;
  107. if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
  108. player->viewz = player->mo->ceilingz-4*FRACUNIT;
  109. player->viewz = player->mo->z + player->viewheight;
  110. return;
  111. }
  112. angle = (FINEANGLES/20*leveltime)&FINEMASK;
  113. bob = FixedMul ( player->bob/2, finesine[angle]);
  114. //
  115. // move viewheight
  116. //
  117. if (player->playerstate == PST_LIVE)
  118. {
  119. player->viewheight += player->deltaviewheight;
  120. if (player->viewheight > VIEWHEIGHT)
  121. {
  122. player->viewheight = VIEWHEIGHT;
  123. player->deltaviewheight = 0;
  124. }
  125. if (player->viewheight < VIEWHEIGHT/2)
  126. {
  127. player->viewheight = VIEWHEIGHT/2;
  128. if (player->deltaviewheight <= 0)
  129. player->deltaviewheight = 1;
  130. }
  131. if (player->deltaviewheight)
  132. {
  133. player->deltaviewheight += FRACUNIT/4;
  134. if (!player->deltaviewheight)
  135. player->deltaviewheight = 1;
  136. }
  137. }
  138. if(player->morphTics)
  139. {
  140. player->viewz = player->mo->z+player->viewheight-(20*FRACUNIT);
  141. }
  142. else
  143. {
  144. player->viewz = player->mo->z+player->viewheight+bob;
  145. }
  146. if(player->mo->floorclip && player->playerstate != PST_DEAD
  147. && player->mo->z <= player->mo->floorz)
  148. {
  149. player->viewz -= player->mo->floorclip;
  150. }
  151. if(player->viewz > player->mo->ceilingz-4*FRACUNIT)
  152. {
  153. player->viewz = player->mo->ceilingz-4*FRACUNIT;
  154. }
  155. if(player->viewz < player->mo->floorz+4*FRACUNIT)
  156. {
  157. player->viewz = player->mo->floorz+4*FRACUNIT;
  158. }
  159. }
  160. /*
  161. =================
  162. =
  163. = P_MovePlayer
  164. =
  165. =================
  166. */
  167. void P_MovePlayer(player_t *player)
  168. {
  169. int look;
  170. int fly;
  171. ticcmd_t *cmd;
  172. cmd = &player->cmd;
  173. player->mo->angle += (cmd->angleturn<<16);
  174. onground = (player->mo->z <= player->mo->floorz
  175. || (player->mo->flags2&MF2_ONMOBJ));
  176. if(cmd->forwardmove)
  177. {
  178. if(onground || player->mo->flags2&MF2_FLY)
  179. {
  180. P_Thrust(player, player->mo->angle, cmd->forwardmove*2048);
  181. }
  182. else
  183. {
  184. P_Thrust(player, player->mo->angle, FRACUNIT>>8);
  185. }
  186. }
  187. if(cmd->sidemove)
  188. {
  189. if(onground || player->mo->flags2&MF2_FLY)
  190. {
  191. P_Thrust(player, player->mo->angle-ANG90, cmd->sidemove*2048);
  192. }
  193. else
  194. {
  195. P_Thrust(player, player->mo->angle, FRACUNIT>>8);
  196. }
  197. }
  198. if(cmd->forwardmove || cmd->sidemove)
  199. {
  200. if(player->mo->state == &states[PStateNormal[player->class]])
  201. {
  202. P_SetMobjState(player->mo, PStateRun[player->class]);
  203. }
  204. }
  205. look = cmd->lookfly&15;
  206. if(look > 7)
  207. {
  208. look -= 16;
  209. }
  210. if(look)
  211. {
  212. if(look == TOCENTER)
  213. {
  214. player->centering = true;
  215. }
  216. else
  217. {
  218. player->lookdir += 5*look;
  219. if(player->lookdir > 90 || player->lookdir < -110)
  220. {
  221. player->lookdir -= 5*look;
  222. }
  223. }
  224. }
  225. if(player->centering)
  226. {
  227. if(player->lookdir > 0)
  228. {
  229. player->lookdir -= 8;
  230. }
  231. else if(player->lookdir < 0)
  232. {
  233. player->lookdir += 8;
  234. }
  235. if(abs(player->lookdir) < 8)
  236. {
  237. player->lookdir = 0;
  238. player->centering = false;
  239. }
  240. }
  241. fly = cmd->lookfly>>4;
  242. if(fly > 7)
  243. {
  244. fly -= 16;
  245. }
  246. if(fly && player->powers[pw_flight])
  247. {
  248. if(fly != TOCENTER)
  249. {
  250. player->flyheight = fly*2;
  251. if(!(player->mo->flags2&MF2_FLY))
  252. {
  253. player->mo->flags2 |= MF2_FLY;
  254. player->mo->flags |= MF_NOGRAVITY;
  255. if(player->mo->momz <= -39*FRACUNIT)
  256. { // stop falling scream
  257. S_StopSound(player->mo);
  258. }
  259. }
  260. }
  261. else
  262. {
  263. player->mo->flags2 &= ~MF2_FLY;
  264. player->mo->flags &= ~MF_NOGRAVITY;
  265. }
  266. }
  267. else if(fly > 0)
  268. {
  269. P_PlayerUseArtifact(player, arti_fly);
  270. }
  271. if(player->mo->flags2&MF2_FLY)
  272. {
  273. player->mo->momz = player->flyheight*FRACUNIT;
  274. if(player->flyheight)
  275. {
  276. player->flyheight /= 2;
  277. }
  278. }
  279. }
  280. //==========================================================================
  281. //
  282. // P_DeathThink
  283. //
  284. //==========================================================================
  285. void P_DeathThink(player_t *player)
  286. {
  287. int dir;
  288. angle_t delta;
  289. int lookDelta;
  290. extern int inv_ptr;
  291. extern int curpos;
  292. P_MovePsprites(player);
  293. onground = (player->mo->z <= player->mo->floorz);
  294. if(player->mo->type == MT_BLOODYSKULL || player->mo->type == MT_ICECHUNK)
  295. { // Flying bloody skull or flying ice chunk
  296. player->viewheight = 6*FRACUNIT;
  297. player->deltaviewheight = 0;
  298. //player->damagecount = 20;
  299. if(onground)
  300. {
  301. if(player->lookdir < 60)
  302. {
  303. lookDelta = (60-player->lookdir)/8;
  304. if(lookDelta < 1 && (leveltime&1))
  305. {
  306. lookDelta = 1;
  307. }
  308. else if(lookDelta > 6)
  309. {
  310. lookDelta = 6;
  311. }
  312. player->lookdir += lookDelta;
  313. }
  314. }
  315. }
  316. else if(!(player->mo->flags2&MF2_ICEDAMAGE))
  317. { // Fall to ground (if not frozen)
  318. player->deltaviewheight = 0;
  319. if(player->viewheight > 6*FRACUNIT)
  320. {
  321. player->viewheight -= FRACUNIT;
  322. }
  323. if(player->viewheight < 6*FRACUNIT)
  324. {
  325. player->viewheight = 6*FRACUNIT;
  326. }
  327. if(player->lookdir > 0)
  328. {
  329. player->lookdir -= 6;
  330. }
  331. else if(player->lookdir < 0)
  332. {
  333. player->lookdir += 6;
  334. }
  335. if(abs(player->lookdir) < 6)
  336. {
  337. player->lookdir = 0;
  338. }
  339. }
  340. P_CalcHeight(player);
  341. if(player->attacker && player->attacker != player->mo)
  342. { // Watch killer
  343. dir = P_FaceMobj(player->mo, player->attacker, &delta);
  344. if(delta < ANGLE_1*10)
  345. { // Looking at killer, so fade damage and poison counters
  346. if(player->damagecount)
  347. {
  348. player->damagecount--;
  349. }
  350. if(player->poisoncount)
  351. {
  352. player->poisoncount--;
  353. }
  354. }
  355. delta = delta/8;
  356. if(delta > ANGLE_1*5)
  357. {
  358. delta = ANGLE_1*5;
  359. }
  360. if(dir)
  361. { // Turn clockwise
  362. player->mo->angle += delta;
  363. }
  364. else
  365. { // Turn counter clockwise
  366. player->mo->angle -= delta;
  367. }
  368. }
  369. else if(player->damagecount || player->poisoncount)
  370. {
  371. if(player->damagecount)
  372. {
  373. player->damagecount--;
  374. }
  375. else
  376. {
  377. player->poisoncount--;
  378. }
  379. }
  380. if(player->cmd.buttons&BT_USE)
  381. {
  382. if(player == &players[consoleplayer])
  383. {
  384. I_SetPalette((byte *)W_CacheLumpName("PLAYPAL", PU_CACHE));
  385. inv_ptr = 0;
  386. curpos = 0;
  387. newtorch = 0;
  388. newtorchdelta = 0;
  389. }
  390. player->playerstate = PST_REBORN;
  391. player->mo->special1 = player->class;
  392. if(player->mo->special1 > 2)
  393. {
  394. player->mo->special1 = 0;
  395. }
  396. // Let the mobj know the player has entered the reborn state. Some
  397. // mobjs need to know when it's ok to remove themselves.
  398. player->mo->special2 = 666;
  399. }
  400. }
  401. //----------------------------------------------------------------------------
  402. //
  403. // PROC P_MorphPlayerThink
  404. //
  405. //----------------------------------------------------------------------------
  406. void P_MorphPlayerThink(player_t *player)
  407. {
  408. mobj_t *pmo;
  409. if(player->morphTics&15)
  410. {
  411. return;
  412. }
  413. pmo = player->mo;
  414. if(!(pmo->momx+pmo->momy) && P_Random() < 64)
  415. { // Snout sniff
  416. P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2);
  417. S_StartSound(pmo, SFX_PIG_ACTIVE1); // snort
  418. return;
  419. }
  420. if(P_Random() < 48)
  421. {
  422. if(P_Random() < 128)
  423. {
  424. S_StartSound(pmo, SFX_PIG_ACTIVE1);
  425. }
  426. else
  427. {
  428. S_StartSound(pmo, SFX_PIG_ACTIVE2);
  429. }
  430. }
  431. }
  432. //----------------------------------------------------------------------------
  433. //
  434. // FUNC P_GetPlayerNum
  435. //
  436. //----------------------------------------------------------------------------
  437. int P_GetPlayerNum(player_t *player)
  438. {
  439. int i;
  440. for(i = 0; i < MAXPLAYERS; i++)
  441. {
  442. if(player == &players[i])
  443. {
  444. return(i);
  445. }
  446. }
  447. return(0);
  448. }
  449. //----------------------------------------------------------------------------
  450. //
  451. // FUNC P_UndoPlayerMorph
  452. //
  453. //----------------------------------------------------------------------------
  454. boolean P_UndoPlayerMorph(player_t *player)
  455. {
  456. mobj_t *fog;
  457. mobj_t *mo;
  458. mobj_t *pmo;
  459. fixed_t x;
  460. fixed_t y;
  461. fixed_t z;
  462. angle_t angle;
  463. int playerNum;
  464. weapontype_t weapon;
  465. int oldFlags;
  466. int oldFlags2;
  467. int oldBeast;
  468. pmo = player->mo;
  469. x = pmo->x;
  470. y = pmo->y;
  471. z = pmo->z;
  472. angle = pmo->angle;
  473. weapon = pmo->special1;
  474. oldFlags = pmo->flags;
  475. oldFlags2 = pmo->flags2;
  476. oldBeast = pmo->type;
  477. P_SetMobjState(pmo, S_FREETARGMOBJ);
  478. playerNum = P_GetPlayerNum(player);
  479. switch(PlayerClass[playerNum])
  480. {
  481. case PCLASS_FIGHTER:
  482. mo = P_SpawnMobj(x, y, z, MT_PLAYER_FIGHTER);
  483. break;
  484. case PCLASS_CLERIC:
  485. mo = P_SpawnMobj(x, y, z, MT_PLAYER_CLERIC);
  486. break;
  487. case PCLASS_MAGE:
  488. mo = P_SpawnMobj(x, y, z, MT_PLAYER_MAGE);
  489. break;
  490. default:
  491. I_Error("P_UndoPlayerMorph: Unknown player class %d\n",
  492. player->class);
  493. }
  494. if(P_TestMobjLocation(mo) == false)
  495. { // Didn't fit
  496. P_RemoveMobj(mo);
  497. mo = P_SpawnMobj(x, y, z, oldBeast);
  498. mo->angle = angle;
  499. mo->health = player->health;
  500. mo->special1 = weapon;
  501. mo->player = player;
  502. mo->flags = oldFlags;
  503. mo->flags2 = oldFlags2;
  504. player->mo = mo;
  505. player->morphTics = 2*35;
  506. return(false);
  507. }
  508. if(player->class == PCLASS_FIGHTER)
  509. {
  510. // The first type should be blue, and the third should be the
  511. // Fighter's original gold color
  512. if(playerNum == 0)
  513. {
  514. mo->flags |= 2<<MF_TRANSSHIFT;
  515. }
  516. else if(playerNum != 2)
  517. {
  518. mo->flags |= playerNum<<MF_TRANSSHIFT;
  519. }
  520. }
  521. else if(playerNum)
  522. { // Set color translation bits for player sprites
  523. mo->flags |= playerNum<<MF_TRANSSHIFT;
  524. }
  525. mo->angle = angle;
  526. mo->player = player;
  527. mo->reactiontime = 18;
  528. if(oldFlags2&MF2_FLY)
  529. {
  530. mo->flags2 |= MF2_FLY;
  531. mo->flags |= MF_NOGRAVITY;
  532. }
  533. player->morphTics = 0;
  534. player->health = mo->health = MAXHEALTH;
  535. player->mo = mo;
  536. player->class = PlayerClass[playerNum];
  537. angle >>= ANGLETOFINESHIFT;
  538. fog = P_SpawnMobj(x+20*finecosine[angle],
  539. y+20*finesine[angle], z+TELEFOGHEIGHT, MT_TFOG);
  540. S_StartSound(fog, SFX_TELEPORT);
  541. P_PostMorphWeapon(player, weapon);
  542. return(true);
  543. }
  544. //----------------------------------------------------------------------------
  545. //
  546. // PROC P_PlayerThink
  547. //
  548. //----------------------------------------------------------------------------
  549. void P_PlayerThink(player_t *player)
  550. {
  551. ticcmd_t *cmd;
  552. weapontype_t newweapon;
  553. int floorType;
  554. mobj_t *pmo;
  555. // No-clip cheat
  556. if(player->cheats&CF_NOCLIP)
  557. {
  558. player->mo->flags |= MF_NOCLIP;
  559. }
  560. else
  561. {
  562. player->mo->flags &= ~MF_NOCLIP;
  563. }
  564. cmd = &player->cmd;
  565. if(player->mo->flags&MF_JUSTATTACKED)
  566. { // Gauntlets attack auto forward motion
  567. cmd->angleturn = 0;
  568. cmd->forwardmove = 0xc800/512;
  569. cmd->sidemove = 0;
  570. player->mo->flags &= ~MF_JUSTATTACKED;
  571. }
  572. // messageTics is above the rest of the counters so that messages will
  573. // go away, even in death.
  574. player->messageTics--; // Can go negative
  575. if(!player->messageTics || player->messageTics == -1)
  576. { // Refresh the screen when a message goes away
  577. player->ultimateMessage = false; // clear out any chat messages.
  578. player->yellowMessage = false;
  579. if(player == &players[consoleplayer])
  580. {
  581. BorderTopRefresh = true;
  582. }
  583. }
  584. player->worldTimer++;
  585. if(player->playerstate == PST_DEAD)
  586. {
  587. P_DeathThink(player);
  588. return;
  589. }
  590. if(player->jumpTics)
  591. {
  592. player->jumpTics--;
  593. }
  594. if(player->morphTics)
  595. {
  596. P_MorphPlayerThink(player);
  597. }
  598. // Handle movement
  599. if(player->mo->reactiontime)
  600. { // Player is frozen
  601. player->mo->reactiontime--;
  602. }
  603. else
  604. {
  605. P_MovePlayer(player);
  606. pmo = player->mo;
  607. if(player->powers[pw_speed] && !(leveltime&1)
  608. && P_AproxDistance(pmo->momx, pmo->momy) > 12*FRACUNIT)
  609. {
  610. mobj_t *speedMo;
  611. int playerNum;
  612. speedMo = P_SpawnMobj(pmo->x, pmo->y, pmo->z, MT_PLAYER_SPEED);
  613. if(speedMo)
  614. {
  615. speedMo->angle = pmo->angle;
  616. playerNum = P_GetPlayerNum(player);
  617. if(player->class == PCLASS_FIGHTER)
  618. {
  619. // The first type should be blue, and the
  620. // third should be the Fighter's original gold color
  621. if(playerNum == 0)
  622. {
  623. speedMo->flags |= 2<<MF_TRANSSHIFT;
  624. }
  625. else if(playerNum != 2)
  626. {
  627. speedMo->flags |= playerNum<<MF_TRANSSHIFT;
  628. }
  629. }
  630. else if(playerNum)
  631. { // Set color translation bits for player sprites
  632. speedMo->flags |= playerNum<<MF_TRANSSHIFT;
  633. }
  634. speedMo->target = pmo;
  635. speedMo->special1 = player->class;
  636. if(speedMo->special1 > 2)
  637. {
  638. speedMo->special1 = 0;
  639. }
  640. speedMo->sprite = pmo->sprite;
  641. speedMo->floorclip = pmo->floorclip;
  642. if(player == &players[consoleplayer])
  643. {
  644. speedMo->flags2 |= MF2_DONTDRAW;
  645. }
  646. }
  647. }
  648. }
  649. P_CalcHeight(player);
  650. if(player->mo->subsector->sector->special)
  651. {
  652. P_PlayerInSpecialSector(player);
  653. }
  654. if((floorType = P_GetThingFloorType(player->mo)) != FLOOR_SOLID)
  655. {
  656. P_PlayerOnSpecialFlat(player, floorType);
  657. }
  658. switch(player->class)
  659. {
  660. case PCLASS_FIGHTER:
  661. if(player->mo->momz <= -35*FRACUNIT
  662. && player->mo->momz >= -40*FRACUNIT && !player->morphTics
  663. && !S_GetSoundPlayingInfo(player->mo,
  664. SFX_PLAYER_FIGHTER_FALLING_SCREAM))
  665. {
  666. S_StartSound(player->mo,
  667. SFX_PLAYER_FIGHTER_FALLING_SCREAM);
  668. }
  669. break;
  670. case PCLASS_CLERIC:
  671. if(player->mo->momz <= -35*FRACUNIT
  672. && player->mo->momz >= -40*FRACUNIT && !player->morphTics
  673. && !S_GetSoundPlayingInfo(player->mo,
  674. SFX_PLAYER_CLERIC_FALLING_SCREAM))
  675. {
  676. S_StartSound(player->mo,
  677. SFX_PLAYER_CLERIC_FALLING_SCREAM);
  678. }
  679. break;
  680. case PCLASS_MAGE:
  681. if(player->mo->momz <= -35*FRACUNIT
  682. && player->mo->momz >= -40*FRACUNIT && !player->morphTics
  683. && !S_GetSoundPlayingInfo(player->mo,
  684. SFX_PLAYER_MAGE_FALLING_SCREAM))
  685. {
  686. S_StartSound(player->mo,
  687. SFX_PLAYER_MAGE_FALLING_SCREAM);
  688. }
  689. break;
  690. default:
  691. break;
  692. }
  693. if(cmd->arti)
  694. { // Use an artifact
  695. if((cmd->arti&AFLAG_JUMP) && onground && !player->jumpTics)
  696. {
  697. if(player->morphTics)
  698. {
  699. player->mo->momz = 6*FRACUNIT;
  700. }
  701. else
  702. {
  703. player->mo->momz = 9*FRACUNIT;
  704. }
  705. player->mo->flags2 &= ~MF2_ONMOBJ;
  706. player->jumpTics = 18;
  707. }
  708. else if(cmd->arti&AFLAG_SUICIDE)
  709. {
  710. P_DamageMobj(player->mo, NULL, NULL, 10000);
  711. }
  712. if(cmd->arti == NUMARTIFACTS)
  713. { // use one of each artifact (except puzzle artifacts)
  714. int i;
  715. for(i = 1; i < arti_firstpuzzitem; i++)
  716. {
  717. P_PlayerUseArtifact(player, i);
  718. }
  719. }
  720. else
  721. {
  722. P_PlayerUseArtifact(player, cmd->arti&AFLAG_MASK);
  723. }
  724. }
  725. // Check for weapon change
  726. if(cmd->buttons&BT_SPECIAL)
  727. { // A special event has no other buttons
  728. cmd->buttons = 0;
  729. }
  730. if(cmd->buttons&BT_CHANGE && !player->morphTics)
  731. {
  732. // The actual changing of the weapon is done when the weapon
  733. // psprite can do it (A_WeaponReady), so it doesn't happen in
  734. // the middle of an attack.
  735. newweapon = (cmd->buttons&BT_WEAPONMASK)>>BT_WEAPONSHIFT;
  736. if(player->weaponowned[newweapon]
  737. && newweapon != player->readyweapon)
  738. {
  739. player->pendingweapon = newweapon;
  740. }
  741. }
  742. // Check for use
  743. if(cmd->buttons&BT_USE)
  744. {
  745. if(!player->usedown)
  746. {
  747. P_UseLines(player);
  748. player->usedown = true;
  749. }
  750. }
  751. else
  752. {
  753. player->usedown = false;
  754. }
  755. // Morph counter
  756. if(player->morphTics)
  757. {
  758. if(!--player->morphTics)
  759. { // Attempt to undo the pig
  760. P_UndoPlayerMorph(player);
  761. }
  762. }
  763. // Cycle psprites
  764. P_MovePsprites(player);
  765. // Other Counters
  766. if(player->powers[pw_invulnerability])
  767. {
  768. if(player->class == PCLASS_CLERIC)
  769. {
  770. if(!(leveltime&7) && player->mo->flags&MF_SHADOW
  771. && !(player->mo->flags2&MF2_DONTDRAW))
  772. {
  773. player->mo->flags &= ~MF_SHADOW;
  774. if(!(player->mo->flags&MF_ALTSHADOW))
  775. {
  776. player->mo->flags2 |= MF2_DONTDRAW|MF2_NONSHOOTABLE;
  777. }
  778. }
  779. if(!(leveltime&31))
  780. {
  781. if(player->mo->flags2&MF2_DONTDRAW)
  782. {
  783. if(!(player->mo->flags&MF_SHADOW))
  784. {
  785. player->mo->flags |= MF_SHADOW|MF_ALTSHADOW;
  786. }
  787. else
  788. {
  789. player->mo->flags2 &= ~(MF2_DONTDRAW|MF2_NONSHOOTABLE);
  790. }
  791. }
  792. else
  793. {
  794. player->mo->flags |= MF_SHADOW;
  795. player->mo->flags &= ~MF_ALTSHADOW;
  796. }
  797. }
  798. }
  799. if(!(--player->powers[pw_invulnerability]))
  800. {
  801. player->mo->flags2 &= ~(MF2_INVULNERABLE|MF2_REFLECTIVE);
  802. if(player->class == PCLASS_CLERIC)
  803. {
  804. player->mo->flags2 &= ~(MF2_DONTDRAW|MF2_NONSHOOTABLE);
  805. player->mo->flags &= ~(MF_SHADOW|MF_ALTSHADOW);
  806. }
  807. }
  808. }
  809. if(player->powers[pw_minotaur])
  810. {
  811. player->powers[pw_minotaur]--;
  812. }
  813. if(player->powers[pw_infrared])
  814. {
  815. player->powers[pw_infrared]--;
  816. }
  817. if(player->powers[pw_flight] && netgame)
  818. {
  819. if(!--player->powers[pw_flight])
  820. {
  821. if(player->mo->z != player->mo->floorz)
  822. {
  823. #ifdef __WATCOMC__
  824. if(!useexterndriver)
  825. {
  826. player->centering = true;
  827. }
  828. #else
  829. player->centering = true;
  830. #endif
  831. }
  832. player->mo->flags2 &= ~MF2_FLY;
  833. player->mo->flags &= ~MF_NOGRAVITY;
  834. BorderTopRefresh = true; //make sure the sprite's cleared out
  835. }
  836. }
  837. if(player->powers[pw_speed])
  838. {
  839. player->powers[pw_speed]--;
  840. }
  841. if(player->damagecount)
  842. {
  843. player->damagecount--;
  844. }
  845. if(player->bonuscount)
  846. {
  847. player->bonuscount--;
  848. }
  849. if(player->poisoncount && !(leveltime&15))
  850. {
  851. player->poisoncount -= 5;
  852. if(player->poisoncount < 0)
  853. {
  854. player->poisoncount = 0;
  855. }
  856. P_PoisonDamage(player, player->poisoner, 1, true);
  857. }
  858. // Colormaps
  859. // if(player->powers[pw_invulnerability])
  860. // {
  861. // if(player->powers[pw_invulnerability] > BLINKTHRESHOLD
  862. // || (player->powers[pw_invulnerability]&8))
  863. // {
  864. // player->fixedcolormap = INVERSECOLORMAP;
  865. // }
  866. // else
  867. // {
  868. // player->fixedcolormap = 0;
  869. // }
  870. // }
  871. // else
  872. if(player->powers[pw_infrared])
  873. {
  874. if (player->powers[pw_infrared] <= BLINKTHRESHOLD)
  875. {
  876. if(player->powers[pw_infrared]&8)
  877. {
  878. player->fixedcolormap = 0;
  879. }
  880. else
  881. {
  882. player->fixedcolormap = 1;
  883. }
  884. }
  885. else if(!(leveltime&16) && player == &players[consoleplayer])
  886. {
  887. if(newtorch)
  888. {
  889. if(player->fixedcolormap+newtorchdelta > 7
  890. || player->fixedcolormap+newtorchdelta < 1
  891. || newtorch == player->fixedcolormap)
  892. {
  893. newtorch = 0;
  894. }
  895. else
  896. {
  897. player->fixedcolormap += newtorchdelta;
  898. }
  899. }
  900. else
  901. {
  902. newtorch = (M_Random()&7)+1;
  903. newtorchdelta = (newtorch == player->fixedcolormap) ?
  904. 0 : ((newtorch > player->fixedcolormap) ? 1 : -1);
  905. }
  906. }
  907. }
  908. else
  909. {
  910. player->fixedcolormap = 0;
  911. }
  912. }
  913. //----------------------------------------------------------------------------
  914. //
  915. // PROC P_ArtiTele
  916. //
  917. //----------------------------------------------------------------------------
  918. void P_ArtiTele(player_t *player)
  919. {
  920. int i;
  921. int selections;
  922. fixed_t destX;
  923. fixed_t destY;
  924. angle_t destAngle;
  925. if(deathmatch)
  926. {
  927. selections = deathmatch_p-deathmatchstarts;
  928. i = P_Random()%selections;
  929. destX = deathmatchstarts[i].x<<FRACBITS;
  930. destY = deathmatchstarts[i].y<<FRACBITS;
  931. destAngle = ANG45*(deathmatchstarts[i].angle/45);
  932. }
  933. else
  934. {
  935. destX = playerstarts[0][0].x<<FRACBITS;
  936. destY = playerstarts[0][0].y<<FRACBITS;
  937. destAngle = ANG45*(playerstarts[0][0].angle/45);
  938. }
  939. P_Teleport(player->mo, destX, destY, destAngle, true);
  940. if(player->morphTics)
  941. { // Teleporting away will undo any morph effects (pig)
  942. P_UndoPlayerMorph(player);
  943. }
  944. //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
  945. }
  946. //----------------------------------------------------------------------------
  947. //
  948. // PROC P_ArtiTeleportOther
  949. //
  950. //----------------------------------------------------------------------------
  951. void P_ArtiTeleportOther(player_t *player)
  952. {
  953. mobj_t *mo;
  954. mo=P_SpawnPlayerMissile(player->mo, MT_TELOTHER_FX1);
  955. if (mo)
  956. {
  957. mo->target = player->mo;
  958. }
  959. }
  960. void P_TeleportToPlayerStarts(mobj_t *victim)
  961. {
  962. int i,selections=0;
  963. fixed_t destX,destY;
  964. angle_t destAngle;
  965. for (i=0;i<MAXPLAYERS;i++)
  966. {
  967. if (!playeringame[i]) continue;
  968. selections++;
  969. }
  970. i = P_Random()%selections;
  971. destX = playerstarts[0][i].x<<FRACBITS;
  972. destY = playerstarts[0][i].y<<FRACBITS;
  973. destAngle = ANG45*(playerstarts[0][i].angle/45);
  974. P_Teleport(victim, destX, destY, destAngle, true);
  975. //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
  976. }
  977. void P_TeleportToDeathmatchStarts(mobj_t *victim)
  978. {
  979. int i,selections;
  980. fixed_t destX,destY;
  981. angle_t destAngle;
  982. selections = deathmatch_p-deathmatchstarts;
  983. if (selections)
  984. {
  985. i = P_Random()%selections;
  986. destX = deathmatchstarts[i].x<<FRACBITS;
  987. destY = deathmatchstarts[i].y<<FRACBITS;
  988. destAngle = ANG45*(deathmatchstarts[i].angle/45);
  989. P_Teleport(victim, destX, destY, destAngle, true);
  990. //S_StartSound(NULL, sfx_wpnup); // Full volume laugh
  991. }
  992. else
  993. {
  994. P_TeleportToPlayerStarts(victim);
  995. }
  996. }
  997. //----------------------------------------------------------------------------
  998. //
  999. // PROC P_TeleportOther
  1000. //
  1001. //----------------------------------------------------------------------------
  1002. void P_TeleportOther(mobj_t *victim)
  1003. {
  1004. if (victim->player)
  1005. {
  1006. if (deathmatch)
  1007. P_TeleportToDeathmatchStarts(victim);
  1008. else
  1009. P_TeleportToPlayerStarts(victim);
  1010. }
  1011. else
  1012. {
  1013. // If death action, run it upon teleport
  1014. if (victim->flags&MF_COUNTKILL && victim->special)
  1015. {
  1016. P_RemoveMobjFromTIDList(victim);
  1017. P_ExecuteLineSpecial(victim->special, victim->args,
  1018. NULL, 0, victim);
  1019. victim->special = 0;
  1020. }
  1021. // Send all monsters to deathmatch spots
  1022. P_TeleportToDeathmatchStarts(victim);
  1023. }
  1024. }
  1025. #define BLAST_RADIUS_DIST 255*FRACUNIT
  1026. #define BLAST_SPEED 20*FRACUNIT
  1027. #define BLAST_FULLSTRENGTH 255
  1028. void ResetBlasted(mobj_t *mo)
  1029. {
  1030. mo->flags2 &= ~MF2_BLASTED;
  1031. if (!(mo->flags&MF_ICECORPSE))
  1032. {
  1033. mo->flags2 &= ~MF2_SLIDE;
  1034. }
  1035. }
  1036. void P_BlastMobj(mobj_t *source, mobj_t *victim, fixed_t strength)
  1037. {
  1038. angle_t angle,ang;
  1039. mobj_t *mo;
  1040. fixed_t x,y,z;
  1041. angle = R_PointToAngle2(source->x, source->y, victim->x, victim->y);
  1042. angle >>= ANGLETOFINESHIFT;
  1043. if (strength < BLAST_FULLSTRENGTH)
  1044. {
  1045. victim->momx = FixedMul(strength, finecosine[angle]);
  1046. victim->momy = FixedMul(strength, finesine[angle]);
  1047. if (victim->player)
  1048. {
  1049. // Players handled automatically
  1050. }
  1051. else
  1052. {
  1053. victim->flags2 |= MF2_SLIDE;
  1054. victim->flags2 |= MF2_BLASTED;
  1055. }
  1056. }
  1057. else // full strength blast from artifact
  1058. {
  1059. if (victim->flags&MF_MISSILE)
  1060. {
  1061. switch(victim->type)
  1062. {
  1063. case MT_SORCBALL1: // don't blast sorcerer balls
  1064. case MT_SORCBALL2:
  1065. case MT_SORCBALL3:
  1066. return;
  1067. break;
  1068. case MT_MSTAFF_FX2: // Reflect to originator
  1069. victim->special1 = (int)victim->target;
  1070. victim->target = source;
  1071. break;
  1072. default:
  1073. break;
  1074. }
  1075. }
  1076. if (victim->type == MT_HOLY_FX)
  1077. {
  1078. if ((mobj_t *)(victim->special1) == source)
  1079. {
  1080. victim->special1 = (int)victim->target;
  1081. victim->target = source;
  1082. }
  1083. }
  1084. victim->momx = FixedMul(BLAST_SPEED, finecosine[angle]);
  1085. victim->momy = FixedMul(BLAST_SPEED, finesine[angle]);
  1086. // Spawn blast puff
  1087. ang = R_PointToAngle2(victim->x, victim->y, source->x, source->y);
  1088. ang >>= ANGLETOFINESHIFT;
  1089. x = victim->x + FixedMul(victim->radius+FRACUNIT, finecosine[ang]);
  1090. y = victim->y + FixedMul(victim->radius+FRACUNIT, finesine[ang]);
  1091. z = victim->z - victim->floorclip + (victim->height>>1);
  1092. mo=P_SpawnMobj(x, y, z, MT_BLASTEFFECT);
  1093. if (mo)
  1094. {
  1095. mo->momx = victim->momx;
  1096. mo->momy = victim->momy;
  1097. }
  1098. if (victim->flags&MF_MISSILE)
  1099. {
  1100. victim->momz = 8*FRACUNIT;
  1101. mo->momz = victim->momz;
  1102. }
  1103. else
  1104. {
  1105. victim->momz = (1000/victim->info->mass)<<FRACBITS;
  1106. }
  1107. if (victim->player)
  1108. {
  1109. // Players handled automatically
  1110. }
  1111. else
  1112. {
  1113. victim->flags2 |= MF2_SLIDE;
  1114. victim->flags2 |= MF2_BLASTED;
  1115. }
  1116. }
  1117. }
  1118. // Blast all mobj things away
  1119. void P_BlastRadius(player_t *player)
  1120. {
  1121. mobj_t *mo;
  1122. mobj_t *pmo=player->mo;
  1123. thinker_t *think;
  1124. fixed_t dist;
  1125. S_StartSound(pmo, SFX_ARTIFACT_BLAST);
  1126. P_NoiseAlert(player->mo, player->mo);
  1127. for(think = thinkercap.next; think != &thinkercap; think = think->next)
  1128. {
  1129. if(think->function != P_MobjThinker)
  1130. { // Not a mobj thinker
  1131. continue;
  1132. }
  1133. mo = (mobj_t *)think;
  1134. if((mo == pmo) || (mo->flags2&MF2_BOSS))
  1135. { // Not a valid monster
  1136. continue;
  1137. }
  1138. if ((mo->type == MT_POISONCLOUD) || // poison cloud
  1139. (mo->type == MT_HOLY_FX) || // holy fx
  1140. (mo->flags&MF_ICECORPSE)) // frozen corpse
  1141. {
  1142. // Let these special cases go
  1143. }
  1144. else if ((mo->flags&MF_COUNTKILL) &&
  1145. (mo->health <= 0))
  1146. {
  1147. continue;
  1148. }
  1149. else if (!(mo->flags&MF_COUNTKILL) &&
  1150. !(mo->player) &&
  1151. !(mo->flags&MF_MISSILE))
  1152. { // Must be monster, player, or missile
  1153. continue;
  1154. }
  1155. if (mo->flags2&MF2_DORMANT)
  1156. {
  1157. continue; // no dormant creatures
  1158. }
  1159. if ((mo->type == MT_WRAITHB) && (mo->flags2&MF2_DONTDRAW))
  1160. {
  1161. continue; // no underground wraiths
  1162. }
  1163. if ((mo->type == MT_SPLASHBASE) ||
  1164. (mo->type == MT_SPLASH))
  1165. {
  1166. continue;
  1167. }
  1168. if(mo->type == MT_SERPENT || mo->type == MT_SERPENTLEADER)
  1169. {
  1170. continue;
  1171. }
  1172. dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y);
  1173. if(dist > BLAST_RADIUS_DIST)
  1174. { // Out of range
  1175. continue;
  1176. }
  1177. P_BlastMobj(pmo, mo, BLAST_FULLSTRENGTH);
  1178. }
  1179. }
  1180. #define HEAL_RADIUS_DIST 255*FRACUNIT
  1181. // Do class specific effect for everyone in radius
  1182. boolean P_HealRadius(player_t *player)
  1183. {
  1184. mobj_t *mo;
  1185. mobj_t *pmo=player->mo;
  1186. thinker_t *think;
  1187. fixed_t dist;
  1188. int effective=false;
  1189. int amount;
  1190. for(think = thinkercap.next; think != &thinkercap; think = think->next)
  1191. {
  1192. if(think->function != P_MobjThinker)
  1193. { // Not a mobj thinker
  1194. continue;
  1195. }
  1196. mo = (mobj_t *)think;
  1197. if (!mo->player) continue;
  1198. if (mo->health <= 0) continue;
  1199. dist = P_AproxDistance(pmo->x - mo->x, pmo->y - mo->y);
  1200. if(dist > HEAL_RADIUS_DIST)
  1201. { // Out of range
  1202. continue;
  1203. }
  1204. switch(player->class)
  1205. {
  1206. case PCLASS_FIGHTER: // Radius armor boost
  1207. if ((P_GiveArmor(mo->player, ARMOR_ARMOR, 1)) ||
  1208. (P_GiveArmor(mo->player, ARMOR_SHIELD, 1)) ||
  1209. (P_GiveArmor(mo->player, ARMOR_HELMET, 1)) ||
  1210. (P_GiveArmor(mo->player, ARMOR_AMULET, 1)))
  1211. {
  1212. effective=true;
  1213. S_StartSound(mo, SFX_MYSTICINCANT);
  1214. }
  1215. break;
  1216. case PCLASS_CLERIC: // Radius heal
  1217. amount = 50 + (P_Random()%50);
  1218. if (P_GiveBody(mo->player, amount))
  1219. {
  1220. effective=true;
  1221. S_StartSound(mo, SFX_MYSTICINCANT);
  1222. }
  1223. break;
  1224. case PCLASS_MAGE: // Radius mana boost
  1225. amount = 50 + (P_Random()%50);
  1226. if ((P_GiveMana(mo->player, MANA_1, amount)) ||
  1227. (P_GiveMana(mo->player, MANA_2, amount)))
  1228. {
  1229. effective=true;
  1230. S_StartSound(mo, SFX_MYSTICINCANT);
  1231. }
  1232. break;
  1233. case PCLASS_PIG:
  1234. default:
  1235. break;
  1236. }
  1237. }
  1238. return(effective);
  1239. }
  1240. //----------------------------------------------------------------------------
  1241. //
  1242. // PROC P_PlayerNextArtifact
  1243. //
  1244. //----------------------------------------------------------------------------
  1245. void P_PlayerNextArtifact(player_t *player)
  1246. {
  1247. extern int inv_ptr;
  1248. extern int curpos;
  1249. if(player == &players[consoleplayer])
  1250. {
  1251. inv_ptr--;
  1252. if(inv_ptr < 6)
  1253. {
  1254. curpos--;
  1255. if(curpos < 0)
  1256. {
  1257. curpos = 0;
  1258. }
  1259. }
  1260. if(inv_ptr < 0)
  1261. {
  1262. inv_ptr = player->inventorySlotNum-1;
  1263. if(inv_ptr < 6)
  1264. {
  1265. curpos = inv_ptr;
  1266. }
  1267. else
  1268. {
  1269. curpos = 6;
  1270. }
  1271. }
  1272. player->readyArtifact =
  1273. player->inventory[inv_ptr].type;
  1274. }
  1275. }
  1276. //----------------------------------------------------------------------------
  1277. //
  1278. // PROC P_PlayerRemoveArtifact
  1279. //
  1280. //----------------------------------------------------------------------------
  1281. void P_PlayerRemoveArtifact(player_t *player, int slot)
  1282. {
  1283. int i;
  1284. extern int inv_ptr;
  1285. extern int curpos;
  1286. player->artifactCount--;
  1287. if(!(--player->inventory[slot].count))
  1288. { // Used last of a type - compact the artifact list
  1289. player->readyArtifact = arti_none;
  1290. player->inventory[slot].type = arti_none;
  1291. for(i = slot+1; i < player->inventorySlotNum; i++)
  1292. {
  1293. player->inventory[i-1] = player->inventory[i];
  1294. }
  1295. player->inventorySlotNum--;
  1296. if(player == &players[consoleplayer])
  1297. { // Set position markers and get next readyArtifact
  1298. inv_ptr--;
  1299. if(inv_ptr < 6)
  1300. {
  1301. curpos--;
  1302. if(curpos < 0)
  1303. {
  1304. curpos = 0;
  1305. }
  1306. }
  1307. if(inv_ptr >= player->inventorySlotNum)
  1308. {
  1309. inv_ptr = player->inventorySlotNum-1;
  1310. }
  1311. if(inv_ptr < 0)
  1312. {
  1313. inv_ptr = 0;
  1314. }
  1315. player->readyArtifact =
  1316. player->inventory[inv_ptr].type;
  1317. }
  1318. }
  1319. }
  1320. //----------------------------------------------------------------------------
  1321. //
  1322. // PROC P_PlayerUseArtifact
  1323. //
  1324. //----------------------------------------------------------------------------
  1325. void P_PlayerUseArtifact(player_t *player, artitype_t arti)
  1326. {
  1327. int i;
  1328. for(i = 0; i < player->inventorySlotNum; i++)
  1329. {
  1330. if(player->inventory[i].type == arti)
  1331. { // Found match - try to use
  1332. if(P_UseArtifact(player, arti))
  1333. { // Artifact was used - remove it from inventory
  1334. P_PlayerRemoveArtifact(player, i);
  1335. if(player == &players[consoleplayer])
  1336. {
  1337. if(arti < arti_firstpuzzitem)
  1338. {
  1339. S_StartSound(NULL, SFX_ARTIFACT_USE);
  1340. }
  1341. else
  1342. {
  1343. S_StartSound(NULL, SFX_PUZZLE_SUCCESS);
  1344. }
  1345. ArtifactFlash = 4;
  1346. }
  1347. }
  1348. else if(arti < arti_firstpuzzitem)
  1349. { // Unable to use artifact, advance pointer
  1350. P_PlayerNextArtifact(player);
  1351. }
  1352. break;
  1353. }
  1354. }
  1355. }
  1356. //==========================================================================
  1357. //
  1358. // P_UseArtifact
  1359. //
  1360. // Returns true if the artifact was used.
  1361. //
  1362. //==========================================================================
  1363. boolean P_UseArtifact(player_t *player, artitype_t arti)
  1364. {
  1365. mobj_t *mo;
  1366. angle_t angle;
  1367. int i;
  1368. int count;
  1369. switch(arti)
  1370. {
  1371. case arti_invulnerability:
  1372. if(!P_GivePower(player, pw_invulnerability))
  1373. {
  1374. return(false);
  1375. }
  1376. break;
  1377. case arti_health:
  1378. if(!P_GiveBody(player, 25))
  1379. {
  1380. return(false);
  1381. }
  1382. break;
  1383. case arti_superhealth:
  1384. if(!P_GiveBody(player, 100))
  1385. {
  1386. return(false);
  1387. }
  1388. break;
  1389. case arti_healingradius:
  1390. if (!P_HealRadius(player))
  1391. {
  1392. return(false);
  1393. }
  1394. break;
  1395. case arti_torch:
  1396. if(!P_GivePower(player, pw_infrared))
  1397. {
  1398. return(false);
  1399. }
  1400. break;
  1401. case arti_egg:
  1402. mo = player->mo;
  1403. P_SpawnPlayerMissile(mo, MT_EGGFX);
  1404. P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/6));
  1405. P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/6));
  1406. P_SPMAngle(mo, MT_EGGFX, mo->angle-(ANG45/3));
  1407. P_SPMAngle(mo, MT_EGGFX, mo->angle+(ANG45/3));
  1408. break;
  1409. case arti_fly:
  1410. if(!P_GivePower(player, pw_flight))
  1411. {
  1412. return(false);
  1413. }
  1414. if(player->mo->momz <= -35*FRACUNIT)
  1415. { // stop falling scream
  1416. S_StopSound(player->mo);
  1417. }
  1418. break;
  1419. case arti_summon:
  1420. mo = P_SpawnPlayerMissile(player->mo, MT_SUMMON_FX);
  1421. if (mo)
  1422. {
  1423. mo->target = player->mo;
  1424. mo->special1 = (int)(player->mo);
  1425. mo->momz = 5*FRACUNIT;
  1426. }
  1427. break;
  1428. case arti_teleport:
  1429. P_ArtiTele(player);
  1430. break;
  1431. case arti_teleportother:
  1432. P_ArtiTeleportOther(player);
  1433. break;
  1434. case arti_poisonbag:
  1435. angle = player->mo->angle>>ANGLETOFINESHIFT;
  1436. if(player->class == PCLASS_CLERIC)
  1437. {
  1438. mo = P_SpawnMobj(player->mo->x+16*finecosine[angle],
  1439. player->mo->y+24*finesine[angle], player->mo->z-
  1440. player->mo->floorclip+8*FRACUNIT, MT_POISONBAG);
  1441. if(mo)
  1442. {
  1443. mo->target = player->mo;
  1444. }
  1445. }
  1446. else if(player->class == PCLASS_MAGE)
  1447. {
  1448. mo = P_SpawnMobj(player->mo->x+16*finecosine[angle],
  1449. player->mo->y+24*finesine[angle], player->mo->z-
  1450. player->mo->floorclip+8*FRACUNIT, MT_FIREBOMB);
  1451. if(mo)
  1452. {
  1453. mo->target = player->mo;
  1454. }
  1455. }
  1456. else // PCLASS_FIGHTER, obviously (also pig, not so obviously)
  1457. {
  1458. mo = P_SpawnMobj(player->mo->x, player->mo->y,
  1459. player->mo->z-player->mo->floorclip+35*FRACUNIT,
  1460. MT_THROWINGBOMB);
  1461. if(mo)
  1462. {
  1463. mo->angle = player->mo->angle+(((P_Random()&7)-4)<<24);
  1464. mo->momz = 4*FRACUNIT+((player->lookdir)<<(FRACBITS-4));
  1465. mo->z += player->lookdir<<(FRACBITS-4);
  1466. P_ThrustMobj(mo, mo->angle, mo->info->speed);
  1467. mo->momx += player->mo->momx>>1;
  1468. mo->momy += player->mo->momy>>1;
  1469. mo->target = player->mo;
  1470. mo->tics -= P_Random()&3;
  1471. P_CheckMissileSpawn(mo);
  1472. }
  1473. }
  1474. break;
  1475. case arti_speed:
  1476. if(!P_GivePower(player, pw_speed))
  1477. {
  1478. return(false);
  1479. }
  1480. break;
  1481. case arti_boostmana:
  1482. if(!P_GiveMana(player, MANA_1, MAX_MANA))
  1483. {
  1484. if(!P_GiveMana(player, MANA_2, MAX_MANA))
  1485. {
  1486. return false;
  1487. }
  1488. }
  1489. else
  1490. {
  1491. P_GiveMana(player, MANA_2, MAX_MANA);
  1492. }
  1493. break;
  1494. case arti_boostarmor:
  1495. count = 0;
  1496. for(i = 0; i < NUMARMOR; i++)
  1497. {
  1498. count += P_GiveArmor(player, i, 1); // 1 point per armor type
  1499. }
  1500. if(!count)
  1501. {
  1502. return false;
  1503. }
  1504. break;
  1505. case arti_blastradius:
  1506. P_BlastRadius(player);
  1507. break;
  1508. case arti_puzzskull:
  1509. case arti_puzzgembig:
  1510. case arti_puzzgemred:
  1511. case arti_puzzgemgreen1:
  1512. case arti_puzzgemgreen2:
  1513. case arti_puzzgemblue1:
  1514. case arti_puzzgemblue2:
  1515. case arti_puzzbook1:
  1516. case arti_puzzbook2:
  1517. case arti_puzzskull2:
  1518. case arti_puzzfweapon:
  1519. case arti_puzzcweapon:
  1520. case arti_puzzmweapon:
  1521. case arti_puzzgear1:
  1522. case arti_puzzgear2:
  1523. case arti_puzzgear3:
  1524. case arti_puzzgear4:
  1525. if(P_UsePuzzleItem(player, arti-arti_firstpuzzitem))
  1526. {
  1527. return true;
  1528. }
  1529. else
  1530. {
  1531. P_SetYellowMessage(player, TXT_USEPUZZLEFAILED, false);
  1532. return false;
  1533. }
  1534. break;
  1535. default:
  1536. return false;
  1537. }
  1538. return true;
  1539. }
  1540. //============================================================================
  1541. //
  1542. // A_SpeedFade
  1543. //
  1544. //============================================================================
  1545. void A_SpeedFade(mobj_t *actor)
  1546. {
  1547. actor->flags |= MF_SHADOW;
  1548. actor->flags &= ~MF_ALTSHADOW;
  1549. actor->sprite = actor->target->sprite;
  1550. }