p_inter.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "Precompiled.h"
  21. #include "globaldata.h"
  22. // Data.
  23. #include "doomdef.h"
  24. #include "dstrings.h"
  25. #include "sounds.h"
  26. #include "doomstat.h"
  27. #include "m_random.h"
  28. #include "i_system.h"
  29. #include "am_map.h"
  30. #include "p_local.h"
  31. #include "s_sound.h"
  32. #ifdef __GNUG__
  33. #pragma implementation "p_inter.h"
  34. #endif
  35. #include "p_inter.h"
  36. #include "Main.h"
  37. #include "sys/sys_signin.h"
  38. #include "../../neo/d3xp/Game_Local.h"
  39. // a weapon is found with two clip loads,
  40. // a big item has five clip loads
  41. const int maxammo[NUMAMMO] = {200, 50, 300, 50};
  42. const int clipammo[NUMAMMO] = {10, 4, 20, 1};
  43. //
  44. // GET STUFF
  45. //
  46. //
  47. // P_GiveAmmo
  48. // Num is the number of clip loads,
  49. // not the individual count (0= 1/2 clip).
  50. // Returns false if the ammo can't be picked up at all
  51. //
  52. qboolean
  53. P_GiveAmmo
  54. ( player_t* player,
  55. ammotype_t ammo,
  56. int num )
  57. {
  58. int oldammo;
  59. if (ammo == am_noammo)
  60. return false;
  61. if (ammo < 0 || ammo > NUMAMMO)
  62. I_Error ("P_GiveAmmo: bad type %i", ammo);
  63. if ( player->ammo[ammo] == player->maxammo[ammo] )
  64. return false;
  65. if (num)
  66. num *= clipammo[ammo];
  67. else
  68. num = clipammo[ammo]/2;
  69. if (::g->gameskill == sk_baby
  70. || ::g->gameskill == sk_nightmare)
  71. {
  72. // give double ammo in trainer mode,
  73. // you'll need in nightmare
  74. num <<= 1;
  75. }
  76. oldammo = player->ammo[ammo];
  77. player->ammo[ammo] += num;
  78. if (player->ammo[ammo] > player->maxammo[ammo])
  79. player->ammo[ammo] = player->maxammo[ammo];
  80. // If non zero ammo,
  81. // don't change up weapons,
  82. // player was lower on purpose.
  83. if (oldammo)
  84. return true;
  85. // We were down to zero,
  86. // so select a new weapon.
  87. // Preferences are not user selectable.
  88. switch (ammo)
  89. {
  90. case am_clip:
  91. if (player->readyweapon == wp_fist)
  92. {
  93. if (player->weaponowned[wp_chaingun])
  94. player->pendingweapon = wp_chaingun;
  95. else
  96. player->pendingweapon = wp_pistol;
  97. }
  98. break;
  99. case am_shell:
  100. if (player->readyweapon == wp_fist
  101. || player->readyweapon == wp_pistol)
  102. {
  103. if (player->weaponowned[wp_shotgun])
  104. player->pendingweapon = wp_shotgun;
  105. }
  106. break;
  107. case am_cell:
  108. if (player->readyweapon == wp_fist
  109. || player->readyweapon == wp_pistol)
  110. {
  111. if (player->weaponowned[wp_plasma])
  112. player->pendingweapon = wp_plasma;
  113. }
  114. break;
  115. case am_misl:
  116. if (player->readyweapon == wp_fist)
  117. {
  118. if (player->weaponowned[wp_missile])
  119. player->pendingweapon = wp_missile;
  120. }
  121. default:
  122. break;
  123. }
  124. return true;
  125. }
  126. //
  127. // P_GiveWeapon
  128. // The weapon name may have a MF_DROPPED flag ored in.
  129. //
  130. qboolean
  131. P_GiveWeapon
  132. ( player_t* player,
  133. weapontype_t weapon,
  134. qboolean dropped )
  135. {
  136. qboolean gaveammo;
  137. qboolean gaveweapon;
  138. if (::g->netgame
  139. && (::g->deathmatch!=2)
  140. && !dropped )
  141. {
  142. // leave placed weapons forever on net games
  143. if (player->weaponowned[weapon])
  144. return false;
  145. player->bonuscount += BONUSADD;
  146. player->weaponowned[weapon] = true;
  147. if (::g->deathmatch)
  148. P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
  149. else
  150. P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
  151. player->pendingweapon = weapon;
  152. if (player == &::g->players[::g->consoleplayer])
  153. S_StartSound (player->mo, sfx_wpnup);
  154. return false;
  155. }
  156. if (weaponinfo[weapon].ammo != am_noammo)
  157. {
  158. // give one clip with a dropped weapon,
  159. // two clips with a found weapon
  160. if (dropped)
  161. gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
  162. else
  163. gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
  164. }
  165. else
  166. gaveammo = false;
  167. if (player->weaponowned[weapon])
  168. gaveweapon = false;
  169. else
  170. {
  171. gaveweapon = true;
  172. player->weaponowned[weapon] = true;
  173. player->pendingweapon = weapon;
  174. }
  175. return (gaveweapon || gaveammo);
  176. }
  177. //
  178. // P_GiveBody
  179. // Returns false if the body isn't needed at all
  180. //
  181. qboolean
  182. P_GiveBody
  183. ( player_t* player,
  184. int num )
  185. {
  186. if (player->health >= MAXHEALTH)
  187. return false;
  188. player->health += num;
  189. if (player->health > MAXHEALTH)
  190. player->health = MAXHEALTH;
  191. player->mo->health = player->health;
  192. return true;
  193. }
  194. //
  195. // P_GiveArmor
  196. // Returns false if the armor is worse
  197. // than the current armor.
  198. //
  199. qboolean
  200. P_GiveArmor
  201. ( player_t* player,
  202. int armortype )
  203. {
  204. int hits;
  205. hits = armortype*100;
  206. if (player->armorpoints >= hits)
  207. return false; // don't pick up
  208. player->armortype = armortype;
  209. player->armorpoints = hits;
  210. return true;
  211. }
  212. //
  213. // P_GiveCard
  214. //
  215. void P_GiveCard( player_t* player, card_t card, const char *pickup_message ) {
  216. if ( ( ::g->demoplayback && ::g->netgame ) || common->IsMultiplayer() ) {
  217. for ( int i=0; i < MAXPLAYERS; i++ ) {
  218. if ( ::g->playeringame[i] ) {
  219. player_t *thePlayer = &::g->players[i];
  220. if (thePlayer->cards[card])
  221. continue;
  222. thePlayer->bonuscount = BONUSADD;
  223. thePlayer->message = pickup_message;
  224. thePlayer->cards[card] = 1;
  225. }
  226. }
  227. } else {
  228. if (player->cards[card])
  229. return;
  230. player->bonuscount = BONUSADD;
  231. player->message = pickup_message;
  232. player->cards[card] = 1;
  233. }
  234. }
  235. //
  236. // P_GivePower
  237. //
  238. qboolean
  239. P_GivePower
  240. ( player_t* player,
  241. int /*powertype_t*/ power )
  242. {
  243. if (power == pw_invulnerability)
  244. {
  245. player->powers[power] = INVULNTICS;
  246. return true;
  247. }
  248. if (power == pw_invisibility)
  249. {
  250. player->powers[power] = INVISTICS;
  251. player->mo->flags |= MF_SHADOW;
  252. return true;
  253. }
  254. if (power == pw_infrared)
  255. {
  256. player->powers[power] = INFRATICS;
  257. return true;
  258. }
  259. if (power == pw_ironfeet)
  260. {
  261. player->powers[power] = IRONTICS;
  262. return true;
  263. }
  264. if (power == pw_strength)
  265. {
  266. P_GiveBody (player, 100);
  267. player->powers[power] = 1;
  268. return true;
  269. }
  270. if (player->powers[power])
  271. return false; // already got it
  272. player->powers[power] = 1;
  273. return true;
  274. }
  275. //
  276. // P_TouchSpecialThing
  277. //
  278. void
  279. P_TouchSpecialThing
  280. ( mobj_t* special,
  281. mobj_t* toucher )
  282. {
  283. player_t* player;
  284. int i;
  285. fixed_t delta;
  286. int sound;
  287. delta = special->z - toucher->z;
  288. if (delta > toucher->height
  289. || delta < -8*FRACUNIT)
  290. {
  291. // out of reach
  292. return;
  293. }
  294. sound = sfx_itemup;
  295. player = toucher->player;
  296. // Dead thing touching.
  297. // Can happen with a sliding player corpse.
  298. if (toucher->health <= 0)
  299. return;
  300. // Identify by sprite.
  301. switch (special->sprite)
  302. {
  303. // armor
  304. case SPR_ARM1:
  305. if (!P_GiveArmor (player, 1))
  306. return;
  307. player->message = GOTARMOR;
  308. break;
  309. case SPR_ARM2:
  310. if (!P_GiveArmor (player, 2))
  311. return;
  312. player->message = GOTMEGA;
  313. break;
  314. // bonus items
  315. case SPR_BON1:
  316. player->health++; // can go over 100%
  317. if (player->health > 200)
  318. player->health = 200;
  319. player->mo->health = player->health;
  320. player->message = GOTHTHBONUS;
  321. break;
  322. case SPR_BON2:
  323. player->armorpoints++; // can go over 100%
  324. if (player->armorpoints > 200)
  325. player->armorpoints = 200;
  326. if (!player->armortype)
  327. player->armortype = 1;
  328. player->message = GOTARMBONUS;
  329. break;
  330. case SPR_SOUL:
  331. player->health += 100;
  332. if (player->health > 200)
  333. player->health = 200;
  334. player->mo->health = player->health;
  335. player->message = GOTSUPER;
  336. sound = sfx_getpow;
  337. break;
  338. case SPR_MEGA:
  339. if (::g->gamemode != commercial)
  340. return;
  341. player->health = 200;
  342. player->mo->health = player->health;
  343. P_GiveArmor (player,2);
  344. player->message = GOTMSPHERE;
  345. sound = sfx_getpow;
  346. break;
  347. // cards
  348. // leave cards for everyone
  349. case SPR_BKEY:
  350. //if (!player->cards[it_bluecard])
  351. //player->message = GOTBLUECARD;
  352. P_GiveCard (player, it_bluecard, GOTBLUECARD);
  353. if (!::g->netgame)
  354. break;
  355. return;
  356. case SPR_YKEY:
  357. //if (!player->cards[it_yellowcard])
  358. //player->message = GOTYELWCARD;
  359. P_GiveCard (player, it_yellowcard, GOTYELWCARD);
  360. if (!::g->netgame)
  361. break;
  362. return;
  363. case SPR_RKEY:
  364. //if (!player->cards[it_redcard])
  365. //player->message = GOTREDCARD;
  366. P_GiveCard (player, it_redcard, GOTREDCARD);
  367. if (!::g->netgame)
  368. break;
  369. return;
  370. case SPR_BSKU:
  371. //if (!player->cards[it_blueskull])
  372. //player->message = GOTBLUESKUL;
  373. P_GiveCard (player, it_blueskull, GOTBLUESKUL);
  374. if (!::g->netgame)
  375. break;
  376. return;
  377. case SPR_YSKU:
  378. //if (!player->cards[it_yellowskull])
  379. //player->message = GOTYELWSKUL;
  380. P_GiveCard (player, it_yellowskull, GOTYELWSKUL);
  381. if (!::g->netgame)
  382. break;
  383. return;
  384. case SPR_RSKU:
  385. //if (!player->cards[it_redskull])
  386. //player->message = GOTREDSKULL;
  387. P_GiveCard (player, it_redskull, GOTREDSKULL);
  388. if (!::g->netgame)
  389. break;
  390. return;
  391. // medikits, heals
  392. case SPR_STIM:
  393. if (!P_GiveBody (player, 10))
  394. return;
  395. player->message = GOTSTIM;
  396. break;
  397. case SPR_MEDI:
  398. if (!P_GiveBody (player, 25))
  399. return;
  400. if (player->health < 25)
  401. player->message = GOTMEDINEED;
  402. else
  403. player->message = GOTMEDIKIT;
  404. break;
  405. // power ups
  406. case SPR_PINV:
  407. if (!P_GivePower (player, pw_invulnerability))
  408. return;
  409. player->message = GOTINVUL;
  410. sound = sfx_getpow;
  411. break;
  412. case SPR_PSTR:
  413. if (!P_GivePower (player, pw_strength))
  414. return;
  415. player->message = GOTBERSERK;
  416. if (player->readyweapon != wp_fist)
  417. player->pendingweapon = wp_fist;
  418. sound = sfx_getpow;
  419. break;
  420. case SPR_PINS:
  421. if (!P_GivePower (player, pw_invisibility))
  422. return;
  423. player->message = GOTINVIS;
  424. sound = sfx_getpow;
  425. break;
  426. case SPR_SUIT:
  427. if (!P_GivePower (player, pw_ironfeet))
  428. return;
  429. player->message = GOTSUIT;
  430. sound = sfx_getpow;
  431. break;
  432. case SPR_PMAP:
  433. if (!P_GivePower (player, pw_allmap))
  434. return;
  435. player->message = GOTMAP;
  436. sound = sfx_getpow;
  437. break;
  438. case SPR_PVIS:
  439. if (!P_GivePower (player, pw_infrared))
  440. return;
  441. player->message = GOTVISOR;
  442. sound = sfx_getpow;
  443. break;
  444. // ammo
  445. case SPR_CLIP:
  446. if (special->flags & MF_DROPPED)
  447. {
  448. if (!P_GiveAmmo (player,am_clip,0))
  449. return;
  450. }
  451. else
  452. {
  453. if (!P_GiveAmmo (player,am_clip,1))
  454. return;
  455. }
  456. player->message = GOTCLIP;
  457. break;
  458. case SPR_AMMO:
  459. if (!P_GiveAmmo (player, am_clip,5))
  460. return;
  461. player->message = GOTCLIPBOX;
  462. break;
  463. case SPR_ROCK:
  464. if (!P_GiveAmmo (player, am_misl,1))
  465. return;
  466. player->message = GOTROCKET;
  467. break;
  468. case SPR_BROK:
  469. if (!P_GiveAmmo (player, am_misl,5))
  470. return;
  471. player->message = GOTROCKBOX;
  472. break;
  473. case SPR_CELL:
  474. if (!P_GiveAmmo (player, am_cell,1))
  475. return;
  476. player->message = GOTCELL;
  477. break;
  478. case SPR_CELP:
  479. if (!P_GiveAmmo (player, am_cell,5))
  480. return;
  481. player->message = GOTCELLBOX;
  482. break;
  483. case SPR_SHEL:
  484. if (!P_GiveAmmo (player, am_shell,1))
  485. return;
  486. player->message = GOTSHELLS;
  487. break;
  488. case SPR_SBOX:
  489. if (!P_GiveAmmo (player, am_shell,5))
  490. return;
  491. player->message = GOTSHELLBOX;
  492. break;
  493. case SPR_BPAK:
  494. if (!player->backpack)
  495. {
  496. for (i=0 ; i<NUMAMMO ; i++)
  497. player->maxammo[i] *= 2;
  498. player->backpack = true;
  499. }
  500. for (i=0 ; i<NUMAMMO ; i++)
  501. P_GiveAmmo (player, (ammotype_t)i, 1);
  502. player->message = GOTBACKPACK;
  503. break;
  504. // weapons
  505. case SPR_BFUG:
  506. if (!P_GiveWeapon (player, wp_bfg, false) )
  507. return;
  508. // DHM - Nerve :: Give achievement
  509. if ( !common->IsMultiplayer() ) {
  510. switch( DoomLib::GetGameSKU() ) {
  511. case GAME_SKU_DOOM2_BFG: {
  512. idAchievementManager::LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_REALLY_BIG_GUN_FIND_BFG_SINGLEPLAYER );
  513. }
  514. default: {
  515. // No unlocks for other SKUs.
  516. break;
  517. }
  518. }
  519. }
  520. player->message = GOTBFG9000;
  521. sound = sfx_wpnup;
  522. break;
  523. case SPR_MGUN:
  524. if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
  525. return;
  526. player->message = GOTCHAINGUN;
  527. sound = sfx_wpnup;
  528. break;
  529. case SPR_CSAW:
  530. if (!P_GiveWeapon (player, wp_chainsaw, false) )
  531. return;
  532. player->message = GOTCHAINSAW;
  533. sound = sfx_wpnup;
  534. break;
  535. case SPR_LAUN:
  536. if (!P_GiveWeapon (player, wp_missile, false) )
  537. return;
  538. player->message = GOTLAUNCHER;
  539. sound = sfx_wpnup;
  540. break;
  541. case SPR_PLAS:
  542. if (!P_GiveWeapon (player, wp_plasma, false) )
  543. return;
  544. player->message = GOTPLASMA;
  545. sound = sfx_wpnup;
  546. break;
  547. case SPR_SHOT:
  548. if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
  549. return;
  550. player->message = GOTSHOTGUN;
  551. sound = sfx_wpnup;
  552. break;
  553. case SPR_SGN2:
  554. if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
  555. return;
  556. player->message = GOTSHOTGUN2;
  557. sound = sfx_wpnup;
  558. break;
  559. default:
  560. I_Error ("P_SpecialThing: Unknown gettable thing");
  561. }
  562. if (special->flags & MF_COUNTITEM)
  563. player->itemcount++;
  564. P_RemoveMobj (special);
  565. player->bonuscount += BONUSADD;
  566. if (player == &::g->players[::g->consoleplayer])
  567. S_StartSound (player->mo, sound);
  568. }
  569. //
  570. // IsOnlineDeathmatchWithLocalProfile
  571. //
  572. // Helper to simplify the online frag stat tracking. Returns the
  573. // master user's profile if successful, NULL if not.
  574. //
  575. idPlayerProfile * IsOnlineDeathmatchWithLocalProfile() {
  576. if ( !MatchTypeIsOnline( session->GetGameLobbyBase().GetMatchParms().matchFlags ) ) {
  577. return NULL;
  578. }
  579. if ( !::g ) {
  580. return NULL;
  581. }
  582. if ( !::g->deathmatch ) {
  583. return NULL;
  584. }
  585. // Assume that the master local user is the one playing.
  586. idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
  587. if ( user == NULL ) {
  588. return NULL;
  589. }
  590. idPlayerProfile * profile = user->GetProfile();
  591. if ( profile == NULL ) {
  592. return NULL;
  593. }
  594. return profile;
  595. }
  596. //
  597. // KillMobj
  598. //
  599. void
  600. P_KillMobj
  601. ( mobj_t* source,
  602. mobj_t* target )
  603. {
  604. mobjtype_t item;
  605. mobj_t* mo;
  606. target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
  607. if (target->type != MT_SKULL)
  608. target->flags &= ~MF_NOGRAVITY;
  609. target->flags |= MF_CORPSE|MF_DROPOFF;
  610. target->height >>= 2;
  611. if (source && source->player)
  612. {
  613. // count for intermission
  614. if (target->flags & MF_COUNTKILL)
  615. source->player->killcount++;
  616. if (target->player) {
  617. source->player->frags[target->player-::g->players]++;
  618. // Keep track of the local player's total frags for trophy awards.
  619. // Make sure the killing player is the local player
  620. if ( source->player == &(::g->players[::g->consoleplayer]) ) {
  621. // Make sure this is an online game.
  622. // TODO: PC
  623. }
  624. }
  625. // DHM - Nerve :: Check for killing cyberdemon with fists achievement
  626. // JAF TROPHY int port = gameLocal->GetPortForPlayer( DoomLib::GetPlayer() );
  627. if ( source->player->readyweapon == wp_fist && target->type == MT_CYBORG && !common->IsMultiplayer() ) {
  628. switch( DoomLib::GetGameSKU() ) {
  629. case GAME_SKU_DOOM2_BFG: {
  630. // Removing trophies for DOOM and DOOM II BFG due to point limit.
  631. //gameLocal->UnlockAchievement( Doom2BFG_Trophies::YOU_HAVE_HUGE_GUTS_KILL_CYBERDEMON_WITH_FISTS );
  632. break;
  633. }
  634. case GAME_SKU_DCC: {
  635. // Not for PC.
  636. //session->GetAchievementSystem().AchievementUnlock( session->GetSignInManager().GetMasterLocalUser(), DOOM_ACHIEVEMENT_KILL_CYBER_DEMON_WITH_FISTS );
  637. break;
  638. }
  639. default: {
  640. // No unlocks for other SKUs.
  641. break;
  642. }
  643. }
  644. }
  645. // DHM - Nerve :: Chainsaw kills
  646. if ( source->player->readyweapon == wp_chainsaw && !common->IsMultiplayer() ) {
  647. source->player->chainsawKills++;
  648. if ( source->player->chainsawKills == 20 ) {
  649. switch( DoomLib::GetGameSKU() ) {
  650. case GAME_SKU_DOOM2_BFG: {
  651. // Removing trophies for DOOM and DOOM II BFG due to point limit.
  652. //gameLocal->UnlockAchievement( Doom2BFG_Trophies::GREAT_COMMUNICATOR_20_CHAINSAW_KILLS );
  653. break;
  654. }
  655. case GAME_SKU_DCC: {
  656. // Not for PC.
  657. //gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_20KILLS_CHAINSAW );
  658. break;
  659. }
  660. default: {
  661. // No unlocks for other SKUs.
  662. break;
  663. }
  664. }
  665. }
  666. }
  667. // DHM - Nerve :: Berserker kills
  668. if ( source->player->readyweapon == wp_fist && source->player->powers[pw_strength] && !common->IsMultiplayer()) {
  669. source->player->berserkKills++;
  670. idLib::Printf( "Player has %d berserk kills\n", source->player->berserkKills );
  671. if ( source->player->berserkKills == 20 ) {
  672. switch( DoomLib::GetGameSKU() ) {
  673. case GAME_SKU_DOOM2_BFG: {
  674. // Removing trophies for DOOM and DOOM II BFG due to point limit.
  675. //gameLocal->UnlockAchievement( Doom2BFG_Trophies::MAN_AND_A_HALF_20_BERSERK_KILLS );
  676. break;
  677. }
  678. case GAME_SKU_DCC: {
  679. // Not for PC.
  680. //gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_20KILLS_BERSERKER );
  681. break;
  682. }
  683. default: {
  684. // No unlocks for other SKUs.
  685. break;
  686. }
  687. }
  688. }
  689. }
  690. }
  691. else if (!::g->netgame && (target->flags & MF_COUNTKILL) )
  692. {
  693. // count all monster deaths,
  694. // even those caused by other monsters
  695. ::g->players[0].killcount++;
  696. }
  697. if (target->player)
  698. {
  699. // count environment kills against you
  700. if (!source)
  701. target->player->frags[target->player-::g->players]++;
  702. target->flags &= ~MF_SOLID;
  703. target->player->playerstate = PST_DEAD;
  704. P_DropWeapon (target->player);
  705. if (target->player == &::g->players[::g->consoleplayer]
  706. && ::g->automapactive)
  707. {
  708. // don't die in auto map,
  709. // switch view prior to dying
  710. AM_Stop ();
  711. }
  712. }
  713. if (target->health < -target->info->spawnhealth
  714. && target->info->xdeathstate)
  715. {
  716. P_SetMobjState (target, (statenum_t)target->info->xdeathstate);
  717. }
  718. else
  719. P_SetMobjState (target, (statenum_t)target->info->deathstate);
  720. target->tics -= P_Random()&3;
  721. if (target->tics < 1)
  722. target->tics = 1;
  723. // I_StartSound (&actor->r, actor->info->deathsound);
  724. // Drop stuff.
  725. // This determines the kind of object spawned
  726. // during the death frame of a thing.
  727. switch (target->type)
  728. {
  729. case MT_WOLFSS:
  730. case MT_POSSESSED:
  731. item = MT_CLIP;
  732. break;
  733. case MT_SHOTGUY:
  734. item = MT_SHOTGUN;
  735. break;
  736. case MT_CHAINGUY:
  737. item = MT_CHAINGUN;
  738. break;
  739. default:
  740. return;
  741. }
  742. mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
  743. mo->flags |= MF_DROPPED; // special versions of items
  744. }
  745. //
  746. // P_DamageMobj
  747. // Damages both enemies and ::g->players
  748. // "inflictor" is the thing that caused the damage
  749. // creature or missile, can be NULL (slime, etc)
  750. // "source" is the thing to target after taking damage
  751. // creature or NULL
  752. // Source and inflictor are the same for melee attacks.
  753. // Source can be NULL for slime, barrel explosions
  754. // and other environmental stuff.
  755. //
  756. void
  757. P_DamageMobj
  758. ( mobj_t* target,
  759. mobj_t* inflictor,
  760. mobj_t* source,
  761. int damage )
  762. {
  763. unsigned ang;
  764. int saved;
  765. player_t* player;
  766. fixed_t thrust;
  767. int temp;
  768. if ( !(target->flags & MF_SHOOTABLE) )
  769. return; // shouldn't happen...
  770. if (target->health <= 0)
  771. return;
  772. if ( target->flags & MF_SKULLFLY )
  773. {
  774. target->momx = target->momy = target->momz = 0;
  775. }
  776. player = target->player;
  777. if (player && ::g->gameskill == sk_baby)
  778. damage >>= 1; // take half damage in trainer mode
  779. // Some close combat weapons should not
  780. // inflict thrust and push the victim out of reach,
  781. // thus kick away unless using the chainsaw.
  782. if (inflictor
  783. && !(target->flags & MF_NOCLIP)
  784. && (!source
  785. || !source->player
  786. || source->player->readyweapon != wp_chainsaw))
  787. {
  788. ang = R_PointToAngle2 ( inflictor->x,
  789. inflictor->y,
  790. target->x,
  791. target->y);
  792. thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
  793. // make fall forwards sometimes
  794. if ( damage < 40
  795. && damage > target->health
  796. && target->z - inflictor->z > 64*FRACUNIT
  797. && (P_Random ()&1) )
  798. {
  799. ang += ANG180;
  800. thrust *= 4;
  801. }
  802. ang >>= ANGLETOFINESHIFT;
  803. target->momx += FixedMul (thrust, finecosine[ang]);
  804. target->momy += FixedMul (thrust, finesine[ang]);
  805. }
  806. // player specific
  807. if (player)
  808. {
  809. // end of game hell hack
  810. if (target->subsector->sector->special == 11
  811. && damage >= target->health)
  812. {
  813. damage = target->health - 1;
  814. }
  815. float baseShake_High = 0.5f;
  816. int baseShake_High_Dur = 100;
  817. float baseShake_Low = 0.5f;
  818. int baseShake_Low_Dur = 100;
  819. int damageClamp = Min( damage, 100 );
  820. float damageFloat = std::min( (float)damageClamp / 100.0f, 100.0f );
  821. float additional = 0.5f * damageFloat;
  822. int additional_time = 500.0f * damageFloat;
  823. if( ::g->plyr == player ) {
  824. }
  825. // Below certain threshold,
  826. // ignore damage in GOD mode, or with INVUL power.
  827. if ( damage < 1000
  828. && ( (player->cheats&CF_GODMODE)
  829. || player->powers[pw_invulnerability] ) )
  830. {
  831. return;
  832. }
  833. if (player->armortype)
  834. {
  835. if (player->armortype == 1)
  836. saved = damage/3;
  837. else
  838. saved = damage/2;
  839. if (player->armorpoints <= saved)
  840. {
  841. // armor is used up
  842. saved = player->armorpoints;
  843. player->armortype = 0;
  844. }
  845. player->armorpoints -= saved;
  846. damage -= saved;
  847. }
  848. player->health -= damage; // mirror mobj health here for Dave
  849. if (player->health < 0)
  850. player->health = 0;
  851. player->attacker = source;
  852. player->damagecount += damage; // add damage after armor / invuln
  853. if (player->damagecount > 100)
  854. player->damagecount = 100; // teleport stomp does 10k points...
  855. temp = damage < 100 ? damage : 100;
  856. }
  857. // do the damage
  858. target->health -= damage;
  859. if (target->health <= 0)
  860. {
  861. P_KillMobj (source, target);
  862. return;
  863. }
  864. if ( (P_Random () < target->info->painchance)
  865. && !(target->flags&MF_SKULLFLY) )
  866. {
  867. target->flags |= MF_JUSTHIT; // fight back!
  868. P_SetMobjState (target, (statenum_t)target->info->painstate);
  869. }
  870. target->reactiontime = 0; // we're awake now...
  871. if ( (!target->threshold || target->type == MT_VILE)
  872. && source && source != target
  873. && source->type != MT_VILE)
  874. {
  875. // if not intent on another player,
  876. // chase after this one
  877. target->target = source;
  878. target->threshold = BASETHRESHOLD;
  879. if (target->state == &::g->states[target->info->spawnstate]
  880. && target->info->seestate != S_NULL)
  881. P_SetMobjState (target, (statenum_t)target->info->seestate);
  882. }
  883. }