Skip to content

Commit 3033faf

Browse files
Boondorlmadame-rachelle
authored andcommitted
Improvements to death and cheat handling
Extra safety to ensure dummy Actor deaths properly emulate a real death and aren't duplicate called. Fixed a crash when using the kill command while set to unmorph on death. Super morphing is now possible while using the morphme cheat if passing the morph class directly. Added a flag to ignore player invulnerability completely when morphing.
1 parent 6c64a44 commit 3033faf

File tree

8 files changed

+44
-23
lines changed

8 files changed

+44
-23
lines changed

src/m_cheat.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -626,10 +626,13 @@ class DSuicider : public DThinker
626626
double plyrdmgfact = Pawn->DamageFactor;
627627
Pawn->DamageFactor = 1.;
628628
P_DamageMobj (Pawn, Pawn, Pawn, TELEFRAG_DAMAGE, NAME_Suicide);
629-
Pawn->DamageFactor = plyrdmgfact;
630-
if (Pawn->health <= 0)
629+
if (Pawn != nullptr)
631630
{
632-
Pawn->flags &= ~MF_SHOOTABLE;
631+
Pawn->DamageFactor = plyrdmgfact;
632+
if (Pawn->health <= 0)
633+
{
634+
Pawn->flags &= ~MF_SHOOTABLE;
635+
}
633636
}
634637
Destroy();
635638
}

src/namedef_custom.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,6 @@ xx(MonsterClass)
465465
xx(MorphedMonster)
466466
xx(Wi_NoAutostartMap)
467467

468-
xx(MorphFlags)
469468
xx(Duration)
470469
xx(MorphStyle)
471470
xx(MorphFlash)

src/playsim/a_morph.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ enum
2626
MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires
2727
MORPH_UNDOALWAYS = 0x00002000, // Powerups must always unmorph, no matter what.
2828
MORPH_TRANSFERTRANSLATION = 0x00004000, // Transfer translation from the original actor to the morphed one
29+
MORPH_KEEPARMOR = 0x00008000, // Don't lose current armor value when morphing.
30+
MORPH_IGNOREINVULN = 0x00010000, // Completely ignore invulnerability status on players.
2931

3032
MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT,
3133
};

src/playsim/p_interaction.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,14 +324,23 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
324324
{
325325
// Return values are no longer used to ensure things stay properly managed.
326326
AActor* const realMo = alternative;
327-
const int morphStyle = player != nullptr ? player->MorphStyle : IntVar(NAME_MorphFlags);
327+
int morphStyle = 0;
328328

329329
VMValue params[] = { this };
330+
331+
{
332+
IFVM(Actor, GetMorphStyle)
333+
{
334+
VMReturn ret[] = { &morphStyle };
335+
VMCall(func, params, 1, ret, 1);
336+
}
337+
}
338+
330339
VMCall(func, params, 1, nullptr, 0);
331340

332341
// Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need
333342
// to stay, otherwise they won't respawn correctly.
334-
if (realMo != nullptr
343+
if (realMo != nullptr && !(realMo->flags6 & MF6_KILLED)
335344
&& ((alternative != nullptr && player == nullptr) || (alternative == nullptr && !(morphStyle & MORPH_UNDOBYDEATHSAVES))))
336345
{
337346
if (wasgibbed)
@@ -345,6 +354,11 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
345354
realMo->health = 0;
346355
}
347356

357+
// Pass appropriate damage information along when it's confirmed to die.
358+
realMo->DamageTypeReceived = DamageTypeReceived;
359+
realMo->DamageType = DamageType;
360+
realMo->special1 = special1;
361+
348362
realMo->CallDie(source, inflictor, dmgflags, MeansOfDeath);
349363
}
350364
}

wadsrc/static/zscript/actors/morph.zs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ extend class Actor
9191
// when a morphed Actor dies.
9292
virtual Actor, int, int MorphedDeath()
9393
{
94-
EMorphFlags mStyle = player ? player.MorphStyle : MorphFlags;
94+
EMorphFlags mStyle = GetMorphStyle();
9595
if (mStyle & MRF_UNDOBYDEATH)
9696
Unmorph(self, force: mStyle & MRF_UNDOBYDEATHFORCED);
9797

wadsrc/static/zscript/actors/player/player_cheat.zs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,29 +426,34 @@ extend class PlayerPawn
426426
}
427427

