P_INTER.C 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253
  1. //**************************************************************************
  2. //**
  3. //** p_inter.c : Heretic 2 : Raven Software, Corp.
  4. //**
  5. //** $RCSfile: p_inter.c,v $
  6. //** $Revision: 1.145 $
  7. //** $Date: 96/01/16 10:35:33 $
  8. //** $Author: bgokey $
  9. //**
  10. //**************************************************************************
  11. #include "h2def.h"
  12. #include "p_local.h"
  13. #include "soundst.h"
  14. #define BONUSADD 6
  15. int ArmorIncrement[NUMCLASSES][NUMARMOR] =
  16. {
  17. { 25*FRACUNIT, 20*FRACUNIT, 15*FRACUNIT, 5*FRACUNIT },
  18. { 10*FRACUNIT, 25*FRACUNIT, 5*FRACUNIT, 20*FRACUNIT },
  19. { 5*FRACUNIT, 15*FRACUNIT, 10*FRACUNIT, 25*FRACUNIT },
  20. { 0, 0, 0, 0 }
  21. };
  22. int AutoArmorSave[NUMCLASSES] = { 15*FRACUNIT, 10*FRACUNIT, 5*FRACUNIT, 0 };
  23. char *TextKeyMessages[] =
  24. {
  25. TXT_KEY_STEEL,
  26. TXT_KEY_CAVE,
  27. TXT_KEY_AXE,
  28. TXT_KEY_FIRE,
  29. TXT_KEY_EMERALD,
  30. TXT_KEY_DUNGEON,
  31. TXT_KEY_SILVER,
  32. TXT_KEY_RUSTED,
  33. TXT_KEY_HORN,
  34. TXT_KEY_SWAMP,
  35. TXT_KEY_CASTLE
  36. };
  37. static void SetDormantArtifact(mobj_t *arti);
  38. static void TryPickupArtifact(player_t *player, artitype_t artifactType,
  39. mobj_t *artifact);
  40. static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
  41. weapontype_t weaponType, mobj_t *weapon, char *message);
  42. static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
  43. int pieceValue, mobj_t *pieceMobj);
  44. #ifdef __NeXT__
  45. extern void strupr(char *s);
  46. #endif
  47. //--------------------------------------------------------------------------
  48. //
  49. // PROC P_SetMessage
  50. //
  51. //--------------------------------------------------------------------------
  52. void P_SetMessage(player_t *player, char *message, boolean ultmsg)
  53. {
  54. extern boolean messageson;
  55. if((player->ultimateMessage || !messageson) && !ultmsg)
  56. {
  57. return;
  58. }
  59. if(strlen(message) > 79)
  60. {
  61. memcpy(player->message, message, 80);
  62. player->message[80] = 0;
  63. }
  64. else
  65. {
  66. strcpy(player->message, message);
  67. }
  68. strupr(player->message);
  69. player->messageTics = MESSAGETICS;
  70. player->yellowMessage = false;
  71. if(ultmsg)
  72. {
  73. player->ultimateMessage = true;
  74. }
  75. if(player == &players[consoleplayer])
  76. {
  77. BorderTopRefresh = true;
  78. }
  79. }
  80. //==========================================================================
  81. //
  82. // P_SetYellowMessage
  83. //
  84. //==========================================================================
  85. void P_SetYellowMessage(player_t *player, char *message, boolean ultmsg)
  86. {
  87. extern boolean messageson;
  88. if((player->ultimateMessage || !messageson) && !ultmsg)
  89. {
  90. return;
  91. }
  92. if(strlen(message) > 79)
  93. {
  94. memcpy(player->message, message, 80);
  95. player->message[80] = 0;
  96. }
  97. else
  98. {
  99. strcpy(player->message, message);
  100. }
  101. player->messageTics = 5*MESSAGETICS; // Bold messages last longer
  102. player->yellowMessage = true;
  103. if(ultmsg)
  104. {
  105. player->ultimateMessage = true;
  106. }
  107. if(player == &players[consoleplayer])
  108. {
  109. BorderTopRefresh = true;
  110. }
  111. }
  112. //==========================================================================
  113. //
  114. // P_ClearMessage
  115. //
  116. //==========================================================================
  117. void P_ClearMessage(player_t *player)
  118. {
  119. player->messageTics = 0;
  120. if(player == &players[consoleplayer])
  121. {
  122. BorderTopRefresh = true;
  123. }
  124. }
  125. //----------------------------------------------------------------------------
  126. //
  127. // PROC P_HideSpecialThing
  128. //
  129. //----------------------------------------------------------------------------
  130. void P_HideSpecialThing(mobj_t *thing)
  131. {
  132. thing->flags &= ~MF_SPECIAL;
  133. thing->flags2 |= MF2_DONTDRAW;
  134. P_SetMobjState(thing, S_HIDESPECIAL1);
  135. }
  136. //--------------------------------------------------------------------------
  137. //
  138. // FUNC P_GiveMana
  139. //
  140. // Returns true if the player accepted the mana, false if it was
  141. // refused (player has MAX_MANA).
  142. //
  143. //--------------------------------------------------------------------------
  144. boolean P_GiveMana(player_t *player, manatype_t mana, int count)
  145. {
  146. int prevMana;
  147. //weapontype_t changeWeapon;
  148. if(mana == MANA_NONE || mana == MANA_BOTH)
  149. {
  150. return(false);
  151. }
  152. if(mana < 0 || mana > NUMMANA)
  153. {
  154. I_Error("P_GiveMana: bad type %i", mana);
  155. }
  156. if(player->mana[mana] == MAX_MANA)
  157. {
  158. return(false);
  159. }
  160. if(gameskill == sk_baby || gameskill == sk_nightmare)
  161. { // extra mana in baby mode and nightmare mode
  162. count += count>>1;
  163. }
  164. prevMana = player->mana[mana];
  165. player->mana[mana] += count;
  166. if(player->mana[mana] > MAX_MANA)
  167. {
  168. player->mana[mana] = MAX_MANA;
  169. }
  170. if(player->class == PCLASS_FIGHTER && player->readyweapon == WP_SECOND
  171. && mana == MANA_1 && prevMana <= 0)
  172. {
  173. P_SetPsprite(player, ps_weapon, S_FAXEREADY_G);
  174. }
  175. return(true);
  176. }
  177. //==========================================================================
  178. //
  179. // TryPickupWeapon
  180. //
  181. //==========================================================================
  182. static void TryPickupWeapon(player_t *player, pclass_t weaponClass,
  183. weapontype_t weaponType, mobj_t *weapon, char *message)
  184. {
  185. boolean remove;
  186. boolean gaveMana;
  187. boolean gaveWeapon;
  188. remove = true;
  189. if(player->class != weaponClass)
  190. { // Wrong class, but try to pick up for mana
  191. if(netgame && !deathmatch)
  192. { // Can't pick up weapons for other classes in coop netplay
  193. return;
  194. }
  195. if(weaponType == WP_SECOND)
  196. {
  197. if(!P_GiveMana(player, MANA_1, 25))
  198. {
  199. return;
  200. }
  201. }
  202. else
  203. {
  204. if(!P_GiveMana(player, MANA_2, 25))
  205. {
  206. return;
  207. }
  208. }
  209. }
  210. else if(netgame && !deathmatch)
  211. { // Cooperative net-game
  212. if(player->weaponowned[weaponType])
  213. {
  214. return;
  215. }
  216. player->weaponowned[weaponType] = true;
  217. if(weaponType == WP_SECOND)
  218. {
  219. P_GiveMana(player, MANA_1, 25);
  220. }
  221. else
  222. {
  223. P_GiveMana(player, MANA_2, 25);
  224. }
  225. player->pendingweapon = weaponType;
  226. remove = false;
  227. }
  228. else
  229. { // Deathmatch or single player game
  230. if(weaponType == WP_SECOND)
  231. {
  232. gaveMana = P_GiveMana(player, MANA_1, 25);
  233. }
  234. else
  235. {
  236. gaveMana = P_GiveMana(player, MANA_2, 25);
  237. }
  238. if(player->weaponowned[weaponType])
  239. {
  240. gaveWeapon = false;
  241. }
  242. else
  243. {
  244. gaveWeapon = true;
  245. player->weaponowned[weaponType] = true;
  246. if(weaponType > player->readyweapon)
  247. { // Only switch to more powerful weapons
  248. player->pendingweapon = weaponType;
  249. }
  250. }
  251. if(!(gaveWeapon || gaveMana))
  252. { // Player didn't need the weapon or any mana
  253. return;
  254. }
  255. }
  256. P_SetMessage(player, message, false);
  257. if(weapon->special)
  258. {
  259. P_ExecuteLineSpecial(weapon->special, weapon->args,
  260. NULL, 0, player->mo);
  261. weapon->special = 0;
  262. }
  263. if(remove)
  264. {
  265. if(deathmatch && !(weapon->flags2&MF2_DROPPED))
  266. {
  267. P_HideSpecialThing(weapon);
  268. }
  269. else
  270. {
  271. P_RemoveMobj(weapon);
  272. }
  273. }
  274. player->bonuscount += BONUSADD;
  275. if(player == &players[consoleplayer])
  276. {
  277. S_StartSound(NULL, SFX_PICKUP_WEAPON);
  278. SB_PaletteFlash(false);
  279. }
  280. }
  281. //--------------------------------------------------------------------------
  282. //
  283. // FUNC P_GiveWeapon
  284. //
  285. // Returns true if the weapon or its mana was accepted.
  286. //
  287. //--------------------------------------------------------------------------
  288. /*
  289. boolean P_GiveWeapon(player_t *player, pclass_t class, weapontype_t weapon)
  290. {
  291. boolean gaveMana;
  292. boolean gaveWeapon;
  293. if(player->class != class)
  294. { // player cannot use this weapon, take it anyway, and get mana
  295. if(netgame && !deathmatch)
  296. { // Can't pick up weapons for other classes in coop netplay
  297. return false;
  298. }
  299. if(weapon == WP_SECOND)
  300. {
  301. return P_GiveMana(player, MANA_1, 25);
  302. }
  303. else
  304. {
  305. return P_GiveMana(player, MANA_2, 25);
  306. }
  307. }
  308. if(netgame && !deathmatch)
  309. { // Cooperative net-game
  310. if(player->weaponowned[weapon])
  311. {
  312. return(false);
  313. }
  314. player->bonuscount += BONUSADD;
  315. player->weaponowned[weapon] = true;
  316. if(weapon == WP_SECOND)
  317. {
  318. P_GiveMana(player, MANA_1, 25);
  319. }
  320. else
  321. {
  322. P_GiveMana(player, MANA_2, 25);
  323. }
  324. player->pendingweapon = weapon;
  325. if(player == &players[consoleplayer])
  326. {
  327. S_StartSound(NULL, SFX_PICKUP_WEAPON);
  328. }
  329. return(false);
  330. }
  331. if(weapon == WP_SECOND)
  332. {
  333. gaveMana = P_GiveMana(player, MANA_1, 25);
  334. }
  335. else
  336. {
  337. gaveMana = P_GiveMana(player, MANA_2, 25);
  338. }
  339. if(player->weaponowned[weapon])
  340. {
  341. gaveWeapon = false;
  342. }
  343. else
  344. {
  345. gaveWeapon = true;
  346. player->weaponowned[weapon] = true;
  347. if(weapon > player->readyweapon)
  348. { // Only switch to more powerful weapons
  349. player->pendingweapon = weapon;
  350. }
  351. }
  352. return(gaveWeapon || gaveMana);
  353. }
  354. */
  355. //===========================================================================
  356. //
  357. // P_GiveWeaponPiece
  358. //
  359. //===========================================================================
  360. /*
  361. boolean P_GiveWeaponPiece(player_t *player, pclass_t class, int piece)
  362. {
  363. P_GiveMana(player, MANA_1, 20);
  364. P_GiveMana(player, MANA_2, 20);
  365. if(player->class != class)
  366. {
  367. return true;
  368. }
  369. else if(player->pieces&piece)
  370. { // player already has that weapon piece
  371. return true;
  372. }
  373. player->pieces |= piece;
  374. if(player->pieces == 7)
  375. { // player has built the fourth weapon!
  376. P_GiveWeapon(player, class, WP_FOURTH);
  377. S_StartSound(player->mo, SFX_WEAPON_BUILD);
  378. }
  379. return true;
  380. }
  381. */
  382. //==========================================================================
  383. //
  384. // TryPickupWeaponPiece
  385. //
  386. //==========================================================================
  387. static void TryPickupWeaponPiece(player_t *player, pclass_t matchClass,
  388. int pieceValue, mobj_t *pieceMobj)
  389. {
  390. boolean remove;
  391. boolean checkAssembled;
  392. boolean gaveWeapon;
  393. int gaveMana;
  394. static char *fourthWeaponText[] =
  395. {
  396. TXT_WEAPON_F4,
  397. TXT_WEAPON_C4,
  398. TXT_WEAPON_M4
  399. };
  400. static char *weaponPieceText[] =
  401. {
  402. TXT_QUIETUS_PIECE,
  403. TXT_WRAITHVERGE_PIECE,
  404. TXT_BLOODSCOURGE_PIECE
  405. };
  406. static int pieceValueTrans[] =
  407. {
  408. 0, // 0: never
  409. WPIECE1|WPIECE2|WPIECE3, // WPIECE1 (1)
  410. WPIECE2|WPIECE3, // WPIECE2 (2)
  411. 0, // 3: never
  412. WPIECE3 // WPIECE3 (4)
  413. };
  414. remove = true;
  415. checkAssembled = true;
  416. gaveWeapon = false;
  417. if(player->class != matchClass)
  418. { // Wrong class, but try to pick up for mana
  419. if(netgame && !deathmatch)
  420. { // Can't pick up wrong-class weapons in coop netplay
  421. return;
  422. }
  423. checkAssembled = false;
  424. gaveMana = P_GiveMana(player, MANA_1, 20)+
  425. P_GiveMana(player, MANA_2, 20);
  426. if(!gaveMana)
  427. { // Didn't need the mana, so don't pick it up
  428. return;
  429. }
  430. }
  431. else if(netgame && !deathmatch)
  432. { // Cooperative net-game
  433. if(player->pieces&pieceValue)
  434. { // Already has the piece
  435. return;
  436. }
  437. pieceValue = pieceValueTrans[pieceValue];
  438. P_GiveMana(player, MANA_1, 20);
  439. P_GiveMana(player, MANA_2, 20);
  440. remove = false;
  441. }
  442. else
  443. { // Deathmatch or single player game
  444. gaveMana = P_GiveMana(player, MANA_1, 20)+
  445. P_GiveMana(player, MANA_2, 20);
  446. if(player->pieces&pieceValue)
  447. { // Already has the piece, check if mana needed
  448. if(!gaveMana)
  449. { // Didn't need the mana, so don't pick it up
  450. return;
  451. }
  452. checkAssembled = false;
  453. }
  454. }
  455. // Pick up the weapon piece
  456. if(pieceMobj->special)
  457. {
  458. P_ExecuteLineSpecial(pieceMobj->special, pieceMobj->args,
  459. NULL, 0, player->mo);
  460. pieceMobj->special = 0;
  461. }
  462. if(remove)
  463. {
  464. if(deathmatch && !(pieceMobj->flags2&MF2_DROPPED))
  465. {
  466. P_HideSpecialThing(pieceMobj);
  467. }
  468. else
  469. {
  470. P_RemoveMobj(pieceMobj);
  471. }
  472. }
  473. player->bonuscount += BONUSADD;
  474. if(player == &players[consoleplayer])
  475. {
  476. SB_PaletteFlash(false);
  477. }
  478. // Check if fourth weapon assembled
  479. if(checkAssembled)
  480. {
  481. player->pieces |= pieceValue;
  482. if(player->pieces == (WPIECE1|WPIECE2|WPIECE3))
  483. {
  484. gaveWeapon = true;
  485. player->weaponowned[WP_FOURTH] = true;
  486. player->pendingweapon = WP_FOURTH;
  487. }
  488. }
  489. if(gaveWeapon)
  490. {
  491. P_SetMessage(player, fourthWeaponText[matchClass], false);
  492. // Play the build-sound full volume for all players
  493. S_StartSound(NULL, SFX_WEAPON_BUILD);
  494. }
  495. else
  496. {
  497. P_SetMessage(player, weaponPieceText[matchClass], false);
  498. if(player == &players[consoleplayer])
  499. {
  500. S_StartSound(NULL, SFX_PICKUP_WEAPON);
  501. }
  502. }
  503. }
  504. //---------------------------------------------------------------------------
  505. //
  506. // FUNC P_GiveBody
  507. //
  508. // Returns false if the body isn't needed at all.
  509. //
  510. //---------------------------------------------------------------------------
  511. boolean P_GiveBody(player_t *player, int num)
  512. {
  513. int max;
  514. max = MAXHEALTH;
  515. if(player->morphTics)
  516. {
  517. max = MAXMORPHHEALTH;
  518. }
  519. if(player->health >= max)
  520. {
  521. return(false);
  522. }
  523. player->health += num;
  524. if(player->health > max)
  525. {
  526. player->health = max;
  527. }
  528. player->mo->health = player->health;
  529. return(true);
  530. }
  531. //---------------------------------------------------------------------------
  532. //
  533. // FUNC P_GiveArmor
  534. //
  535. // Returns false if the armor is worse than the current armor.
  536. //
  537. //---------------------------------------------------------------------------
  538. boolean P_GiveArmor(player_t *player, armortype_t armortype, int amount)
  539. {
  540. int hits;
  541. int totalArmor;
  542. extern int ArmorMax[NUMCLASSES];
  543. if(amount == -1)
  544. {
  545. hits = ArmorIncrement[player->class][armortype];
  546. if(player->armorpoints[armortype] >= hits)
  547. {
  548. return false;
  549. }
  550. else
  551. {
  552. player->armorpoints[armortype] = hits;
  553. }
  554. }
  555. else
  556. {
  557. hits = amount*5*FRACUNIT;
  558. totalArmor = player->armorpoints[ARMOR_ARMOR]
  559. +player->armorpoints[ARMOR_SHIELD]
  560. +player->armorpoints[ARMOR_HELMET]
  561. +player->armorpoints[ARMOR_AMULET]
  562. +AutoArmorSave[player->class];
  563. if(totalArmor < ArmorMax[player->class]*5*FRACUNIT)
  564. {
  565. player->armorpoints[armortype] += hits;
  566. }
  567. else
  568. {
  569. return false;
  570. }
  571. }
  572. return true;
  573. }
  574. //---------------------------------------------------------------------------
  575. //
  576. // PROC P_GiveKey
  577. //
  578. //---------------------------------------------------------------------------
  579. int P_GiveKey(player_t *player, keytype_t key)
  580. {
  581. if(player->keys&(1<<key))
  582. {
  583. return false;
  584. }
  585. player->bonuscount += BONUSADD;
  586. player->keys |= 1<<key;
  587. return true;
  588. }
  589. //---------------------------------------------------------------------------
  590. //
  591. // FUNC P_GivePower
  592. //
  593. // Returns true if power accepted.
  594. //
  595. //---------------------------------------------------------------------------
  596. boolean P_GivePower(player_t *player, powertype_t power)
  597. {
  598. if(power == pw_invulnerability)
  599. {
  600. if(player->powers[power] > BLINKTHRESHOLD)
  601. { // Already have it
  602. return(false);
  603. }
  604. player->powers[power] = INVULNTICS;
  605. player->mo->flags2 |= MF2_INVULNERABLE;
  606. if(player->class == PCLASS_MAGE)
  607. {
  608. player->mo->flags2 |= MF2_REFLECTIVE;
  609. }
  610. return(true);
  611. }
  612. if(power == pw_flight)
  613. {
  614. if(player->powers[power] > BLINKTHRESHOLD)
  615. { // Already have it
  616. return(false);
  617. }
  618. player->powers[power] = FLIGHTTICS;
  619. player->mo->flags2 |= MF2_FLY;
  620. player->mo->flags |= MF_NOGRAVITY;
  621. if(player->mo->z <= player->mo->floorz)
  622. {
  623. player->flyheight = 10; // thrust the player in the air a bit
  624. }
  625. return(true);
  626. }
  627. if(power == pw_infrared)
  628. {
  629. if(player->powers[power] > BLINKTHRESHOLD)
  630. { // Already have it
  631. return(false);
  632. }
  633. player->powers[power] = INFRATICS;
  634. return(true);
  635. }
  636. if(power == pw_speed)
  637. {
  638. if(player->powers[power] > BLINKTHRESHOLD)
  639. { // Already have it
  640. return(false);
  641. }
  642. player->powers[power] = SPEEDTICS;
  643. return(true);
  644. }
  645. if(power == pw_minotaur)
  646. {
  647. // Doesn't matter if already have power, renew ticker
  648. player->powers[power] = MAULATORTICS;
  649. return(true);
  650. }
  651. /*
  652. if(power == pw_ironfeet)
  653. {
  654. player->powers[power] = IRONTICS;
  655. return(true);
  656. }
  657. if(power == pw_strength)
  658. {
  659. P_GiveBody(player, 100);
  660. player->powers[power] = 1;
  661. return(true);
  662. }
  663. */
  664. if(player->powers[power])
  665. {
  666. return(false); // already got it
  667. }
  668. player->powers[power] = 1;
  669. return(true);
  670. }
  671. //==========================================================================
  672. //
  673. // TryPickupArtifact
  674. //
  675. //==========================================================================
  676. static void TryPickupArtifact(player_t *player, artitype_t artifactType,
  677. mobj_t *artifact)
  678. {
  679. static char *artifactMessages[NUMARTIFACTS] =
  680. {
  681. NULL,
  682. TXT_ARTIINVULNERABILITY,
  683. TXT_ARTIHEALTH,
  684. TXT_ARTISUPERHEALTH,
  685. TXT_ARTIHEALINGRADIUS,
  686. TXT_ARTISUMMON,
  687. TXT_ARTITORCH,
  688. TXT_ARTIEGG,
  689. TXT_ARTIFLY,
  690. TXT_ARTIBLASTRADIUS,
  691. TXT_ARTIPOISONBAG,
  692. TXT_ARTITELEPORTOTHER,
  693. TXT_ARTISPEED,
  694. TXT_ARTIBOOSTMANA,
  695. TXT_ARTIBOOSTARMOR,
  696. TXT_ARTITELEPORT,
  697. TXT_ARTIPUZZSKULL,
  698. TXT_ARTIPUZZGEMBIG,
  699. TXT_ARTIPUZZGEMRED,
  700. TXT_ARTIPUZZGEMGREEN1,
  701. TXT_ARTIPUZZGEMGREEN2,
  702. TXT_ARTIPUZZGEMBLUE1,
  703. TXT_ARTIPUZZGEMBLUE2,
  704. TXT_ARTIPUZZBOOK1,
  705. TXT_ARTIPUZZBOOK2,
  706. TXT_ARTIPUZZSKULL2,
  707. TXT_ARTIPUZZFWEAPON,
  708. TXT_ARTIPUZZCWEAPON,
  709. TXT_ARTIPUZZMWEAPON,
  710. TXT_ARTIPUZZGEAR, // All gear pickups use the same text
  711. TXT_ARTIPUZZGEAR,
  712. TXT_ARTIPUZZGEAR,
  713. TXT_ARTIPUZZGEAR
  714. };
  715. if(P_GiveArtifact(player, artifactType, artifact))
  716. {
  717. if(artifact->special)
  718. {
  719. P_ExecuteLineSpecial(artifact->special, artifact->args,
  720. NULL, 0, NULL);
  721. artifact->special = 0;
  722. }
  723. player->bonuscount += BONUSADD;
  724. if(artifactType < arti_firstpuzzitem)
  725. {
  726. SetDormantArtifact(artifact);
  727. S_StartSound(artifact, SFX_PICKUP_ARTIFACT);
  728. P_SetMessage(player, artifactMessages[artifactType], false);
  729. }
  730. else
  731. { // Puzzle item
  732. S_StartSound(NULL, SFX_PICKUP_ITEM);
  733. P_SetMessage(player, artifactMessages[artifactType], true);
  734. if(!netgame || deathmatch)
  735. { // Remove puzzle items if not cooperative netplay
  736. P_RemoveMobj(artifact);
  737. }
  738. }
  739. }
  740. }
  741. //---------------------------------------------------------------------------
  742. //
  743. // FUNC P_GiveArtifact
  744. //
  745. // Returns true if artifact accepted.
  746. //
  747. //---------------------------------------------------------------------------
  748. boolean P_GiveArtifact(player_t *player, artitype_t arti, mobj_t *mo)
  749. {
  750. int i;
  751. int j;
  752. boolean slidePointer;
  753. slidePointer = false;
  754. i = 0;
  755. while(player->inventory[i].type != arti && i < player->inventorySlotNum)
  756. {
  757. i++;
  758. }
  759. if(i == player->inventorySlotNum)
  760. {
  761. if(arti < arti_firstpuzzitem)
  762. {
  763. i = 0;
  764. while(player->inventory[i].type < arti_firstpuzzitem
  765. && i < player->inventorySlotNum)
  766. {
  767. i++;
  768. }
  769. if(i != player->inventorySlotNum)
  770. {
  771. for(j = player->inventorySlotNum; j > i; j--)
  772. {
  773. player->inventory[j].count = player->inventory[j-1].count;
  774. player->inventory[j].type = player->inventory[j-1].type;
  775. slidePointer = true;
  776. }
  777. }
  778. }
  779. player->inventory[i].count = 1;
  780. player->inventory[i].type = arti;
  781. player->inventorySlotNum++;
  782. }
  783. else
  784. {
  785. if(arti >= arti_firstpuzzitem && netgame && !deathmatch)
  786. { // Can't carry more than 1 puzzle item in coop netplay
  787. return false;
  788. }
  789. if(player->inventory[i].count >= 25)
  790. { // Player already has 25 of this item
  791. return false;
  792. }
  793. player->inventory[i].count++;
  794. }
  795. if(!player->artifactCount)
  796. {
  797. player->readyArtifact = arti;
  798. }
  799. else if(player == &players[consoleplayer] && slidePointer
  800. && i <= inv_ptr)
  801. {
  802. inv_ptr++;
  803. curpos++;
  804. if(curpos > 6)
  805. {
  806. curpos = 6;
  807. }
  808. }
  809. player->artifactCount++;
  810. return(true);
  811. }
  812. //==========================================================================
  813. //
  814. // SetDormantArtifact
  815. //
  816. // Removes the MF_SPECIAL flag and initiates the artifact pickup
  817. // animation.
  818. //
  819. //==========================================================================
  820. static void SetDormantArtifact(mobj_t *arti)
  821. {
  822. arti->flags &= ~MF_SPECIAL;
  823. if(deathmatch && !(arti->flags2 & MF2_DROPPED))
  824. {
  825. if(arti->type == MT_ARTIINVULNERABILITY)
  826. {
  827. P_SetMobjState(arti, S_DORMANTARTI3_1);
  828. }
  829. else if(arti->type == MT_SUMMONMAULATOR
  830. || arti->type == MT_ARTIFLY)
  831. {
  832. P_SetMobjState(arti, S_DORMANTARTI2_1);
  833. }
  834. else
  835. {
  836. P_SetMobjState(arti, S_DORMANTARTI1_1);
  837. }
  838. }
  839. else
  840. { // Don't respawn
  841. P_SetMobjState(arti, S_DEADARTI1);
  842. }
  843. }
  844. //---------------------------------------------------------------------------
  845. //
  846. // PROC A_RestoreArtifact
  847. //
  848. //---------------------------------------------------------------------------
  849. void A_RestoreArtifact(mobj_t *arti)
  850. {
  851. arti->flags |= MF_SPECIAL;
  852. P_SetMobjState(arti, arti->info->spawnstate);
  853. S_StartSound(arti, SFX_RESPAWN);
  854. }
  855. //---------------------------------------------------------------------------
  856. //
  857. // PROC A_RestoreSpecialThing1
  858. //
  859. // Make a special thing visible again.
  860. //
  861. //---------------------------------------------------------------------------
  862. void A_RestoreSpecialThing1(mobj_t *thing)
  863. {
  864. thing->flags2 &= ~MF2_DONTDRAW;
  865. S_StartSound(thing, SFX_RESPAWN);
  866. }
  867. //---------------------------------------------------------------------------
  868. //
  869. // PROC A_RestoreSpecialThing2
  870. //
  871. //---------------------------------------------------------------------------
  872. void A_RestoreSpecialThing2(mobj_t *thing)
  873. {
  874. thing->flags |= MF_SPECIAL;
  875. P_SetMobjState(thing, thing->info->spawnstate);
  876. }
  877. //---------------------------------------------------------------------------
  878. //
  879. // PROC P_TouchSpecialThing
  880. //
  881. //---------------------------------------------------------------------------
  882. void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher)
  883. {
  884. player_t *player;
  885. fixed_t delta;
  886. int sound;
  887. boolean respawn;
  888. delta = special->z-toucher->z;
  889. if(delta > toucher->height || delta < -32*FRACUNIT)
  890. { // Out of reach
  891. return;
  892. }
  893. if(toucher->health <= 0)
  894. { // Toucher is dead
  895. return;
  896. }
  897. sound = SFX_PICKUP_ITEM;
  898. player = toucher->player;
  899. respawn = true;
  900. switch(special->sprite)
  901. {
  902. // Items
  903. case SPR_PTN1: // Item_HealingPotion
  904. if(!P_GiveBody(player, 10))
  905. {
  906. return;
  907. }
  908. P_SetMessage(player, TXT_ITEMHEALTH, false);
  909. break;
  910. case SPR_ARM1:
  911. if(!P_GiveArmor(player, ARMOR_ARMOR, -1))
  912. {
  913. return;
  914. }
  915. P_SetMessage(player, TXT_ARMOR1, false);
  916. break;
  917. case SPR_ARM2:
  918. if(!P_GiveArmor(player, ARMOR_SHIELD, -1))
  919. {
  920. return;
  921. }
  922. P_SetMessage(player, TXT_ARMOR2, false);
  923. break;
  924. case SPR_ARM3:
  925. if(!P_GiveArmor(player, ARMOR_HELMET, -1))
  926. {
  927. return;
  928. }
  929. P_SetMessage(player, TXT_ARMOR3, false);
  930. break;
  931. case SPR_ARM4:
  932. if(!P_GiveArmor(player, ARMOR_AMULET, -1))
  933. {
  934. return;
  935. }
  936. P_SetMessage(player, TXT_ARMOR4, false);
  937. break;
  938. // Keys
  939. case SPR_KEY1:
  940. case SPR_KEY2:
  941. case SPR_KEY3:
  942. case SPR_KEY4:
  943. case SPR_KEY5:
  944. case SPR_KEY6:
  945. case SPR_KEY7:
  946. case SPR_KEY8:
  947. case SPR_KEY9:
  948. case SPR_KEYA:
  949. case SPR_KEYB:
  950. if(!P_GiveKey(player, special->sprite-SPR_KEY1))
  951. {
  952. return;
  953. }
  954. P_SetMessage(player, TextKeyMessages[special->sprite-SPR_KEY1],
  955. true);
  956. sound = SFX_PICKUP_KEY;
  957. // Check and process the special now in case the key doesn't
  958. // get removed for coop netplay
  959. if(special->special)
  960. {
  961. P_ExecuteLineSpecial(special->special, special->args,
  962. NULL, 0, toucher);
  963. special->special = 0;
  964. }
  965. if(!netgame)
  966. { // Only remove keys in single player game
  967. break;
  968. }
  969. player->bonuscount += BONUSADD;
  970. if(player == &players[consoleplayer])
  971. {
  972. S_StartSound(NULL, sound);
  973. SB_PaletteFlash(false);
  974. }
  975. return;
  976. // Artifacts
  977. case SPR_PTN2:
  978. TryPickupArtifact(player, arti_health, special);
  979. return;
  980. case SPR_SOAR:
  981. TryPickupArtifact(player, arti_fly, special);
  982. return;
  983. case SPR_INVU:
  984. TryPickupArtifact(player, arti_invulnerability, special);
  985. return;
  986. case SPR_SUMN:
  987. TryPickupArtifact(player, arti_summon, special);
  988. return;
  989. case SPR_PORK:
  990. TryPickupArtifact(player, arti_egg, special);
  991. return;
  992. case SPR_SPHL:
  993. TryPickupArtifact(player, arti_superhealth, special);
  994. return;
  995. case SPR_HRAD:
  996. TryPickupArtifact(player, arti_healingradius, special);
  997. return;
  998. case SPR_TRCH:
  999. TryPickupArtifact(player, arti_torch, special);
  1000. return;
  1001. case SPR_ATLP:
  1002. TryPickupArtifact(player, arti_teleport, special);
  1003. return;
  1004. case SPR_TELO:
  1005. TryPickupArtifact(player, arti_teleportother, special);
  1006. return;
  1007. case SPR_PSBG:
  1008. TryPickupArtifact(player, arti_poisonbag, special);
  1009. return;
  1010. case SPR_SPED:
  1011. TryPickupArtifact(player, arti_speed, special);
  1012. return;
  1013. case SPR_BMAN:
  1014. TryPickupArtifact(player, arti_boostmana, special);
  1015. return;
  1016. case SPR_BRAC:
  1017. TryPickupArtifact(player, arti_boostarmor, special);
  1018. return;
  1019. case SPR_BLST:
  1020. TryPickupArtifact(player, arti_blastradius, special);
  1021. return;
  1022. // Puzzle artifacts
  1023. case SPR_ASKU:
  1024. TryPickupArtifact(player, arti_puzzskull, special);
  1025. return;
  1026. case SPR_ABGM:
  1027. TryPickupArtifact(player, arti_puzzgembig, special);
  1028. return;
  1029. case SPR_AGMR:
  1030. TryPickupArtifact(player, arti_puzzgemred, special);
  1031. return;
  1032. case SPR_AGMG:
  1033. TryPickupArtifact(player, arti_puzzgemgreen1, special);
  1034. return;
  1035. case SPR_AGG2:
  1036. TryPickupArtifact(player, arti_puzzgemgreen2, special);
  1037. return;
  1038. case SPR_AGMB:
  1039. TryPickupArtifact(player, arti_puzzgemblue1, special);
  1040. return;
  1041. case SPR_AGB2:
  1042. TryPickupArtifact(player, arti_puzzgemblue2, special);
  1043. return;
  1044. case SPR_ABK1:
  1045. TryPickupArtifact(player, arti_puzzbook1, special);
  1046. return;
  1047. case SPR_ABK2:
  1048. TryPickupArtifact(player, arti_puzzbook2, special);
  1049. return;
  1050. case SPR_ASK2:
  1051. TryPickupArtifact(player, arti_puzzskull2, special);
  1052. return;
  1053. case SPR_AFWP:
  1054. TryPickupArtifact(player, arti_puzzfweapon, special);
  1055. return;
  1056. case SPR_ACWP:
  1057. TryPickupArtifact(player, arti_puzzcweapon, special);
  1058. return;
  1059. case SPR_AMWP:
  1060. TryPickupArtifact(player, arti_puzzmweapon, special);
  1061. return;
  1062. case SPR_AGER:
  1063. TryPickupArtifact(player, arti_puzzgear1, special);
  1064. return;
  1065. case SPR_AGR2:
  1066. TryPickupArtifact(player, arti_puzzgear2, special);
  1067. return;
  1068. case SPR_AGR3:
  1069. TryPickupArtifact(player, arti_puzzgear3, special);
  1070. return;
  1071. case SPR_AGR4:
  1072. TryPickupArtifact(player, arti_puzzgear4, special);
  1073. return;
  1074. // Mana
  1075. case SPR_MAN1:
  1076. if(!P_GiveMana(player, MANA_1, 15))
  1077. {
  1078. return;
  1079. }
  1080. P_SetMessage(player, TXT_MANA_1, false);
  1081. break;
  1082. case SPR_MAN2:
  1083. if(!P_GiveMana(player, MANA_2, 15))
  1084. {
  1085. return;
  1086. }
  1087. P_SetMessage(player, TXT_MANA_2, false);
  1088. break;
  1089. case SPR_MAN3: // Double Mana Dodecahedron
  1090. if(!P_GiveMana(player, MANA_1, 20))
  1091. {
  1092. if(!P_GiveMana(player, MANA_2, 20))
  1093. {
  1094. return;
  1095. }
  1096. }
  1097. else
  1098. {
  1099. P_GiveMana(player, MANA_2, 20);
  1100. }
  1101. P_SetMessage(player, TXT_MANA_BOTH, false);
  1102. break;
  1103. // 2nd and 3rd Mage Weapons
  1104. case SPR_WMCS: // Frost Shards
  1105. TryPickupWeapon(player, PCLASS_MAGE, WP_SECOND,
  1106. special, TXT_WEAPON_M2);
  1107. return;
  1108. case SPR_WMLG: // Arc of Death
  1109. TryPickupWeapon(player, PCLASS_MAGE, WP_THIRD,
  1110. special, TXT_WEAPON_M3);
  1111. return;
  1112. // 2nd and 3rd Fighter Weapons
  1113. case SPR_WFAX: // Timon's Axe
  1114. TryPickupWeapon(player, PCLASS_FIGHTER, WP_SECOND,
  1115. special, TXT_WEAPON_F2);
  1116. return;
  1117. case SPR_WFHM: // Hammer of Retribution
  1118. TryPickupWeapon(player, PCLASS_FIGHTER, WP_THIRD,
  1119. special, TXT_WEAPON_F3);
  1120. return;
  1121. // 2nd and 3rd Cleric Weapons
  1122. case SPR_WCSS: // Serpent Staff
  1123. TryPickupWeapon(player, PCLASS_CLERIC, WP_SECOND,
  1124. special, TXT_WEAPON_C2);
  1125. return;
  1126. case SPR_WCFM: // Firestorm
  1127. TryPickupWeapon(player, PCLASS_CLERIC, WP_THIRD,
  1128. special, TXT_WEAPON_C3);
  1129. return;
  1130. // Fourth Weapon Pieces
  1131. case SPR_WFR1:
  1132. TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE1,
  1133. special);
  1134. return;
  1135. case SPR_WFR2:
  1136. TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE2,
  1137. special);
  1138. return;
  1139. case SPR_WFR3:
  1140. TryPickupWeaponPiece(player, PCLASS_FIGHTER, WPIECE3,
  1141. special);
  1142. return;
  1143. case SPR_WCH1:
  1144. TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE1,
  1145. special);
  1146. return;
  1147. case SPR_WCH2:
  1148. TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE2,
  1149. special);
  1150. return;
  1151. case SPR_WCH3:
  1152. TryPickupWeaponPiece(player, PCLASS_CLERIC, WPIECE3,
  1153. special);
  1154. return;
  1155. case SPR_WMS1:
  1156. TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE1,
  1157. special);
  1158. return;
  1159. case SPR_WMS2:
  1160. TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE2,
  1161. special);
  1162. return;
  1163. case SPR_WMS3:
  1164. TryPickupWeaponPiece(player, PCLASS_MAGE, WPIECE3,
  1165. special);
  1166. return;
  1167. default:
  1168. I_Error("P_SpecialThing: Unknown gettable thing");
  1169. }
  1170. if(special->special)
  1171. {
  1172. P_ExecuteLineSpecial(special->special, special->args, NULL,
  1173. 0, toucher);
  1174. special->special = 0;
  1175. }
  1176. if(deathmatch && respawn && !(special->flags2&MF2_DROPPED))
  1177. {
  1178. P_HideSpecialThing(special);
  1179. }
  1180. else
  1181. {
  1182. P_RemoveMobj(special);
  1183. }
  1184. player->bonuscount += BONUSADD;
  1185. if(player == &players[consoleplayer])
  1186. {
  1187. S_StartSound(NULL, sound);
  1188. SB_PaletteFlash(false);
  1189. }
  1190. }
  1191. // Search thinker list for minotaur
  1192. mobj_t *ActiveMinotaur(player_t *master)
  1193. {
  1194. mobj_t *mo;
  1195. player_t *plr;
  1196. thinker_t *think;
  1197. unsigned int *starttime;
  1198. for(think = thinkercap.next; think != &thinkercap; think = think->next)
  1199. {
  1200. if(think->function != P_MobjThinker) continue;
  1201. mo = (mobj_t *)think;
  1202. if(mo->type != MT_MINOTAUR) continue;
  1203. if(mo->health <= 0) continue;
  1204. if(!(mo->flags&MF_COUNTKILL)) continue; // for morphed minotaurs
  1205. if(mo->flags&MF_CORPSE) continue;
  1206. starttime = (unsigned int *)mo->args;
  1207. if ((leveltime - *starttime) >= MAULATORTICS) continue;
  1208. plr = ((mobj_t *)mo->special1)->player;
  1209. if(plr == master) return(mo);
  1210. }
  1211. return(NULL);
  1212. }
  1213. //---------------------------------------------------------------------------
  1214. //
  1215. // PROC P_KillMobj
  1216. //
  1217. //---------------------------------------------------------------------------
  1218. void P_KillMobj(mobj_t *source, mobj_t *target)
  1219. {
  1220. int dummy;
  1221. mobj_t *master;
  1222. target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY|MF_NOGRAVITY);
  1223. target->flags |= MF_CORPSE|MF_DROPOFF;
  1224. target->flags2 &= ~MF2_PASSMOBJ;
  1225. target->height >>= 2;
  1226. if((target->flags&MF_COUNTKILL || target->type == MT_ZBELL)
  1227. && target->special)
  1228. { // Initiate monster death actions
  1229. if(target->type == MT_SORCBOSS)
  1230. {
  1231. dummy = 0;
  1232. P_StartACS(target->special, 0, (byte *)&dummy, target,
  1233. NULL, 0);
  1234. }
  1235. else
  1236. {
  1237. P_ExecuteLineSpecial(target->special, target->args,
  1238. NULL, 0, target);
  1239. }
  1240. }
  1241. if(source && source->player)
  1242. { // Check for frag changes
  1243. if(target->player)
  1244. {
  1245. if(target == source)
  1246. { // Self-frag
  1247. target->player->frags[target->player-players]--;
  1248. if(cmdfrag && netgame
  1249. && source->player == &players[consoleplayer])
  1250. { // Send out a frag count packet
  1251. NET_SendFrags(source->player);
  1252. }
  1253. }
  1254. else
  1255. {
  1256. source->player->frags[target->player-players]++;
  1257. if(cmdfrag && netgame
  1258. && source->player == &players[consoleplayer])
  1259. { // Send out a frag count packet
  1260. NET_SendFrags(source->player);
  1261. }
  1262. }
  1263. }
  1264. }
  1265. if(target->player)
  1266. { // Player death
  1267. if(!source)
  1268. { // Self-frag
  1269. target->player->frags[target->player-players]--;
  1270. if(cmdfrag && netgame
  1271. && target->player == &players[consoleplayer])
  1272. { // Send out a frag count packet
  1273. NET_SendFrags(target->player);
  1274. }
  1275. }
  1276. target->flags &= ~MF_SOLID;
  1277. target->flags2 &= ~MF2_FLY;
  1278. target->player->powers[pw_flight] = 0;
  1279. target->player->playerstate = PST_DEAD;
  1280. P_DropWeapon(target->player);
  1281. if(target->flags2&MF2_FIREDAMAGE)
  1282. { // Player flame death
  1283. switch(target->player->class)
  1284. {
  1285. case PCLASS_FIGHTER:
  1286. S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
  1287. P_SetMobjState(target, S_PLAY_F_FDTH1);
  1288. return;
  1289. case PCLASS_CLERIC:
  1290. S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
  1291. P_SetMobjState(target, S_PLAY_C_FDTH1);
  1292. return;
  1293. case PCLASS_MAGE:
  1294. S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
  1295. P_SetMobjState(target, S_PLAY_M_FDTH1);
  1296. return;
  1297. default:
  1298. break;
  1299. }
  1300. }
  1301. if(target->flags2&MF2_ICEDAMAGE)
  1302. { // Player ice death
  1303. target->flags &= ~(7<<MF_TRANSSHIFT); //no translation
  1304. target->flags |= MF_ICECORPSE;
  1305. switch(target->player->class)
  1306. {
  1307. case PCLASS_FIGHTER:
  1308. P_SetMobjState(target, S_FPLAY_ICE);
  1309. return;
  1310. case PCLASS_CLERIC:
  1311. P_SetMobjState(target, S_CPLAY_ICE);
  1312. return;
  1313. case PCLASS_MAGE:
  1314. P_SetMobjState(target, S_MPLAY_ICE);
  1315. return;
  1316. case PCLASS_PIG:
  1317. P_SetMobjState(target, S_PIG_ICE);
  1318. return;
  1319. default:
  1320. break;
  1321. }
  1322. }
  1323. }
  1324. if(target->flags2&MF2_FIREDAMAGE)
  1325. {
  1326. if(target->type == MT_FIGHTER_BOSS
  1327. || target->type == MT_CLERIC_BOSS
  1328. || target->type == MT_MAGE_BOSS)
  1329. {
  1330. switch(target->type)
  1331. {
  1332. case MT_FIGHTER_BOSS:
  1333. S_StartSound(target, SFX_PLAYER_FIGHTER_BURN_DEATH);
  1334. P_SetMobjState(target, S_PLAY_F_FDTH1);
  1335. return;
  1336. case MT_CLERIC_BOSS:
  1337. S_StartSound(target, SFX_PLAYER_CLERIC_BURN_DEATH);
  1338. P_SetMobjState(target, S_PLAY_C_FDTH1);
  1339. return;
  1340. case MT_MAGE_BOSS:
  1341. S_StartSound(target, SFX_PLAYER_MAGE_BURN_DEATH);
  1342. P_SetMobjState(target, S_PLAY_M_FDTH1);
  1343. return;
  1344. default:
  1345. break;
  1346. }
  1347. }
  1348. else if(target->type == MT_TREEDESTRUCTIBLE)
  1349. {
  1350. P_SetMobjState(target, S_ZTREEDES_X1);
  1351. target->height = 24*FRACUNIT;
  1352. S_StartSound(target, SFX_TREE_EXPLODE);
  1353. return;
  1354. }
  1355. }
  1356. if(target->flags2&MF2_ICEDAMAGE)
  1357. {
  1358. target->flags |= MF_ICECORPSE;
  1359. switch(target->type)
  1360. {
  1361. case MT_BISHOP:
  1362. P_SetMobjState(target, S_BISHOP_ICE);
  1363. return;
  1364. case MT_CENTAUR:
  1365. case MT_CENTAURLEADER:
  1366. P_SetMobjState(target, S_CENTAUR_ICE);
  1367. return;
  1368. case MT_DEMON:
  1369. case MT_DEMON2:
  1370. P_SetMobjState(target, S_DEMON_ICE);
  1371. return;
  1372. case MT_SERPENT:
  1373. case MT_SERPENTLEADER:
  1374. P_SetMobjState(target, S_SERPENT_ICE);
  1375. return;
  1376. case MT_WRAITH:
  1377. case MT_WRAITHB:
  1378. P_SetMobjState(target, S_WRAITH_ICE);
  1379. return;
  1380. case MT_ETTIN:
  1381. P_SetMobjState(target, S_ETTIN_ICE1);
  1382. return;
  1383. case MT_FIREDEMON:
  1384. P_SetMobjState(target, S_FIRED_ICE1);
  1385. return;
  1386. case MT_FIGHTER_BOSS:
  1387. P_SetMobjState(target, S_FIGHTER_ICE);
  1388. return;
  1389. case MT_CLERIC_BOSS:
  1390. P_SetMobjState(target, S_CLERIC_ICE);
  1391. return;
  1392. case MT_MAGE_BOSS:
  1393. P_SetMobjState(target, S_MAGE_ICE);
  1394. return;
  1395. case MT_PIG:
  1396. P_SetMobjState(target, S_PIG_ICE);
  1397. return;
  1398. default:
  1399. target->flags &= ~MF_ICECORPSE;
  1400. break;
  1401. }
  1402. }
  1403. if(target->type == MT_MINOTAUR)
  1404. {
  1405. master = (mobj_t *)target->special1;
  1406. if(master->health > 0)
  1407. {
  1408. if (!ActiveMinotaur(master->player))
  1409. {
  1410. master->player->powers[pw_minotaur] = 0;
  1411. }
  1412. }
  1413. }
  1414. else if(target->type == MT_TREEDESTRUCTIBLE)
  1415. {
  1416. target->height = 24*FRACUNIT;
  1417. }
  1418. if(target->health < -(target->info->spawnhealth>>1)
  1419. && target->info->xdeathstate)
  1420. { // Extreme death
  1421. P_SetMobjState(target, target->info->xdeathstate);
  1422. }
  1423. else
  1424. { // Normal death
  1425. if ((target->type==MT_FIREDEMON) &&
  1426. (target->z <= target->floorz + 2*FRACUNIT) &&
  1427. (target->info->xdeathstate))
  1428. {
  1429. // This is to fix the imps' staying in fall state
  1430. P_SetMobjState(target, target->info->xdeathstate);
  1431. }
  1432. else
  1433. {
  1434. P_SetMobjState(target, target->info->deathstate);
  1435. }
  1436. }
  1437. target->tics -= P_Random()&3;
  1438. // I_StartSound(&actor->r, actor->info->deathsound);
  1439. }
  1440. //---------------------------------------------------------------------------
  1441. //
  1442. // FUNC P_MinotaurSlam
  1443. //
  1444. //---------------------------------------------------------------------------
  1445. void P_MinotaurSlam(mobj_t *source, mobj_t *target)
  1446. {
  1447. angle_t angle;
  1448. fixed_t thrust;
  1449. angle = R_PointToAngle2(source->x, source->y, target->x, target->y);
  1450. angle >>= ANGLETOFINESHIFT;
  1451. thrust = 16*FRACUNIT+(P_Random()<<10);
  1452. target->momx += FixedMul(thrust, finecosine[angle]);
  1453. target->momy += FixedMul(thrust, finesine[angle]);
  1454. P_DamageMobj(target, NULL, source, HITDICE(4));
  1455. if(target->player)
  1456. {
  1457. target->reactiontime = 14+(P_Random()&7);
  1458. }
  1459. source->args[0] = 0; // Stop charging
  1460. }
  1461. //---------------------------------------------------------------------------
  1462. //
  1463. // FUNC P_MorphPlayer
  1464. //
  1465. // Returns true if the player gets turned into a pig
  1466. //
  1467. //---------------------------------------------------------------------------
  1468. boolean P_MorphPlayer(player_t *player)
  1469. {
  1470. mobj_t *pmo;
  1471. mobj_t *fog;
  1472. mobj_t *beastMo;
  1473. fixed_t x;
  1474. fixed_t y;
  1475. fixed_t z;
  1476. angle_t angle;
  1477. int oldFlags2;
  1478. if(player->powers[pw_invulnerability])
  1479. { // Immune when invulnerable
  1480. return(false);
  1481. }
  1482. if(player->morphTics)
  1483. { // Player is already a beast
  1484. return false;
  1485. }
  1486. pmo = player->mo;
  1487. x = pmo->x;
  1488. y = pmo->y;
  1489. z = pmo->z;
  1490. angle = pmo->angle;
  1491. oldFlags2 = pmo->flags2;
  1492. P_SetMobjState(pmo, S_FREETARGMOBJ);
  1493. fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
  1494. S_StartSound(fog, SFX_TELEPORT);
  1495. beastMo = P_SpawnMobj(x, y, z, MT_PIGPLAYER);
  1496. beastMo->special1 = player->readyweapon;
  1497. beastMo->angle = angle;
  1498. beastMo->player = player;
  1499. player->health = beastMo->health = MAXMORPHHEALTH;
  1500. player->mo = beastMo;
  1501. memset(&player->armorpoints[0], 0, NUMARMOR*sizeof(int));
  1502. player->class = PCLASS_PIG;
  1503. if(oldFlags2&MF2_FLY)
  1504. {
  1505. beastMo->flags2 |= MF2_FLY;
  1506. }
  1507. player->morphTics = MORPHTICS;
  1508. P_ActivateMorphWeapon(player);
  1509. return(true);
  1510. }
  1511. //---------------------------------------------------------------------------
  1512. //
  1513. // FUNC P_MorphMonster
  1514. //
  1515. //---------------------------------------------------------------------------
  1516. boolean P_MorphMonster(mobj_t *actor)
  1517. {
  1518. mobj_t *master, *monster, *fog;
  1519. mobjtype_t moType;
  1520. fixed_t x;
  1521. fixed_t y;
  1522. fixed_t z;
  1523. mobj_t oldMonster;
  1524. if(actor->player) return(false);
  1525. if(!(actor->flags&MF_COUNTKILL)) return false;
  1526. if(actor->flags2&MF2_BOSS) return false;
  1527. moType = actor->type;
  1528. switch(moType)
  1529. {
  1530. case MT_PIG:
  1531. return(false);
  1532. case MT_FIGHTER_BOSS:
  1533. case MT_CLERIC_BOSS:
  1534. case MT_MAGE_BOSS:
  1535. return(false);
  1536. default:
  1537. break;
  1538. }
  1539. oldMonster = *actor;
  1540. x = oldMonster.x;
  1541. y = oldMonster.y;
  1542. z = oldMonster.z;
  1543. P_RemoveMobjFromTIDList(actor);
  1544. P_SetMobjState(actor, S_FREETARGMOBJ);
  1545. fog = P_SpawnMobj(x, y, z+TELEFOGHEIGHT, MT_TFOG);
  1546. S_StartSound(fog, SFX_TELEPORT);
  1547. monster = P_SpawnMobj(x, y, z, MT_PIG);
  1548. monster->special2 = moType;
  1549. monster->special1 = MORPHTICS+P_Random();
  1550. monster->flags |= (oldMonster.flags&MF_SHADOW);
  1551. monster->target = oldMonster.target;
  1552. monster->angle = oldMonster.angle;
  1553. monster->tid = oldMonster.tid;
  1554. monster->special = oldMonster.special;
  1555. P_InsertMobjIntoTIDList(monster, oldMonster.tid);
  1556. memcpy(monster->args, oldMonster.args, 5);
  1557. // check for turning off minotaur power for active icon
  1558. if (moType==MT_MINOTAUR)
  1559. {
  1560. master = (mobj_t *)oldMonster.special1;
  1561. if(master->health > 0)
  1562. {
  1563. if (!ActiveMinotaur(master->player))
  1564. {
  1565. master->player->powers[pw_minotaur] = 0;
  1566. }
  1567. }
  1568. }
  1569. return(true);
  1570. }
  1571. //---------------------------------------------------------------------------
  1572. //
  1573. // PROC P_AutoUseHealth
  1574. //
  1575. //---------------------------------------------------------------------------
  1576. void P_AutoUseHealth(player_t *player, int saveHealth)
  1577. {
  1578. int i;
  1579. int count;
  1580. int normalCount;
  1581. int normalSlot=0;
  1582. int superCount;
  1583. int superSlot=0;
  1584. normalCount = superCount = 0;
  1585. for(i = 0; i < player->inventorySlotNum; i++)
  1586. {
  1587. if(player->inventory[i].type == arti_health)
  1588. {
  1589. normalSlot = i;
  1590. normalCount = player->inventory[i].count;
  1591. }
  1592. else if(player->inventory[i].type == arti_superhealth)
  1593. {
  1594. superSlot = i;
  1595. superCount = player->inventory[i].count;
  1596. }
  1597. }
  1598. if((gameskill == sk_baby) && (normalCount*25 >= saveHealth))
  1599. { // Use quartz flasks
  1600. count = (saveHealth+24)/25;
  1601. for(i = 0; i < count; i++)
  1602. {
  1603. player->health += 25;
  1604. P_PlayerRemoveArtifact(player, normalSlot);
  1605. }
  1606. }
  1607. else if(superCount*100 >= saveHealth)
  1608. { // Use mystic urns
  1609. count = (saveHealth+99)/100;
  1610. for(i = 0; i < count; i++)
  1611. {
  1612. player->health += 100;
  1613. P_PlayerRemoveArtifact(player, superSlot);
  1614. }
  1615. }
  1616. else if((gameskill == sk_baby)
  1617. && (superCount*100+normalCount*25 >= saveHealth))
  1618. { // Use mystic urns and quartz flasks
  1619. count = (saveHealth+24)/25;
  1620. saveHealth -= count*25;
  1621. for(i = 0; i < count; i++)
  1622. {
  1623. player->health += 25;
  1624. P_PlayerRemoveArtifact(player, normalSlot);
  1625. }
  1626. count = (saveHealth+99)/100;
  1627. for(i = 0; i < count; i++)
  1628. {
  1629. player->health += 100;
  1630. P_PlayerRemoveArtifact(player, normalSlot);
  1631. }
  1632. }
  1633. player->mo->health = player->health;
  1634. }
  1635. /*
  1636. =================
  1637. =
  1638. = P_DamageMobj
  1639. =
  1640. = Damages both enemies and players
  1641. = inflictor is the thing that caused the damage
  1642. = creature or missile, can be NULL (slime, etc)
  1643. = source is the thing to target after taking damage
  1644. = creature or NULL
  1645. = Source and inflictor are the same for melee attacks
  1646. = source can be null for barrel explosions and other environmental stuff
  1647. ==================
  1648. */
  1649. void P_DamageMobj
  1650. (
  1651. mobj_t *target,
  1652. mobj_t *inflictor,
  1653. mobj_t *source,
  1654. int damage
  1655. )
  1656. {
  1657. unsigned ang;
  1658. int saved;
  1659. fixed_t savedPercent;
  1660. player_t *player;
  1661. mobj_t *master;
  1662. fixed_t thrust;
  1663. int temp;
  1664. int i;
  1665. if(!(target->flags&MF_SHOOTABLE))
  1666. {
  1667. // Shouldn't happen
  1668. return;
  1669. }
  1670. if(target->health <= 0)
  1671. {
  1672. if (inflictor && inflictor->flags2&MF2_ICEDAMAGE)
  1673. {
  1674. return;
  1675. }
  1676. else if (target->flags&MF_ICECORPSE) // frozen
  1677. {
  1678. target->tics = 1;
  1679. target->momx = target->momy = 0;
  1680. }
  1681. return;
  1682. }
  1683. if ((target->flags2&MF2_INVULNERABLE) && damage < 10000)
  1684. { // mobj is invulnerable
  1685. if(target->player) return; // for player, no exceptions
  1686. if(inflictor)
  1687. {
  1688. switch(inflictor->type)
  1689. {
  1690. // These inflictors aren't foiled by invulnerability
  1691. case MT_HOLY_FX:
  1692. case MT_POISONCLOUD:
  1693. case MT_FIREBOMB:
  1694. break;
  1695. default:
  1696. return;
  1697. }
  1698. }
  1699. else
  1700. {
  1701. return;
  1702. }
  1703. }
  1704. if(target->player)
  1705. {
  1706. if(damage < 1000 && ((target->player->cheats&CF_GODMODE)
  1707. || target->player->powers[pw_invulnerability]))
  1708. {
  1709. return;
  1710. }
  1711. }
  1712. if(target->flags&MF_SKULLFLY)
  1713. {
  1714. target->momx = target->momy = target->momz = 0;
  1715. }
  1716. if(target->flags2&MF2_DORMANT)
  1717. {
  1718. // Invulnerable, and won't wake up
  1719. return;
  1720. }
  1721. player = target->player;
  1722. if(player && gameskill == sk_baby)
  1723. {
  1724. // Take half damage in trainer mode
  1725. damage >>= 1;
  1726. }
  1727. // Special damage types
  1728. if(inflictor)
  1729. {
  1730. switch(inflictor->type)
  1731. {
  1732. case MT_EGGFX:
  1733. if(player)
  1734. {
  1735. P_MorphPlayer(player);
  1736. }
  1737. else
  1738. {
  1739. P_MorphMonster(target);
  1740. }
  1741. return; // Always return
  1742. case MT_TELOTHER_FX1:
  1743. case MT_TELOTHER_FX2:
  1744. case MT_TELOTHER_FX3:
  1745. case MT_TELOTHER_FX4:
  1746. case MT_TELOTHER_FX5:
  1747. if ((target->flags&MF_COUNTKILL) &&
  1748. (target->type != MT_SERPENT) &&
  1749. (target->type != MT_SERPENTLEADER) &&
  1750. (!(target->flags2 & MF2_BOSS)))
  1751. {
  1752. P_TeleportOther(target);
  1753. }
  1754. return;
  1755. case MT_MINOTAUR:
  1756. if(inflictor->flags&MF_SKULLFLY)
  1757. { // Slam only when in charge mode
  1758. P_MinotaurSlam(inflictor, target);
  1759. return;
  1760. }
  1761. break;
  1762. case MT_BISH_FX:
  1763. // Bishops are just too nasty
  1764. damage >>= 1;
  1765. break;
  1766. case MT_SHARDFX1:
  1767. switch(inflictor->special2)
  1768. {
  1769. case 3:
  1770. damage <<= 3;
  1771. break;
  1772. case 2:
  1773. damage <<= 2;
  1774. break;
  1775. case 1:
  1776. damage <<= 1;
  1777. break;
  1778. default:
  1779. break;
  1780. }
  1781. break;
  1782. case MT_CSTAFF_MISSILE:
  1783. // Cleric Serpent Staff does poison damage
  1784. if(target->player)
  1785. {
  1786. P_PoisonPlayer(target->player, source, 20);
  1787. damage >>= 1;
  1788. }
  1789. break;
  1790. case MT_ICEGUY_FX2:
  1791. damage >>= 1;
  1792. break;
  1793. case MT_POISONDART:
  1794. if(target->player)
  1795. {
  1796. P_PoisonPlayer(target->player, source, 20);
  1797. damage >>= 1;
  1798. }
  1799. break;
  1800. case MT_POISONCLOUD:
  1801. if(target->player)
  1802. {
  1803. if(target->player->poisoncount < 4)
  1804. {
  1805. P_PoisonDamage(target->player, source,
  1806. 15+(P_Random()&15), false); // Don't play painsound
  1807. P_PoisonPlayer(target->player, source, 50);
  1808. S_StartSound(target, SFX_PLAYER_POISONCOUGH);
  1809. }
  1810. return;
  1811. }
  1812. else if(!(target->flags&MF_COUNTKILL))
  1813. { // only damage monsters/players with the poison cloud
  1814. return;
  1815. }
  1816. break;
  1817. case MT_FSWORD_MISSILE:
  1818. if(target->player)
  1819. {
  1820. damage -= damage>>2;
  1821. }
  1822. break;
  1823. default:
  1824. break;
  1825. }
  1826. }
  1827. // Push the target unless source is using the gauntlets
  1828. if(inflictor && (!source || !source->player)
  1829. && !(inflictor->flags2&MF2_NODMGTHRUST))
  1830. {
  1831. ang = R_PointToAngle2(inflictor->x, inflictor->y,
  1832. target->x, target->y);
  1833. //thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
  1834. thrust = damage*(FRACUNIT>>3)*150/target->info->mass;
  1835. // make fall forwards sometimes
  1836. if((damage < 40) && (damage > target->health)
  1837. && (target->z-inflictor->z > 64*FRACUNIT) && (P_Random()&1))
  1838. {
  1839. ang += ANG180;
  1840. thrust *= 4;
  1841. }
  1842. ang >>= ANGLETOFINESHIFT;
  1843. target->momx += FixedMul(thrust, finecosine[ang]);
  1844. target->momy += FixedMul(thrust, finesine[ang]);
  1845. }
  1846. //
  1847. // player specific
  1848. //
  1849. if(player)
  1850. {
  1851. savedPercent = AutoArmorSave[player->class]
  1852. +player->armorpoints[ARMOR_ARMOR]+player->armorpoints[ARMOR_SHIELD]
  1853. +player->armorpoints[ARMOR_HELMET]
  1854. +player->armorpoints[ARMOR_AMULET];
  1855. if(savedPercent)
  1856. { // armor absorbed some damage
  1857. if(savedPercent > 100*FRACUNIT)
  1858. {
  1859. savedPercent = 100*FRACUNIT;
  1860. }
  1861. for(i = 0; i < NUMARMOR; i++)
  1862. {
  1863. if(player->armorpoints[i])
  1864. {
  1865. player->armorpoints[i] -=
  1866. FixedDiv(FixedMul(damage<<FRACBITS,
  1867. ArmorIncrement[player->class][i]), 300*FRACUNIT);
  1868. if(player->armorpoints[i] < 2*FRACUNIT)
  1869. {
  1870. player->armorpoints[i] = 0;
  1871. }
  1872. }
  1873. }
  1874. saved = FixedDiv(FixedMul(damage<<FRACBITS, savedPercent),
  1875. 100*FRACUNIT);
  1876. if(saved > savedPercent*2)
  1877. {
  1878. saved = savedPercent*2;
  1879. }
  1880. damage -= saved>>FRACBITS;
  1881. }
  1882. if(damage >= player->health
  1883. && ((gameskill == sk_baby) || deathmatch)
  1884. && !player->morphTics)
  1885. { // Try to use some inventory health
  1886. P_AutoUseHealth(player, damage-player->health+1);
  1887. }
  1888. player->health -= damage; // mirror mobj health here for Dave
  1889. if(player->health < 0)
  1890. {
  1891. player->health = 0;
  1892. }
  1893. player->attacker = source;
  1894. player->damagecount += damage; // add damage after armor / invuln
  1895. if(player->damagecount > 100)
  1896. {
  1897. player->damagecount = 100; // teleport stomp does 10k points...
  1898. }
  1899. temp = damage < 100 ? damage : 100;
  1900. if(player == &players[consoleplayer])
  1901. {
  1902. I_Tactile(40, 10, 40+temp*2);
  1903. SB_PaletteFlash(false);
  1904. }
  1905. }
  1906. //
  1907. // do the damage
  1908. //
  1909. target->health -= damage;
  1910. if(target->health <= 0)
  1911. { // Death
  1912. if(inflictor)
  1913. { // check for special fire damage or ice damage deaths
  1914. if(inflictor->flags2&MF2_FIREDAMAGE)
  1915. {
  1916. if(player && !player->morphTics)
  1917. { // Check for flame death
  1918. if(target->health > -50 && damage > 25)
  1919. {
  1920. target->flags2 |= MF2_FIREDAMAGE;
  1921. }
  1922. }
  1923. else
  1924. {
  1925. target->flags2 |= MF2_FIREDAMAGE;
  1926. }
  1927. }
  1928. else if(inflictor->flags2&MF2_ICEDAMAGE)
  1929. {
  1930. target->flags2 |= MF2_ICEDAMAGE;
  1931. }
  1932. }
  1933. if(source && (source->type == MT_MINOTAUR))
  1934. { // Minotaur's kills go to his master
  1935. master = (mobj_t *)(source->special1);
  1936. // Make sure still alive and not a pointer to fighter head
  1937. if (master->player && (master->player->mo == master))
  1938. {
  1939. source = master;
  1940. }
  1941. }
  1942. if(source && (source->player) &&
  1943. (source->player->readyweapon == WP_FOURTH))
  1944. {
  1945. // Always extreme death from fourth weapon
  1946. target->health = -5000;
  1947. }
  1948. P_KillMobj(source, target);
  1949. return;
  1950. }
  1951. if((P_Random() < target->info->painchance)
  1952. && !(target->flags&MF_SKULLFLY))
  1953. {
  1954. if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR
  1955. && inflictor->type <= MT_LIGHTNING_ZAP))
  1956. {
  1957. if(P_Random() < 96)
  1958. {
  1959. target->flags |= MF_JUSTHIT; // fight back!
  1960. P_SetMobjState(target, target->info->painstate);
  1961. }
  1962. else
  1963. { // "electrocute" the target
  1964. target->frame |= FF_FULLBRIGHT;
  1965. if(target->flags&MF_COUNTKILL && P_Random() < 128
  1966. && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
  1967. {
  1968. if ((target->type == MT_CENTAUR) ||
  1969. (target->type == MT_CENTAURLEADER) ||
  1970. (target->type == MT_ETTIN))
  1971. {
  1972. S_StartSound(target, SFX_PUPPYBEAT);
  1973. }
  1974. }
  1975. }
  1976. }
  1977. else
  1978. {
  1979. target->flags |= MF_JUSTHIT; // fight back!
  1980. P_SetMobjState(target, target->info->painstate);
  1981. if(inflictor && inflictor->type == MT_POISONCLOUD)
  1982. {
  1983. if(target->flags&MF_COUNTKILL && P_Random() < 128
  1984. && !S_GetSoundPlayingInfo(target, SFX_PUPPYBEAT))
  1985. {
  1986. if ((target->type == MT_CENTAUR) ||
  1987. (target->type == MT_CENTAURLEADER) ||
  1988. (target->type == MT_ETTIN))
  1989. {
  1990. S_StartSound(target, SFX_PUPPYBEAT);
  1991. }
  1992. }
  1993. }
  1994. }
  1995. }
  1996. target->reactiontime = 0; // we're awake now...
  1997. if(!target->threshold && source && !(source->flags2&MF2_BOSS)
  1998. && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR))
  1999. {
  2000. // Target actor is not intent on another actor,
  2001. // so make him chase after source
  2002. if((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER)
  2003. || (target->type == MT_CENTAURLEADER
  2004. && source->type == MT_CENTAUR))
  2005. {
  2006. return;
  2007. }
  2008. target->target = source;
  2009. target->threshold = BASETHRESHOLD;
  2010. if(target->state == &states[target->info->spawnstate]
  2011. && target->info->seestate != S_NULL)
  2012. {
  2013. P_SetMobjState(target, target->info->seestate);
  2014. }
  2015. }
  2016. }
  2017. //==========================================================================
  2018. //
  2019. // P_FallingDamage
  2020. //
  2021. //==========================================================================
  2022. void P_FallingDamage(player_t *player)
  2023. {
  2024. int damage;
  2025. int mom;
  2026. int dist;
  2027. mom = abs(player->mo->momz);
  2028. dist = FixedMul(mom, 16*FRACUNIT/23);
  2029. if(mom >= 63*FRACUNIT)
  2030. { // automatic death
  2031. P_DamageMobj(player->mo, NULL, NULL, 10000);
  2032. return;
  2033. }
  2034. damage = ((FixedMul(dist, dist)/10)>>FRACBITS)-24;
  2035. if(player->mo->momz > -39*FRACUNIT && damage > player->mo->health
  2036. && player->mo->health != 1)
  2037. { // No-death threshold
  2038. damage = player->mo->health-1;
  2039. }
  2040. S_StartSound(player->mo, SFX_PLAYER_LAND);
  2041. P_DamageMobj(player->mo, NULL, NULL, damage);
  2042. }
  2043. //==========================================================================
  2044. //
  2045. // P_PoisonPlayer - Sets up all data concerning poisoning
  2046. //
  2047. //==========================================================================
  2048. void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison)
  2049. {
  2050. if((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability])
  2051. {
  2052. return;
  2053. }
  2054. player->poisoncount += poison;
  2055. player->poisoner = poisoner;
  2056. if(player->poisoncount > 100)
  2057. {
  2058. player->poisoncount = 100;
  2059. }
  2060. }
  2061. //==========================================================================
  2062. //
  2063. // P_PoisonDamage - Similar to P_DamageMobj
  2064. //
  2065. //==========================================================================
  2066. void P_PoisonDamage(player_t *player, mobj_t *source, int damage,
  2067. boolean playPainSound)
  2068. {
  2069. mobj_t *target;
  2070. mobj_t *inflictor;
  2071. target = player->mo;
  2072. inflictor = source;
  2073. if(target->health <= 0)
  2074. {
  2075. return;
  2076. }
  2077. if(target->flags2&MF2_INVULNERABLE && damage < 10000)
  2078. { // mobj is invulnerable
  2079. return;
  2080. }
  2081. if(player && gameskill == sk_baby)
  2082. {
  2083. // Take half damage in trainer mode
  2084. damage >>= 1;
  2085. }
  2086. if(damage < 1000 && ((player->cheats&CF_GODMODE)
  2087. || player->powers[pw_invulnerability]))
  2088. {
  2089. return;
  2090. }
  2091. if(damage >= player->health
  2092. && ((gameskill == sk_baby) || deathmatch)
  2093. && !player->morphTics)
  2094. { // Try to use some inventory health
  2095. P_AutoUseHealth(player, damage-player->health+1);
  2096. }
  2097. player->health -= damage; // mirror mobj health here for Dave
  2098. if(player->health < 0)
  2099. {
  2100. player->health = 0;
  2101. }
  2102. player->attacker = source;
  2103. //
  2104. // do the damage
  2105. //
  2106. target->health -= damage;
  2107. if(target->health <= 0)
  2108. { // Death
  2109. target->special1 = damage;
  2110. if(player && inflictor && !player->morphTics)
  2111. { // Check for flame death
  2112. if((inflictor->flags2&MF2_FIREDAMAGE)
  2113. && (target->health > -50) && (damage > 25))
  2114. {
  2115. target->flags2 |= MF2_FIREDAMAGE;
  2116. }
  2117. if(inflictor->flags2&MF2_ICEDAMAGE)
  2118. {
  2119. target->flags2 |= MF2_ICEDAMAGE;
  2120. }
  2121. }
  2122. P_KillMobj(source, target);
  2123. return;
  2124. }
  2125. if(!(leveltime&63) && playPainSound)
  2126. {
  2127. P_SetMobjState(target, target->info->painstate);
  2128. }
  2129. /*
  2130. if((P_Random() < target->info->painchance)
  2131. && !(target->flags&MF_SKULLFLY))
  2132. {
  2133. target->flags |= MF_JUSTHIT; // fight back!
  2134. P_SetMobjState(target, target->info->painstate);
  2135. }
  2136. */
  2137. }