DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { PARAM_ACTION_PROLOGUE; if (self == nullptr) { return 0; } player_t *player = self->player; DPSprite *psp; if (nullptr == player) { return 0; } if (player->PendingWeapon != WP_NOCHANGE) { P_DropWeapon(player); return 0; } if (player->ReadyWeapon == nullptr) { return 0; } psp = player->GetPSprite(PSP_WEAPON); psp->y -= RAISESPEED; if (psp->y > WEAPONTOP) { // Not raised all the way yet return 0; } psp->y = WEAPONTOP; psp->SetState(player->ReadyWeapon->GetReadyState()); return 0; }
DEFINE_ACTION_FUNCTION(AInventory, A_Raise) { if (self == NULL) { return; } player_t *player = self->player; pspdef_t *psp; if (NULL == player) { return; } if (player->PendingWeapon != WP_NOCHANGE) { P_DropWeapon(player); return; } psp = &player->psprites[ps_weapon]; psp->sy -= RAISESPEED; if (psp->sy > WEAPONTOP) { // Not raised all the way yet return; } psp->sy = WEAPONTOP; if (player->ReadyWeapon != NULL) { P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState()); } else { player->psprites[ps_weapon].state = NULL; } }
void P_CheckWeaponSwitch (player_t *player) { if (player == NULL) { return; } if ((player->WeaponState & WF_DISABLESWITCH) || // Weapon changing has been disabled. player->morphTics != 0) // Morphed classes cannot change weapons. { // ...so throw away any pending weapon requests. player->PendingWeapon = WP_NOCHANGE; } // Put the weapon away if the player has a pending weapon or has died, and // we're at a place in the state sequence where dropping the weapon is okay. if ((player->PendingWeapon != WP_NOCHANGE || player->health <= 0) && player->WeaponState & WF_WEAPONSWITCHOK) { P_DropWeapon(player); } }
void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) { // Handle possible unmorph on death bool wasgibbed = (health < GibHealth()); AActor *realthis = NULL; int realstyle = 0; int realhealth = 0; if (P_MorphedDeath(this, &realthis, &realstyle, &realhealth)) { if (!(realstyle & MORPH_UNDOBYDEATHSAVES)) { if (wasgibbed) { int realgibhealth = realthis->GibHealth(); if (realthis->health >= realgibhealth) { realthis->health = realgibhealth -1; // if morphed was gibbed, so must original be (where allowed)l } } realthis->Die(source, inflictor, dmgflags); } return; } // [SO] 9/2/02 -- It's rather funny to see an exploded player body with the invuln sparkle active :) effects &= ~FX_RESPAWNINVUL; //flags &= ~MF_INVINCIBLE; if (debugfile && this->player) { static int dieticks[MAXPLAYERS]; // [ZzZombo] not used? Except if for peeking in debugger... int pnum = int(this->player-players); dieticks[pnum] = gametic; fprintf (debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, this->player->cheats&CF_PREDICTING?"predicting":"real"); } // [RH] Notify this actor's items. for (AInventory *item = Inventory; item != NULL; ) { AInventory *next = item->Inventory; item->OwnerDied(); item = next; } if (flags & MF_MISSILE) { // [RH] When missiles die, they just explode P_ExplodeMissile (this, NULL, NULL); return; } // [RH] Set the target to the thing that killed it. Strife apparently does this. if (source != NULL) { target = source; } flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY; flags |= MF_DROPOFF; if ((flags3 & MF3_ISMONSTER) || FindState(NAME_Raise) != NULL || IsKindOf(RUNTIME_CLASS(APlayerPawn))) { // [RH] Only monsters get to be corpses. // Objects with a raise state should get the flag as well so they can // be revived by an Arch-Vile. Batman Doom needs this. // [RC] And disable this if DONTCORPSE is set, of course. if(!(flags6 & MF6_DONTCORPSE)) flags |= MF_CORPSE; } flags6 |= MF6_KILLED; // [RH] Allow the death height to be overridden using metadata. fixed_t metaheight = 0; if (DamageType == NAME_Fire) { metaheight = GetClass()->Meta.GetMetaFixed (AMETA_BurnHeight); } if (metaheight == 0) { metaheight = GetClass()->Meta.GetMetaFixed (AMETA_DeathHeight); } if (metaheight != 0) { height = MAX<fixed_t> (metaheight, 0); } else { height >>= 2; } // [RH] If the thing has a special, execute and remove it // Note that the thing that killed it is considered // the activator of the script. // New: In Hexen, the thing that died is the activator, // so now a level flag selects who the activator gets to be. // Everything is now moved to P_ActivateThingSpecial(). if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER)) && !(activationtype & THINGSPEC_NoDeathSpecial)) { P_ActivateThingSpecial(this, source, true); } if (CountsAsKill()) level.killed_monsters++; if (source && source->player) { if (CountsAsKill()) { // count for intermission source->player->killcount++; } // Don't count any frags at level start, because they're just telefrags // resulting from insufficient deathmatch starts, and it wouldn't be // fair to count them toward a player's score. if (player && level.maptime) { source->player->frags[player - players]++; if (player == source->player) // [RH] Cumulative frag count { char buff[256]; player->fragcount--; if (deathmatch && player->spreecount >= 5 && cl_showsprees) { SexMessage (GStrings("SPREEKILLSELF"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), player->userinfo.GetName()); StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } else { if ((dmflags2 & DF2_YES_LOSEFRAG) && deathmatch) player->fragcount--; ++source->player->fragcount; ++source->player->spreecount; if (source->player->morphTics) { // Make a super chicken source->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2)); } if (deathmatch && cl_showsprees) { const char *spreemsg; char buff[256]; switch (source->player->spreecount) { case 5: spreemsg = GStrings("SPREE5"); break; case 10: spreemsg = GStrings("SPREE10"); break; case 15: spreemsg = GStrings("SPREE15"); break; case 20: spreemsg = GStrings("SPREE20"); break; case 25: spreemsg = GStrings("SPREE25"); break; default: spreemsg = NULL; break; } if (spreemsg == NULL && player->spreecount >= 5) { if (!AnnounceSpreeLoss (this)) { SexMessage (GStrings("SPREEOVER"), buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } else if (spreemsg != NULL) { if (!AnnounceSpree (source)) { SexMessage (spreemsg, buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } } } // [RH] Multikills if (player != source->player) { source->player->multicount++; if (source->player->lastkilltime > 0) { if (source->player->lastkilltime < level.time - 3*TICRATE) { source->player->multicount = 1; } if (deathmatch && source->CheckLocalView (consoleplayer) && cl_showmultikills) { const char *multimsg; switch (source->player->multicount) { case 1: multimsg = NULL; break; case 2: multimsg = GStrings("MULTI2"); break; case 3: multimsg = GStrings("MULTI3"); break; case 4: multimsg = GStrings("MULTI4"); break; default: multimsg = GStrings("MULTI5"); break; } if (multimsg != NULL) { char buff[256]; if (!AnnounceMultikill (source)) { SexMessage (multimsg, buff, player->userinfo.GetGender(), player->userinfo.GetName(), source->player->userinfo.GetName()); StatusBar->AttachMessage (new DHUDMessageFadeOut (SmallFont, buff, 1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L')); } } } } source->player->lastkilltime = level.time; } // [RH] Implement fraglimit if (deathmatch && fraglimit && fraglimit <= D_GetFragCount (source->player)) { Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); G_ExitLevel (0, false); } } } else if (!multiplayer && CountsAsKill()) { // count all monster deaths, // even those caused by other monsters players[0].killcount++; } if (player) { // [RH] Death messages ClientObituary (this, inflictor, source, dmgflags); // Death script execution, care of Skull Tag FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true); // [RH] Force a delay between death and respawn player->respawn_time = level.time + TICRATE; //Added by MC: Respawn bots if (bglobal.botnum && !demoplayback) { if (player->Bot != NULL) player->Bot->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1; //Added by MC: Discard enemies. for (int i = 0; i < MAXPLAYERS; i++) { if (players[i].Bot != NULL && this == players[i].Bot->enemy) { if (players[i].Bot->dest == players[i].Bot->enemy) players[i].Bot->dest = NULL; players[i].Bot->enemy = NULL; } } player->spreecount = 0; player->multicount = 0; } // count environment kills against you if (!source) { player->frags[player - players]++; player->fragcount--; // [RH] Cumulative frag count } flags &= ~MF_SOLID; player->playerstate = PST_DEAD; P_DropWeapon (player); if (this == players[consoleplayer].camera && automapactive) { // don't die in auto map, switch view prior to dying AM_Stop (); } // [GRB] Clear extralight. When you killed yourself with weapon that // called A_Light1/2 before it called A_Light0, extraligh remained. player->extralight = 0; } // [RH] If this is the unmorphed version of another monster, destroy this // actor, because the morphed version is the one that will stick around in // the level. if (flags & MF_UNMORPHED) { Destroy (); return; } FState *diestate = NULL; int gibhealth = GibHealth(); ActorFlags4 iflags4 = inflictor == NULL ? ActorFlags4::FromInt(0) : inflictor->flags4; bool extremelydead = ((health < gibhealth || iflags4 & MF4_EXTREMEDEATH) && !(iflags4 & MF4_NOEXTREMEDEATH)); // Special check for 'extreme' damage type to ensure that it gets recorded properly as an extreme death for subsequent checks. if (DamageType == NAME_Extreme) { extremelydead = true; DamageType = NAME_None; } // find the appropriate death state. The order is: // // 1. If damagetype is not 'none' and death is extreme, try a damage type specific extreme death state // 2. If no such state is found or death is not extreme try a damage type specific normal death state // 3. If damagetype is 'ice' and actor is a monster or player, try the generic freeze death (unless prohibited) // 4. If no state has been found and death is extreme, try the extreme death state // 5. If no such state is found or death is not extreme try the regular death state. // 6. If still no state has been found, destroy the actor immediately. if (DamageType != NAME_None) { if (extremelydead) { FName labels[] = { NAME_Death, NAME_Extreme, DamageType }; diestate = FindState(3, labels, true); } if (diestate == NULL) { diestate = FindState (NAME_Death, DamageType, true); if (diestate != NULL) extremelydead = false; } if (diestate == NULL) { if (DamageType == NAME_Ice) { // If an actor doesn't have an ice death, we can still give them a generic one. if (!deh.NoAutofreeze && !(flags4 & MF4_NOICEDEATH) && (player || (flags3 & MF3_ISMONSTER))) { diestate = FindState(NAME_GenericFreezeDeath); extremelydead = false; } } } } if (diestate == NULL) { // Don't pass on a damage type this actor cannot handle. // (most importantly, prevent barrels from passing on ice damage.) // Massacre must be preserved though. if (DamageType != NAME_Massacre) { DamageType = NAME_None; } if (extremelydead) { // Extreme death diestate = FindState (NAME_Death, NAME_Extreme, true); } if (diestate == NULL) { // Normal death extremelydead = false; diestate = FindState (NAME_Death); } } if (extremelydead) { // We'll only get here if an actual extreme death state was used. // For players, mark the appropriate flag. if (player != NULL) { player->cheats |= CF_EXTREMELYDEAD; } // If a non-player, mark as extremely dead for the crash state. else if (health >= gibhealth) { health = gibhealth - 1; } } if (diestate != NULL) { SetState (diestate); if (tics > 1) { tics -= pr_killmobj() & 3; if (tics < 1) tics = 1; } } else { Destroy(); } }
void P_KillMobj(mobj_t *source, mobj_t *target, dd_bool stomping) { mobjtype_t item; mobj_t* mo; unsigned int an; angle_t angle; if(!target) return; // Nothing to kill... target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY); if(target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->corpseTics = 0; target->height /= 2*2; if(source && source->player) { // Count for intermission. if(target->flags & MF_COUNTKILL) { source->player->killCount++; source->player->update |= PSF_COUNTERS; } if(target->player) { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); NetSv_KillMessage(source->player, target->player, stomping); } } else if(!IS_NETGAME && (target->flags & MF_COUNTKILL)) { // Count all monster deaths (even those caused by other monsters). players[0].killCount++; } if(target->player) { // Count environment kills against the player. if(!source) { target->player->frags[target->player - players]++; NetSv_FragsForAll(target->player); NetSv_KillMessage(target->player, target->player, stomping); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->update |= PSF_STATE; target->player->plr->flags |= DDPF_DEAD; P_DropWeapon(target->player); // Don't die with the automap open. ST_AutomapOpen(target->player - players, false, false); #if __JHERETIC__ || __JHEXEN__ Hu_InventoryOpen(target->player - players, false); #endif } if(target->health < -target->info->spawnHealth && P_GetState(target->type, SN_XDEATH)) { // Extreme death. P_MobjChangeState(target, P_GetState(target->type, SN_XDEATH)); } else { // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; if(target->tics < 1) target->tics = 1; // Enemies in Chex Quest don't drop stuff. if(gameMode == doom_chex) return; // 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; } // Don't drop at the exact same place, causes Z flickering with // 3D sprites. angle = P_Random() << 24; an = angle >> ANGLETOFINESHIFT; if((mo = P_SpawnMobjXYZ(item, target->origin[VX] + 3 * FIX2FLT(finecosine[an]), target->origin[VY] + 3 * FIX2FLT(finesine[an]), 0, angle, MSF_Z_FLOOR))) mo->flags |= MF_DROPPED; // Special versions of items. }
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_GRAVITY))) { target->flags |= MF_GRAVITY; } 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-players]++; } } else if(!netgame && (target->flags & MF_COUNTKILL)) { // count all monster deaths, // even those caused by other monsters players[0].killcount++; } if(target->player) { // count environment kills against you if(!source) { target->player->frags[target->player-players]++; } target->flags &= ~MF_SOLID; target->player->playerstate = PST_DEAD; P_DropWeapon(target->player); deathmocktics = gametic; if(target->player == &players[consoleplayer] && automapactive) { // don't die in auto map, // switch view prior to dying AM_Stop(); } // 20120123 villsa - obituaries! if(netgame) { P_Obituary(source, target); } } if(target->health < -target->info->spawnhealth && target->info->xdeathstate) { P_SetMobjState(target, target->info->xdeathstate); } else { P_SetMobjState(target, target->info->deathstate); } target->tics -= P_Random(pr_killtics)&3; if(target->tics < 1) { target->tics = 1; } // Drop stuff. // This determines the kind of object spawned // during the death frame of a thing. switch(target->type) { case MT_POSSESSED1: item = MT_AMMO_CLIP; break; case MT_POSSESSED2: item = MT_WEAP_SHOTGUN; break; default: return; } mo = P_SpawnMobj(target->x,target->y,ONFLOORZ, item); mo->flags |= MF_DROPPED; // special versions of items }
void AActor::Die (AActor *source, AActor *inflictor) { // [SO] 9/2/02 -- It's rather funny to see an exploded player body with the invuln sparkle active :) effects &= ~FX_RESPAWNINVUL; //flags &= ~MF_INVINCIBLE; if (debugfile && this->player) { static int dieticks[MAXPLAYERS]; int pnum = this->player-players; if (dieticks[pnum] == gametic) gametic=gametic; dieticks[pnum] = gametic; fprintf (debugfile, "died (%d) on tic %d (%s)\n", pnum, gametic, this->player->cheats&CF_PREDICTING?"predicting":"real"); } if (flags & MF_MISSILE) { // [RH] When missiles die, they just explode P_ExplodeMissile (this, NULL); return; } // [RH] Set the target to the thing that killed it. Strife apparently does this. if (source != NULL) { target = source; } flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); if (!(flags4 & MF4_DONTFALL)) flags&=~MF_NOGRAVITY; flags |= MF_DROPOFF; if (flags3 & MF3_ISMONSTER) { // [RH] Only monsters get to be corpses. flags |= MF_CORPSE; } // [RH] Allow the death height to be overridden using metadata. fixed_t metaheight = 0; if (DamageType == MOD_FIRE) { metaheight = GetClass()->Meta.GetMetaFixed (AMETA_BurnHeight); } if (metaheight == 0) { metaheight = GetClass()->Meta.GetMetaFixed (AMETA_DeathHeight); } if (metaheight != 0) { height = MAX<fixed_t> (metaheight, 0); } else { height >>= 2; } // [RH] If the thing has a special, execute and remove it // Note that the thing that killed it is considered // the activator of the script. // New: In Hexen, the thing that died is the activator, // so now a level flag selects who the activator gets to be. if (special && (!(flags & MF_SPECIAL) || (flags3 & MF3_ISMONSTER))) { LineSpecials[special] (NULL, level.flags & LEVEL_ACTOWNSPECIAL ? this : source, false, args[0], args[1], args[2], args[3], args[4]); special = 0; } if (source && source->player) { if (flags & MF_COUNTKILL) { // count for intermission source->player->killcount++; level.killed_monsters++; } // Don't count any frags at level start, because they're just telefrags // resulting from insufficient deathmatch starts, and it wouldn't be // fair to count them toward a player's score. if (player && level.time) { source->player->frags[player - players]++; if (player == source->player) // [RH] Cumulative frag count { char buff[256]; player->fragcount--; if (deathmatch && player->spreecount >= 5 && cl_showsprees) { SexMessage (GStrings("SPREEKILLSELF"), buff, player->userinfo.gender, player->userinfo.netname, player->userinfo.netname); StatusBar->AttachMessage (new DHUDMessageFadeOut (buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } else { ++source->player->fragcount; ++source->player->spreecount; if (source->player->morphTics) { // Make a super chicken source->GiveInventoryType (RUNTIME_CLASS(APowerWeaponLevel2)); } if (deathmatch && cl_showsprees) { const char *spreemsg; char buff[256]; switch (source->player->spreecount) { case 5: spreemsg = GStrings("SPREE5"); break; case 10: spreemsg = GStrings("SPREE10"); break; case 15: spreemsg = GStrings("SPREE15"); break; case 20: spreemsg = GStrings("SPREE20"); break; case 25: spreemsg = GStrings("SPREE25"); break; default: spreemsg = NULL; break; } if (spreemsg == NULL && player->spreecount >= 5) { if (!AnnounceSpreeLoss (this)) { SexMessage (GStrings("SPREEOVER"), buff, player->userinfo.gender, player->userinfo.netname, source->player->userinfo.netname); StatusBar->AttachMessage (new DHUDMessageFadeOut (buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } else if (spreemsg != NULL) { if (!AnnounceSpree (source)) { SexMessage (spreemsg, buff, player->userinfo.gender, player->userinfo.netname, source->player->userinfo.netname); StatusBar->AttachMessage (new DHUDMessageFadeOut (buff, 1.5f, 0.2f, 0, 0, CR_WHITE, 3.f, 0.5f), MAKE_ID('K','S','P','R')); } } } } // [RH] Multikills source->player->multicount++; if (source->player->lastkilltime > 0) { if (source->player->lastkilltime < level.time - 3*TICRATE) { source->player->multicount = 1; } if (deathmatch && source->CheckLocalView (consoleplayer) && cl_showmultikills) { const char *multimsg; switch (source->player->multicount) { case 1: multimsg = NULL; break; case 2: multimsg = GStrings("MULTI2"); break; case 3: multimsg = GStrings("MULTI3"); break; case 4: multimsg = GStrings("MULTI4"); break; default: multimsg = GStrings("MULTI5"); break; } if (multimsg != NULL) { char buff[256]; if (!AnnounceMultikill (source)) { SexMessage (multimsg, buff, player->userinfo.gender, player->userinfo.netname, source->player->userinfo.netname); StatusBar->AttachMessage (new DHUDMessageFadeOut (buff, 1.5f, 0.8f, 0, 0, CR_RED, 3.f, 0.5f), MAKE_ID('M','K','I','L')); } } } } source->player->lastkilltime = level.time; // [RH] Implement fraglimit if (deathmatch && fraglimit && fraglimit == D_GetFragCount (source->player)) { Printf ("%s\n", GStrings("TXT_FRAGLIMIT")); G_ExitLevel (0, false); } } } else if (!multiplayer && (flags & MF_COUNTKILL)) { // count all monster deaths, // even those caused by other monsters players[0].killcount++; level.killed_monsters++; } if (player) { // [RH] Death messages ClientObituary (this, inflictor, source); // Death script execution, care of Skull Tag FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true); // [RH] Force a delay between death and respawn player->respawn_time = level.time + TICRATE; //Added by MC: Respawn bots if (bglobal.botnum && consoleplayer == Net_Arbitrator && !demoplayback) { if (player->isbot) player->t_respawn = (pr_botrespawn()%15)+((bglobal.botnum-1)*2)+TICRATE+1; //Added by MC: Discard enemies. for (int i = 0; i < MAXPLAYERS; i++) { if (players[i].isbot && this == players[i].enemy) { if (players[i].dest == players[i].enemy) players[i].dest = NULL; players[i].enemy = NULL; } } player->spreecount = 0; player->multicount = 0; } // count environment kills against you if (!source) { player->frags[player - players]++; player->fragcount--; // [RH] Cumulative frag count } flags &= ~MF_SOLID; player->playerstate = PST_DEAD; P_DropWeapon (player); if (this == players[consoleplayer].camera && automapactive) { // don't die in auto map, switch view prior to dying AM_Stop (); } } // [RH] If this is the unmorphed version of another monster, destroy this // actor, because the morphed version is the one that will stick around in // the level. if (flags & MF_UNMORPHED) { Destroy (); return; } if (DamageType == MOD_DISINTEGRATE && EDeathState) { // Electrocution death SetState (EDeathState); } else if (DamageType == MOD_FIRE && BDeathState) { // Burn death SetState (BDeathState); } else if (DamageType == MOD_ICE && (IDeathState || ( (!deh.NoAutofreeze && !(flags4 & MF4_NOICEDEATH)) && (player || (flags3 & MF3_ISMONSTER))))) { // Ice death flags |= MF_ICECORPSE; if (IDeathState) { SetState (IDeathState); } else { SetState (&AActor::States[S_GENERICFREEZEDEATH]); } } else if (XDeathState && health < (gameinfo.gametype == GAME_Doom ? -GetDefault()->health : -GetDefault()->health/2)) { // Extreme death SetState (XDeathState); } else { // Normal death DamageType = MOD_UNKNOWN; // [RH] "Frozen" barrels shouldn't do freezing damage if (DeathState != NULL) // [RH] DeathState might be NULL, so try others as needed { SetState (DeathState); } else if (EDeathState != NULL) { SetState (EDeathState); } else if (BDeathState != NULL) { SetState (BDeathState); } else if (IDeathState != NULL) { SetState (IDeathState); } } tics -= pr_killmobj() & 3; if (tics < 1) tics = 1; }