428428

429-
virtual String CheatMorph(class<PlayerPawn> morphClass, bool quickundo)
429+
virtual String CheatMorph(class<PlayerPawn> morphClass, bool undo)
430430
{
431-
let oldclass = GetClass();
432-
433431
// Set the standard morph style for the current game
434-
int style = MRF_UNDOBYTOMEOFPOWER;
435-
if (gameinfo.gametype == GAME_Hexen) style |= MRF_UNDOBYCHAOSDEVICE;
432+
EMorphFlags style = MRF_UNDOBYTOMEOFPOWER;
433+
if (GameInfo.GameType == GAME_Hexen)
434+
style |= MRF_UNDOBYCHAOSDEVICE;
436435

437436
if (Alternative)
438437
{
439-
if (Unmorph (self))
438+
class<PlayerPawn> cls = GetClass();
439+
Actor mo = Alternative;
440+
if (!undo || Unmorph(self))
440441
{
441-
if (!quickundo && oldclass != morphclass && Morph(self, morphclass, null, 0, style))
442+
if ((!undo && Morph(self, morphClass, null, 0, style))
443+
|| (undo && morphClass != cls && mo.Morph(mo, morphClass, null, 0, style)))
442444
{
443445
return StringTable.Localize("$TXT_STRANGER");
444446
}
445-
return StringTable.Localize("$TXT_NOTSTRANGE");
447+
448+
if (undo)
449+
return StringTable.Localize("$TXT_NOTSTRANGE");
446450
}
447451
}
448-
else if (Morph (self, morphclass, null, 0, style))
452+
else if (Morph(self, morphClass, null, 0, style))
449453
{
450454
return StringTable.Localize("$TXT_STRANGE");
451455
}
456+
452457
return "";
453458
}
454459

wadsrc/static/zscript/actors/player/player_morph.zs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,18 @@ extend class PlayerPawn
9898
virtual bool MorphPlayer(PlayerInfo activator, class<PlayerPawn> spawnType, int duration, EMorphFlags style, class<Actor> enterFlash = "TeleportFog", class<Actor> exitFlash = "TeleportFog")
9999
{
100100
if (!player || !spawnType || bDontMorph || player.Health <= 0
101-
|| (bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE))))
101+
|| (!(style & MRF_IGNOREINVULN) && bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE))))
102102
{
103103
return false;
104104
}
105105

106106
if (!duration)
107107
duration = DEFMORPHTICS;
108108

109-
if (Alternative)
109+
if (spawnType == GetClass())
110110
{
111111
// Player is already a beast.
112-
if (bCanSuperMorph && spawnType == GetClass()
112+
if (Alternative && bCanSuperMorph
113113
&& GetMorphTics() < duration - TICRATE
114114
&& !FindInventory("PowerWeaponLevel2", true))
115115
{
@@ -120,9 +120,6 @@ extend class PlayerPawn
120120
return false;
121121
}
122122

123-
if (spawnType == GetClass())
124-
return false;
125-
126123
let morphed = PlayerPawn(Spawn(spawnType, Pos, NO_REPLACE));
127124
if (!MorphInto(morphed))
128125
{
@@ -228,7 +225,7 @@ extend class PlayerPawn
228225
if (!Alternative || bStayMorphed || Alternative.bStayMorphed)
229226
return false;
230227

231-
if (bInvulnerable
228+
if (!(unmorphFlags & MRF_IGNOREINVULN) && bInvulnerable
232229
&& (player != activator || (!(player.MorphStyle & MRF_WHENINVULNERABLE) && !(unmorphFlags & MRF_STANDARDUNDOING))))
233230
{
234231
return false;

wadsrc/static/zscript/constants.zs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ enum EMorphFlags
233233
MRF_UNDOALWAYS = 0x00002000,
234234
MRF_TRANSFERTRANSLATION = 0x00004000,
235235
MRF_KEEPARMOR = 0x00008000,
236+
MRF_IGNOREINVULN = 0x00010000,
236237
MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT,
237238
};
238239

0 commit comments

Comments
 (0)