mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-16 09:11:21 +00:00
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.
This commit is contained in:
parent
6c64a4403c
commit
3033fafaa7
8 changed files with 44 additions and 23 deletions
|
@ -626,10 +626,13 @@ public:
|
|||
double plyrdmgfact = Pawn->DamageFactor;
|
||||
Pawn->DamageFactor = 1.;
|
||||
P_DamageMobj (Pawn, Pawn, Pawn, TELEFRAG_DAMAGE, NAME_Suicide);
|
||||
Pawn->DamageFactor = plyrdmgfact;
|
||||
if (Pawn->health <= 0)
|
||||
if (Pawn != nullptr)
|
||||
{
|
||||
Pawn->flags &= ~MF_SHOOTABLE;
|
||||
Pawn->DamageFactor = plyrdmgfact;
|
||||
if (Pawn->health <= 0)
|
||||
{
|
||||
Pawn->flags &= ~MF_SHOOTABLE;
|
||||
}
|
||||
}
|
||||
Destroy();
|
||||
}
|
||||
|
|
|
@ -465,7 +465,6 @@ xx(MonsterClass)
|
|||
xx(MorphedMonster)
|
||||
xx(Wi_NoAutostartMap)
|
||||
|
||||
xx(MorphFlags)
|
||||
xx(Duration)
|
||||
xx(MorphStyle)
|
||||
xx(MorphFlash)
|
||||
|
|
|
@ -26,6 +26,8 @@ enum
|
|||
MORPH_UNDOBYTIMEOUT = 0x00001000, // Player unmorphs once countdown expires
|
||||
MORPH_UNDOALWAYS = 0x00002000, // Powerups must always unmorph, no matter what.
|
||||
MORPH_TRANSFERTRANSLATION = 0x00004000, // Transfer translation from the original actor to the morphed one
|
||||
MORPH_KEEPARMOR = 0x00008000, // Don't lose current armor value when morphing.
|
||||
MORPH_IGNOREINVULN = 0x00010000, // Completely ignore invulnerability status on players.
|
||||
|
||||
MORPH_STANDARDUNDOING = MORPH_UNDOBYTOMEOFPOWER | MORPH_UNDOBYCHAOSDEVICE | MORPH_UNDOBYTIMEOUT,
|
||||
};
|
||||
|
|
|
@ -324,14 +324,23 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
|||
{
|
||||
// Return values are no longer used to ensure things stay properly managed.
|
||||
AActor* const realMo = alternative;
|
||||
const int morphStyle = player != nullptr ? player->MorphStyle : IntVar(NAME_MorphFlags);
|
||||
int morphStyle = 0;
|
||||
|
||||
VMValue params[] = { this };
|
||||
|
||||
{
|
||||
IFVM(Actor, GetMorphStyle)
|
||||
{
|
||||
VMReturn ret[] = { &morphStyle };
|
||||
VMCall(func, params, 1, ret, 1);
|
||||
}
|
||||
}
|
||||
|
||||
VMCall(func, params, 1, nullptr, 0);
|
||||
|
||||
// Kill the dummy Actor if it didn't unmorph, otherwise checking the morph flags. Player pawns need
|
||||
// to stay, otherwise they won't respawn correctly.
|
||||
if (realMo != nullptr
|
||||
if (realMo != nullptr && !(realMo->flags6 & MF6_KILLED)
|
||||
&& ((alternative != nullptr && player == nullptr) || (alternative == nullptr && !(morphStyle & MORPH_UNDOBYDEATHSAVES))))
|
||||
{
|
||||
if (wasgibbed)
|
||||
|
@ -345,6 +354,11 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags, FName MeansOf
|
|||
realMo->health = 0;
|
||||
}
|
||||
|
||||
// Pass appropriate damage information along when it's confirmed to die.
|
||||
realMo->DamageTypeReceived = DamageTypeReceived;
|
||||
realMo->DamageType = DamageType;
|
||||
realMo->special1 = special1;
|
||||
|
||||
realMo->CallDie(source, inflictor, dmgflags, MeansOfDeath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ extend class Actor
|
|||
// when a morphed Actor dies.
|
||||
virtual Actor, int, int MorphedDeath()
|
||||
{
|
||||
EMorphFlags mStyle = player ? player.MorphStyle : MorphFlags;
|
||||
EMorphFlags mStyle = GetMorphStyle();
|
||||
if (mStyle & MRF_UNDOBYDEATH)
|
||||
Unmorph(self, force: mStyle & MRF_UNDOBYDEATHFORCED);
|
||||
|
||||
|
|
|
@ -426,29 +426,34 @@ extend class PlayerPawn
|
|||
}
|
||||
|
||||
|
||||
virtual String CheatMorph(class<PlayerPawn> morphClass, bool quickundo)
|
||||
virtual String CheatMorph(class<PlayerPawn> morphClass, bool undo)
|
||||
{
|
||||
let oldclass = GetClass();
|
||||
|
||||
// Set the standard morph style for the current game
|
||||
int style = MRF_UNDOBYTOMEOFPOWER;
|
||||
if (gameinfo.gametype == GAME_Hexen) style |= MRF_UNDOBYCHAOSDEVICE;
|
||||
EMorphFlags style = MRF_UNDOBYTOMEOFPOWER;
|
||||
if (GameInfo.GameType == GAME_Hexen)
|
||||
style |= MRF_UNDOBYCHAOSDEVICE;
|
||||
|
||||
if (Alternative)
|
||||
{
|
||||
if (Unmorph (self))
|
||||
class<PlayerPawn> cls = GetClass();
|
||||
Actor mo = Alternative;
|
||||
if (!undo || Unmorph(self))
|
||||
{
|
||||
if (!quickundo && oldclass != morphclass && Morph(self, morphclass, null, 0, style))
|
||||
if ((!undo && Morph(self, morphClass, null, 0, style))
|
||||
|| (undo && morphClass != cls && mo.Morph(mo, morphClass, null, 0, style)))
|
||||
{
|
||||
return StringTable.Localize("$TXT_STRANGER");
|
||||
}
|
||||
return StringTable.Localize("$TXT_NOTSTRANGE");
|
||||
|
||||
if (undo)
|
||||
return StringTable.Localize("$TXT_NOTSTRANGE");
|
||||
}
|
||||
}
|
||||
else if (Morph (self, morphclass, null, 0, style))
|
||||
else if (Morph(self, morphClass, null, 0, style))
|
||||
{
|
||||
return StringTable.Localize("$TXT_STRANGE");
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
@ -98,7 +98,7 @@ extend class PlayerPawn
|
|||
virtual bool MorphPlayer(PlayerInfo activator, class<PlayerPawn> spawnType, int duration, EMorphFlags style, class<Actor> enterFlash = "TeleportFog", class<Actor> exitFlash = "TeleportFog")
|
||||
{
|
||||
if (!player || !spawnType || bDontMorph || player.Health <= 0
|
||||
|| (bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE))))
|
||||
|| (!(style & MRF_IGNOREINVULN) && bInvulnerable && (player != activator || !(style & MRF_WHENINVULNERABLE))))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -106,10 +106,10 @@ extend class PlayerPawn
|
|||
if (!duration)
|
||||
duration = DEFMORPHTICS;
|
||||
|
||||
if (Alternative)
|
||||
if (spawnType == GetClass())
|
||||
{
|
||||
// Player is already a beast.
|
||||
if (bCanSuperMorph && spawnType == GetClass()
|
||||
if (Alternative && bCanSuperMorph
|
||||
&& GetMorphTics() < duration - TICRATE
|
||||
&& !FindInventory("PowerWeaponLevel2", true))
|
||||
{
|
||||
|
@ -120,9 +120,6 @@ extend class PlayerPawn
|
|||
return false;
|
||||
}
|
||||
|
||||
if (spawnType == GetClass())
|
||||
return false;
|
||||
|
||||
let morphed = PlayerPawn(Spawn(spawnType, Pos, NO_REPLACE));
|
||||
if (!MorphInto(morphed))
|
||||
{
|
||||
|
@ -228,7 +225,7 @@ extend class PlayerPawn
|
|||
if (!Alternative || bStayMorphed || Alternative.bStayMorphed)
|
||||
return false;
|
||||
|
||||
if (bInvulnerable
|
||||
if (!(unmorphFlags & MRF_IGNOREINVULN) && bInvulnerable
|
||||
&& (player != activator || (!(player.MorphStyle & MRF_WHENINVULNERABLE) && !(unmorphFlags & MRF_STANDARDUNDOING))))
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -233,6 +233,7 @@ enum EMorphFlags
|
|||
MRF_UNDOALWAYS = 0x00002000,
|
||||
MRF_TRANSFERTRANSLATION = 0x00004000,
|
||||
MRF_KEEPARMOR = 0x00008000,
|
||||
MRF_IGNOREINVULN = 0x00010000,
|
||||
MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue