123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- 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.
- 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.
- ===========================================================================
- */
- #include "Precompiled.h"
- #include "globaldata.h"
- // Data.
- #include "doomdef.h"
- #include "dstrings.h"
- #include "sounds.h"
- #include "doomstat.h"
- #include "m_random.h"
- #include "i_system.h"
- #include "am_map.h"
- #include "p_local.h"
- #include "s_sound.h"
- #ifdef __GNUG__
- #pragma implementation "p_inter.h"
- #endif
- #include "p_inter.h"
- #include "Main.h"
- #include "sys/sys_signin.h"
- #include "../../neo/d3xp/Game_Local.h"
- // a weapon is found with two clip loads,
- // a big item has five clip loads
- const int maxammo[NUMAMMO] = {200, 50, 300, 50};
- const int clipammo[NUMAMMO] = {10, 4, 20, 1};
- //
- // GET STUFF
- //
- //
- // P_GiveAmmo
- // Num is the number of clip loads,
- // not the individual count (0= 1/2 clip).
- // Returns false if the ammo can't be picked up at all
- //
- qboolean
- P_GiveAmmo
- ( player_t* player,
- ammotype_t ammo,
- int num )
- {
- int oldammo;
- if (ammo == am_noammo)
- return false;
- if (ammo < 0 || ammo > NUMAMMO)
- I_Error ("P_GiveAmmo: bad type %i", ammo);
- if ( player->ammo[ammo] == player->maxammo[ammo] )
- return false;
- if (num)
- num *= clipammo[ammo];
- else
- num = clipammo[ammo]/2;
- if (::g->gameskill == sk_baby
- || ::g->gameskill == sk_nightmare)
- {
- // give double ammo in trainer mode,
- // you'll need in nightmare
- num <<= 1;
- }
- oldammo = player->ammo[ammo];
- player->ammo[ammo] += num;
- if (player->ammo[ammo] > player->maxammo[ammo])
- player->ammo[ammo] = player->maxammo[ammo];
- // If non zero ammo,
- // don't change up weapons,
- // player was lower on purpose.
- if (oldammo)
- return true;
- // We were down to zero,
- // so select a new weapon.
- // Preferences are not user selectable.
- switch (ammo)
- {
- case am_clip:
- if (player->readyweapon == wp_fist)
- {
- if (player->weaponowned[wp_chaingun])
- player->pendingweapon = wp_chaingun;
- else
- player->pendingweapon = wp_pistol;
- }
- break;
- case am_shell:
- if (player->readyweapon == wp_fist
- || player->readyweapon == wp_pistol)
- {
- if (player->weaponowned[wp_shotgun])
- player->pendingweapon = wp_shotgun;
- }
- break;
- case am_cell:
- if (player->readyweapon == wp_fist
- || player->readyweapon == wp_pistol)
- {
- if (player->weaponowned[wp_plasma])
- player->pendingweapon = wp_plasma;
- }
- break;
- case am_misl:
- if (player->readyweapon == wp_fist)
- {
- if (player->weaponowned[wp_missile])
- player->pendingweapon = wp_missile;
- }
- default:
- break;
- }
- return true;
- }
- //
- // P_GiveWeapon
- // The weapon name may have a MF_DROPPED flag ored in.
- //
- qboolean
- P_GiveWeapon
- ( player_t* player,
- weapontype_t weapon,
- qboolean dropped )
- {
- qboolean gaveammo;
- qboolean gaveweapon;
- if (::g->netgame
- && (::g->deathmatch!=2)
- && !dropped )
- {
- // leave placed weapons forever on net games
- if (player->weaponowned[weapon])
- return false;
- player->bonuscount += BONUSADD;
- player->weaponowned[weapon] = true;
- if (::g->deathmatch)
- P_GiveAmmo (player, weaponinfo[weapon].ammo, 5);
- else
- P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
- player->pendingweapon = weapon;
- if (player == &::g->players[::g->consoleplayer])
- S_StartSound (player->mo, sfx_wpnup);
- return false;
- }
- if (weaponinfo[weapon].ammo != am_noammo)
- {
- // give one clip with a dropped weapon,
- // two clips with a found weapon
- if (dropped)
- gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1);
- else
- gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2);
- }
- else
- gaveammo = false;
- if (player->weaponowned[weapon])
- gaveweapon = false;
- else
- {
- gaveweapon = true;
- player->weaponowned[weapon] = true;
- player->pendingweapon = weapon;
- }
- return (gaveweapon || gaveammo);
- }
- //
- // P_GiveBody
- // Returns false if the body isn't needed at all
- //
- qboolean
- P_GiveBody
- ( player_t* player,
- int num )
- {
- if (player->health >= MAXHEALTH)
- return false;
- player->health += num;
- if (player->health > MAXHEALTH)
- player->health = MAXHEALTH;
- player->mo->health = player->health;
- return true;
- }
- //
- // P_GiveArmor
- // Returns false if the armor is worse
- // than the current armor.
- //
- qboolean
- P_GiveArmor
- ( player_t* player,
- int armortype )
- {
- int hits;
- hits = armortype*100;
- if (player->armorpoints >= hits)
- return false; // don't pick up
- player->armortype = armortype;
- player->armorpoints = hits;
- return true;
- }
- //
- // P_GiveCard
- //
- void P_GiveCard( player_t* player, card_t card, const char *pickup_message ) {
- if ( ( ::g->demoplayback && ::g->netgame ) || common->IsMultiplayer() ) {
- for ( int i=0; i < MAXPLAYERS; i++ ) {
- if ( ::g->playeringame[i] ) {
- player_t *thePlayer = &::g->players[i];
- if (thePlayer->cards[card])
- continue;
- thePlayer->bonuscount = BONUSADD;
- thePlayer->message = pickup_message;
- thePlayer->cards[card] = 1;
- }
- }
- } else {
- if (player->cards[card])
- return;
- player->bonuscount = BONUSADD;
- player->message = pickup_message;
- player->cards[card] = 1;
- }
- }
- //
- // P_GivePower
- //
- qboolean
- P_GivePower
- ( player_t* player,
- int /*powertype_t*/ power )
- {
- if (power == pw_invulnerability)
- {
- player->powers[power] = INVULNTICS;
- return true;
- }
- if (power == pw_invisibility)
- {
- player->powers[power] = INVISTICS;
- player->mo->flags |= MF_SHADOW;
- return true;
- }
- if (power == pw_infrared)
- {
- player->powers[power] = INFRATICS;
- return true;
- }
- if (power == pw_ironfeet)
- {
- player->powers[power] = IRONTICS;
- return true;
- }
- if (power == pw_strength)
- {
- P_GiveBody (player, 100);
- player->powers[power] = 1;
- return true;
- }
- if (player->powers[power])
- return false; // already got it
- player->powers[power] = 1;
- return true;
- }
- //
- // P_TouchSpecialThing
- //
- void
- P_TouchSpecialThing
- ( mobj_t* special,
- mobj_t* toucher )
- {
- player_t* player;
- int i;
- fixed_t delta;
- int sound;
- delta = special->z - toucher->z;
- if (delta > toucher->height
- || delta < -8*FRACUNIT)
- {
- // out of reach
- return;
- }
- sound = sfx_itemup;
- player = toucher->player;
- // Dead thing touching.
- // Can happen with a sliding player corpse.
- if (toucher->health <= 0)
- return;
- // Identify by sprite.
- switch (special->sprite)
- {
- // armor
- case SPR_ARM1:
- if (!P_GiveArmor (player, 1))
- return;
- player->message = GOTARMOR;
- break;
- case SPR_ARM2:
- if (!P_GiveArmor (player, 2))
- return;
- player->message = GOTMEGA;
- break;
- // bonus items
- case SPR_BON1:
- player->health++; // can go over 100%
- if (player->health > 200)
- player->health = 200;
- player->mo->health = player->health;
- player->message = GOTHTHBONUS;
- break;
- case SPR_BON2:
- player->armorpoints++; // can go over 100%
- if (player->armorpoints > 200)
- player->armorpoints = 200;
- if (!player->armortype)
- player->armortype = 1;
- player->message = GOTARMBONUS;
- break;
- case SPR_SOUL:
- player->health += 100;
- if (player->health > 200)
- player->health = 200;
- player->mo->health = player->health;
- player->message = GOTSUPER;
- sound = sfx_getpow;
- break;
- case SPR_MEGA:
- if (::g->gamemode != commercial)
- return;
- player->health = 200;
- player->mo->health = player->health;
- P_GiveArmor (player,2);
- player->message = GOTMSPHERE;
- sound = sfx_getpow;
- break;
- // cards
- // leave cards for everyone
- case SPR_BKEY:
- //if (!player->cards[it_bluecard])
- //player->message = GOTBLUECARD;
- P_GiveCard (player, it_bluecard, GOTBLUECARD);
- if (!::g->netgame)
- break;
- return;
- case SPR_YKEY:
- //if (!player->cards[it_yellowcard])
- //player->message = GOTYELWCARD;
- P_GiveCard (player, it_yellowcard, GOTYELWCARD);
- if (!::g->netgame)
- break;
- return;
- case SPR_RKEY:
- //if (!player->cards[it_redcard])
- //player->message = GOTREDCARD;
- P_GiveCard (player, it_redcard, GOTREDCARD);
- if (!::g->netgame)
- break;
- return;
- case SPR_BSKU:
- //if (!player->cards[it_blueskull])
- //player->message = GOTBLUESKUL;
- P_GiveCard (player, it_blueskull, GOTBLUESKUL);
- if (!::g->netgame)
- break;
- return;
- case SPR_YSKU:
- //if (!player->cards[it_yellowskull])
- //player->message = GOTYELWSKUL;
- P_GiveCard (player, it_yellowskull, GOTYELWSKUL);
- if (!::g->netgame)
- break;
- return;
- case SPR_RSKU:
- //if (!player->cards[it_redskull])
- //player->message = GOTREDSKULL;
- P_GiveCard (player, it_redskull, GOTREDSKULL);
- if (!::g->netgame)
- break;
- return;
- // medikits, heals
- case SPR_STIM:
- if (!P_GiveBody (player, 10))
- return;
- player->message = GOTSTIM;
- break;
- case SPR_MEDI:
- if (!P_GiveBody (player, 25))
- return;
- if (player->health < 25)
- player->message = GOTMEDINEED;
- else
- player->message = GOTMEDIKIT;
- break;
- // power ups
- case SPR_PINV:
- if (!P_GivePower (player, pw_invulnerability))
- return;
- player->message = GOTINVUL;
- sound = sfx_getpow;
- break;
- case SPR_PSTR:
- if (!P_GivePower (player, pw_strength))
- return;
- player->message = GOTBERSERK;
- if (player->readyweapon != wp_fist)
- player->pendingweapon = wp_fist;
- sound = sfx_getpow;
- break;
- case SPR_PINS:
- if (!P_GivePower (player, pw_invisibility))
- return;
- player->message = GOTINVIS;
- sound = sfx_getpow;
- break;
- case SPR_SUIT:
- if (!P_GivePower (player, pw_ironfeet))
- return;
- player->message = GOTSUIT;
- sound = sfx_getpow;
- break;
- case SPR_PMAP:
- if (!P_GivePower (player, pw_allmap))
- return;
- player->message = GOTMAP;
- sound = sfx_getpow;
- break;
- case SPR_PVIS:
- if (!P_GivePower (player, pw_infrared))
- return;
- player->message = GOTVISOR;
- sound = sfx_getpow;
- break;
- // ammo
- case SPR_CLIP:
- if (special->flags & MF_DROPPED)
- {
- if (!P_GiveAmmo (player,am_clip,0))
- return;
- }
- else
- {
- if (!P_GiveAmmo (player,am_clip,1))
- return;
- }
- player->message = GOTCLIP;
- break;
- case SPR_AMMO:
- if (!P_GiveAmmo (player, am_clip,5))
- return;
- player->message = GOTCLIPBOX;
- break;
- case SPR_ROCK:
- if (!P_GiveAmmo (player, am_misl,1))
- return;
- player->message = GOTROCKET;
- break;
- case SPR_BROK:
- if (!P_GiveAmmo (player, am_misl,5))
- return;
- player->message = GOTROCKBOX;
- break;
- case SPR_CELL:
- if (!P_GiveAmmo (player, am_cell,1))
- return;
- player->message = GOTCELL;
- break;
- case SPR_CELP:
- if (!P_GiveAmmo (player, am_cell,5))
- return;
- player->message = GOTCELLBOX;
- break;
- case SPR_SHEL:
- if (!P_GiveAmmo (player, am_shell,1))
- return;
- player->message = GOTSHELLS;
- break;
- case SPR_SBOX:
- if (!P_GiveAmmo (player, am_shell,5))
- return;
- player->message = GOTSHELLBOX;
- break;
- case SPR_BPAK:
- if (!player->backpack)
- {
- for (i=0 ; i<NUMAMMO ; i++)
- player->maxammo[i] *= 2;
- player->backpack = true;
- }
- for (i=0 ; i<NUMAMMO ; i++)
- P_GiveAmmo (player, (ammotype_t)i, 1);
- player->message = GOTBACKPACK;
- break;
- // weapons
- case SPR_BFUG:
- if (!P_GiveWeapon (player, wp_bfg, false) )
- return;
- // DHM - Nerve :: Give achievement
- if ( !common->IsMultiplayer() ) {
- switch( DoomLib::GetGameSKU() ) {
- case GAME_SKU_DOOM2_BFG: {
- idAchievementManager::LocalUser_CompleteAchievement( ACHIEVEMENT_DOOM2_REALLY_BIG_GUN_FIND_BFG_SINGLEPLAYER );
- }
- default: {
- // No unlocks for other SKUs.
- break;
- }
- }
- }
- player->message = GOTBFG9000;
- sound = sfx_wpnup;
- break;
- case SPR_MGUN:
- if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) )
- return;
- player->message = GOTCHAINGUN;
- sound = sfx_wpnup;
- break;
- case SPR_CSAW:
- if (!P_GiveWeapon (player, wp_chainsaw, false) )
- return;
- player->message = GOTCHAINSAW;
- sound = sfx_wpnup;
- break;
- case SPR_LAUN:
- if (!P_GiveWeapon (player, wp_missile, false) )
- return;
- player->message = GOTLAUNCHER;
- sound = sfx_wpnup;
- break;
- case SPR_PLAS:
- if (!P_GiveWeapon (player, wp_plasma, false) )
- return;
- player->message = GOTPLASMA;
- sound = sfx_wpnup;
- break;
- case SPR_SHOT:
- if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) )
- return;
- player->message = GOTSHOTGUN;
- sound = sfx_wpnup;
- break;
- case SPR_SGN2:
- if (!P_GiveWeapon (player, wp_supershotgun, special->flags&MF_DROPPED ) )
- return;
- player->message = GOTSHOTGUN2;
- sound = sfx_wpnup;
- break;
- default:
- I_Error ("P_SpecialThing: Unknown gettable thing");
- }
- if (special->flags & MF_COUNTITEM)
- player->itemcount++;
- P_RemoveMobj (special);
- player->bonuscount += BONUSADD;
- if (player == &::g->players[::g->consoleplayer])
- S_StartSound (player->mo, sound);
- }
- //
- // IsOnlineDeathmatchWithLocalProfile
- //
- // Helper to simplify the online frag stat tracking. Returns the
- // master user's profile if successful, NULL if not.
- //
- idPlayerProfile * IsOnlineDeathmatchWithLocalProfile() {
- if ( !MatchTypeIsOnline( session->GetGameLobbyBase().GetMatchParms().matchFlags ) ) {
- return NULL;
- }
- if ( !::g ) {
- return NULL;
- }
- if ( !::g->deathmatch ) {
- return NULL;
- }
- // Assume that the master local user is the one playing.
- idLocalUser * user = session->GetSignInManager().GetMasterLocalUser();
- if ( user == NULL ) {
- return NULL;
- }
- idPlayerProfile * profile = user->GetProfile();
- if ( profile == NULL ) {
- return NULL;
- }
-
- return profile;
- }
- //
- // KillMobj
- //
- void
- P_KillMobj
- ( mobj_t* source,
- mobj_t* target )
- {
- mobjtype_t item;
- mobj_t* mo;
- target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY);
- if (target->type != MT_SKULL)
- target->flags &= ~MF_NOGRAVITY;
- target->flags |= MF_CORPSE|MF_DROPOFF;
- target->height >>= 2;
- if (source && source->player)
- {
- // count for intermission
- if (target->flags & MF_COUNTKILL)
- source->player->killcount++;
- if (target->player) {
- source->player->frags[target->player-::g->players]++;
- // Keep track of the local player's total frags for trophy awards.
- // Make sure the killing player is the local player
- if ( source->player == &(::g->players[::g->consoleplayer]) ) {
- // Make sure this is an online game.
- // TODO: PC
- }
- }
- // DHM - Nerve :: Check for killing cyberdemon with fists achievement
- // JAF TROPHY int port = gameLocal->GetPortForPlayer( DoomLib::GetPlayer() );
- if ( source->player->readyweapon == wp_fist && target->type == MT_CYBORG && !common->IsMultiplayer() ) {
- switch( DoomLib::GetGameSKU() ) {
- case GAME_SKU_DOOM2_BFG: {
- // Removing trophies for DOOM and DOOM II BFG due to point limit.
- //gameLocal->UnlockAchievement( Doom2BFG_Trophies::YOU_HAVE_HUGE_GUTS_KILL_CYBERDEMON_WITH_FISTS );
- break;
- }
- case GAME_SKU_DCC: {
- // Not for PC.
- //session->GetAchievementSystem().AchievementUnlock( session->GetSignInManager().GetMasterLocalUser(), DOOM_ACHIEVEMENT_KILL_CYBER_DEMON_WITH_FISTS );
- break;
- }
- default: {
- // No unlocks for other SKUs.
- break;
- }
- }
- }
- // DHM - Nerve :: Chainsaw kills
- if ( source->player->readyweapon == wp_chainsaw && !common->IsMultiplayer() ) {
- source->player->chainsawKills++;
- if ( source->player->chainsawKills == 20 ) {
- switch( DoomLib::GetGameSKU() ) {
- case GAME_SKU_DOOM2_BFG: {
- // Removing trophies for DOOM and DOOM II BFG due to point limit.
- //gameLocal->UnlockAchievement( Doom2BFG_Trophies::GREAT_COMMUNICATOR_20_CHAINSAW_KILLS );
- break;
- }
- case GAME_SKU_DCC: {
- // Not for PC.
- //gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_20KILLS_CHAINSAW );
- break;
- }
- default: {
- // No unlocks for other SKUs.
- break;
- }
- }
- }
- }
- // DHM - Nerve :: Berserker kills
- if ( source->player->readyweapon == wp_fist && source->player->powers[pw_strength] && !common->IsMultiplayer()) {
- source->player->berserkKills++;
- idLib::Printf( "Player has %d berserk kills\n", source->player->berserkKills );
- if ( source->player->berserkKills == 20 ) {
- switch( DoomLib::GetGameSKU() ) {
- case GAME_SKU_DOOM2_BFG: {
- // Removing trophies for DOOM and DOOM II BFG due to point limit.
- //gameLocal->UnlockAchievement( Doom2BFG_Trophies::MAN_AND_A_HALF_20_BERSERK_KILLS );
- break;
- }
- case GAME_SKU_DCC: {
- // Not for PC.
- //gameLocal->UnlockAchievement( DOOM_ACHIEVEMENT_20KILLS_BERSERKER );
- break;
- }
- default: {
- // No unlocks for other SKUs.
- break;
- }
- }
- }
- }
- }
- else if (!::g->netgame && (target->flags & MF_COUNTKILL) )
- {
- // count all monster deaths,
- // even those caused by other monsters
- ::g->players[0].killcount++;
- }
- if (target->player)
- {
- // count environment kills against you
- if (!source)
- target->player->frags[target->player-::g->players]++;
- target->flags &= ~MF_SOLID;
- target->player->playerstate = PST_DEAD;
- P_DropWeapon (target->player);
- if (target->player == &::g->players[::g->consoleplayer]
- && ::g->automapactive)
- {
- // don't die in auto map,
- // switch view prior to dying
- AM_Stop ();
- }
- }
- if (target->health < -target->info->spawnhealth
- && target->info->xdeathstate)
- {
- P_SetMobjState (target, (statenum_t)target->info->xdeathstate);
- }
- else
- P_SetMobjState (target, (statenum_t)target->info->deathstate);
- target->tics -= P_Random()&3;
- if (target->tics < 1)
- target->tics = 1;
- // I_StartSound (&actor->r, actor->info->deathsound);
- // Drop stuff.
- // This determines the kind of object spawned
- // during the death frame of a thing.
- switch (target->type)
- {
- case MT_WOLFSS:
- case MT_POSSESSED:
- item = MT_CLIP;
- break;
- case MT_SHOTGUY:
- item = MT_SHOTGUN;
- break;
- case MT_CHAINGUY:
- item = MT_CHAINGUN;
- break;
- default:
- return;
- }
- mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item);
- mo->flags |= MF_DROPPED; // special versions of items
- }
- //
- // P_DamageMobj
- // Damages both enemies and ::g->players
- // "inflictor" is the thing that caused the damage
- // creature or missile, can be NULL (slime, etc)
- // "source" is the thing to target after taking damage
- // creature or NULL
- // Source and inflictor are the same for melee attacks.
- // Source can be NULL for slime, barrel explosions
- // and other environmental stuff.
- //
- void
- P_DamageMobj
- ( mobj_t* target,
- mobj_t* inflictor,
- mobj_t* source,
- int damage )
- {
- unsigned ang;
- int saved;
- player_t* player;
- fixed_t thrust;
- int temp;
- if ( !(target->flags & MF_SHOOTABLE) )
- return; // shouldn't happen...
- if (target->health <= 0)
- return;
- if ( target->flags & MF_SKULLFLY )
- {
- target->momx = target->momy = target->momz = 0;
- }
- player = target->player;
- if (player && ::g->gameskill == sk_baby)
- damage >>= 1; // take half damage in trainer mode
- // Some close combat weapons should not
- // inflict thrust and push the victim out of reach,
- // thus kick away unless using the chainsaw.
- if (inflictor
- && !(target->flags & MF_NOCLIP)
- && (!source
- || !source->player
- || source->player->readyweapon != wp_chainsaw))
- {
- ang = R_PointToAngle2 ( inflictor->x,
- inflictor->y,
- target->x,
- target->y);
- thrust = damage*(FRACUNIT>>3)*100/target->info->mass;
- // make fall forwards sometimes
- if ( damage < 40
- && damage > target->health
- && target->z - inflictor->z > 64*FRACUNIT
- && (P_Random ()&1) )
- {
- ang += ANG180;
- thrust *= 4;
- }
- ang >>= ANGLETOFINESHIFT;
- target->momx += FixedMul (thrust, finecosine[ang]);
- target->momy += FixedMul (thrust, finesine[ang]);
- }
- // player specific
- if (player)
- {
- // end of game hell hack
- if (target->subsector->sector->special == 11
- && damage >= target->health)
- {
- damage = target->health - 1;
- }
- float baseShake_High = 0.5f;
- int baseShake_High_Dur = 100;
- float baseShake_Low = 0.5f;
- int baseShake_Low_Dur = 100;
- int damageClamp = Min( damage, 100 );
- float damageFloat = std::min( (float)damageClamp / 100.0f, 100.0f );
- float additional = 0.5f * damageFloat;
- int additional_time = 500.0f * damageFloat;
- if( ::g->plyr == player ) {
- }
- // Below certain threshold,
- // ignore damage in GOD mode, or with INVUL power.
- if ( damage < 1000
- && ( (player->cheats&CF_GODMODE)
- || player->powers[pw_invulnerability] ) )
- {
- return;
- }
- if (player->armortype)
- {
- if (player->armortype == 1)
- saved = damage/3;
- else
- saved = damage/2;
- if (player->armorpoints <= saved)
- {
- // armor is used up
- saved = player->armorpoints;
- player->armortype = 0;
- }
- player->armorpoints -= saved;
- damage -= saved;
- }
- player->health -= damage; // mirror mobj health here for Dave
- if (player->health < 0)
- player->health = 0;
- player->attacker = source;
- player->damagecount += damage; // add damage after armor / invuln
- if (player->damagecount > 100)
- player->damagecount = 100; // teleport stomp does 10k points...
- temp = damage < 100 ? damage : 100;
- }
- // do the damage
- target->health -= damage;
- if (target->health <= 0)
- {
- P_KillMobj (source, target);
- return;
- }
- if ( (P_Random () < target->info->painchance)
- && !(target->flags&MF_SKULLFLY) )
- {
- target->flags |= MF_JUSTHIT; // fight back!
- P_SetMobjState (target, (statenum_t)target->info->painstate);
- }
- target->reactiontime = 0; // we're awake now...
- if ( (!target->threshold || target->type == MT_VILE)
- && source && source != target
- && source->type != MT_VILE)
- {
- // if not intent on another player,
- // chase after this one
- target->target = source;
- target->threshold = BASETHRESHOLD;
- if (target->state == &::g->states[target->info->spawnstate]
- && target->info->seestate != S_NULL)
- P_SetMobjState (target, (statenum_t)target->info->seestate);
- }
- }
|