mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-03-22 19:01:12 +00:00
Improved ZScript interface for morphing
Added getter and setter functions for handling whether or not the player fields should be gotten/set. Added MRF_KEEPARMOR flag to prevent stripping armor on morph. Optimized unmorphed Actor by setting it to NoInteraction and removing it from the blockmap and sector lists.
This commit is contained in:
parent
12dc5c1506
commit
6c64a4403c
6 changed files with 124 additions and 47 deletions
|
@ -68,7 +68,7 @@ Class ArtiTomeOfPower : PowerupGiver
|
|||
|
||||
override bool Use(bool pickup)
|
||||
{
|
||||
EMorphFlags mStyle = Owner.player ? Owner.player.MorphStyle : Owner.MorphFlags;
|
||||
EMorphFlags mStyle = Owner.GetMorphStyle();
|
||||
if (Owner.Alternative && (mStyle & MRF_UNDOBYTOMEOFPOWER))
|
||||
{
|
||||
// Attempt to undo chicken.
|
||||
|
|
|
@ -1928,12 +1928,10 @@ class PowerMorph : Powerup
|
|||
|
||||
// Abort if owner is dead; their Die() method will
|
||||
// take care of any required unmorphing on death.
|
||||
if (MorphedPlayer ? MorphedPlayer.Health <= 0 : Owner.Health <= 0)
|
||||
if (Owner.player ? Owner.player.Health <= 0 : Owner.Health <= 0)
|
||||
return;
|
||||
|
||||
EMorphFlags mStyle = MorphedPlayer ? MorphedPlayer.MorphStyle : MorphStyle;
|
||||
|
||||
Owner.Unmorph(Owner, force: mStyle & MRF_UNDOALWAYS);
|
||||
Owner.Unmorph(Owner, force: Owner.GetMorphStyle() & MRF_UNDOALWAYS);
|
||||
MorphedPlayer = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,11 +23,16 @@
|
|||
|
||||
extend class Actor
|
||||
{
|
||||
// Blockmap, sector, and no interaction are the only relevant flags but the old ones are kept around
|
||||
// for legacy reasons.
|
||||
enum EPremorphProperty
|
||||
{
|
||||
MPROP_SOLID = 1 << 1,
|
||||
MPROP_SHOOTABLE = 1 << 2,
|
||||
MPROP_INVIS = 1 << 6,
|
||||
MPROP_SOLID = 1 << 1,
|
||||
MPROP_SHOOTABLE = 1 << 2,
|
||||
MPROP_NO_BLOCKMAP = 1 << 3,
|
||||
MPROP_NO_SECTOR = 1 << 4,
|
||||
MPROP_NO_INTERACTION = 1 << 5,
|
||||
MPROP_INVIS = 1 << 6,
|
||||
}
|
||||
|
||||
int UnmorphTime;
|
||||
|
@ -35,6 +40,52 @@ extend class Actor
|
|||
class<Actor> MorphExitFlash;
|
||||
EPremorphProperty PremorphProperties;
|
||||
|
||||
// Players still track these separately for legacy reasons.
|
||||
void SetMorphStyle(EMorphFlags flags)
|
||||
{
|
||||
if (player)
|
||||
player.MorphStyle = flags;
|
||||
else
|
||||
MorphFlags = flags;
|
||||
}
|
||||
|
||||
clearscope EMorphFlags GetMorphStyle() const
|
||||
{
|
||||
return player ? player.MorphStyle : MorphFlags;
|
||||
}
|
||||
|
||||
void SetMorphExitFlash(class<Actor> flash)
|
||||
{
|
||||
if (player)
|
||||
player.MorphExitFlash = flash;
|
||||
else
|
||||
MorphExitFlash = flash;
|
||||
}
|
||||
|
||||
clearscope class<Actor> GetMorphExitFlash() const
|
||||
{
|
||||
return player ? player.MorphExitFlash : MorphExitFlash;
|
||||
}
|
||||
|
||||
void SetMorphTics(int dur)
|
||||
{
|
||||
if (player)
|
||||
player.MorphTics = dur;
|
||||
else
|
||||
UnmorphTime = Level.Time + dur;
|
||||
}
|
||||
|
||||
clearscope int GetMorphTics() const
|
||||
{
|
||||
if (player)
|
||||
return player.MorphTics;
|
||||
|
||||
if (UnmorphTime <= 0)
|
||||
return UnmorphTime;
|
||||
|
||||
return UnmorphTime > Level.Time ? UnmorphTime - Level.Time : 0;
|
||||
}
|
||||
|
||||
// This function doesn't return anything anymore since allowing so would be too volatile
|
||||
// for morphing management. Instead it's now a function that lets special actions occur
|
||||
// when a morphed Actor dies.
|
||||
|
@ -113,8 +164,12 @@ extend class Actor
|
|||
Actor morphed = Spawn(spawnType, Pos, ALLOW_REPLACE);
|
||||
if (!MorphInto(morphed))
|
||||
{
|
||||
morphed.ClearCounters();
|
||||
morphed.Destroy();
|
||||
if (morphed)
|
||||
{
|
||||
morphed.ClearCounters();
|
||||
morphed.Destroy();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -146,30 +201,39 @@ extend class Actor
|
|||
morphed.CopyFriendliness(self, true);
|
||||
|
||||
// Remove all armor.
|
||||
for (Inventory item = morphed.Inv; item;)
|
||||
if (!(style & MRF_KEEPARMOR))
|
||||
{
|
||||
Inventory next = item.Inv;
|
||||
if (item is "Armor")
|
||||
item.DepleteOrDestroy();
|
||||
for (Inventory item = morphed.Inv; item;)
|
||||
{
|
||||
Inventory next = item.Inv;
|
||||
if (item is "Armor")
|
||||
item.DepleteOrDestroy();
|
||||
|
||||
item = next;
|
||||
item = next;
|
||||
}
|
||||
}
|
||||
|
||||
morphed.UnmorphTime = Level.Time + (duration ? duration : DEFMORPHTICS) + Random[morphmonst]();
|
||||
morphed.MorphFlags = style;
|
||||
morphed.MorphExitFlash = exitFlash;
|
||||
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) | (bInvisible * MPROP_INVIS);
|
||||
morphed.SetMorphTics((duration ? duration : DEFMORPHTICS) + Random[morphmonst]());
|
||||
morphed.SetMorphStyle(style);
|
||||
morphed.SetMorphExitFlash(exitFlash);
|
||||
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE)
|
||||
| (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR)
|
||||
| (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS);
|
||||
|
||||
// This is just here for backwards compatibility as MorphedMonster used to be required.
|
||||
let morphMon = MorphedMonster(morphed);
|
||||
if (morphMon)
|
||||
{
|
||||
morphMon.UnmorphedMe = morphMon.Alternative;
|
||||
morphMon.MorphStyle = morphMon.MorphFlags;
|
||||
morphMon.MorphStyle = morphMon.GetMorphStyle();
|
||||
morphMon.FlagsSave = morphMon.PremorphProperties;
|
||||
}
|
||||
|
||||
Special = 0;
|
||||
bNoInteraction = true;
|
||||
A_ChangeLinkFlags(true, true);
|
||||
|
||||
// Legacy
|
||||
bInvisible = true;
|
||||
bSolid = bShootable = false;
|
||||
|
||||
|
@ -219,7 +283,7 @@ extend class Actor
|
|||
// Didn't fit.
|
||||
if (!res)
|
||||
{
|
||||
UnmorphTime = Level.Time + 5*TICRATE; // Next try in 5 seconds.
|
||||
SetMorphTics(5 * TICRATE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +313,11 @@ extend class Actor
|
|||
alt.Vel = Vel;
|
||||
alt.Score = Score;
|
||||
|
||||
if (TID && (MorphFlags & MRF_NEWTIDBEHAVIOUR))
|
||||
alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION);
|
||||
alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR));
|
||||
|
||||
EMorphFlags style = GetMorphStyle();
|
||||
if (TID && (style & MRF_NEWTIDBEHAVIOUR))
|
||||
{
|
||||
alt.ChangeTID(TID);
|
||||
ChangeTID(0);
|
||||
|
@ -262,14 +330,12 @@ extend class Actor
|
|||
alt.Tracer = Tracer;
|
||||
alt.Master = Master;
|
||||
alt.CopyFriendliness(self, true, false);
|
||||
if (Health > 0 || (MorphFlags & MRF_UNDOBYDEATHSAVES))
|
||||
if (Health > 0 || (style & MRF_UNDOBYDEATHSAVES))
|
||||
alt.Health = alt.SpawnHealth();
|
||||
else
|
||||
alt.Health = Health;
|
||||
|
||||
Special = 0;
|
||||
bInvisible = true;
|
||||
bSolid = bShootable = false;
|
||||
|
||||
PostUnmorph(alt, false); // From is false here: Leaving the caller's body.
|
||||
alt.PostUnmorph(self, true); // True here: Entering this body from here.
|
||||
|
@ -347,7 +413,7 @@ class MorphedMonster : Actor
|
|||
override bool UndoMonsterMorph(bool force)
|
||||
{
|
||||
Alternative = UnmorphedMe;
|
||||
MorphFlags = MorphStyle;
|
||||
SetMorphStyle(MorphStyle);
|
||||
PremorphProperties = FlagsSave;
|
||||
return super.UndoMonsterMorph(force);
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ extend class PlayerPawn
|
|||
{
|
||||
// Player is already a beast.
|
||||
if (bCanSuperMorph && spawnType == GetClass()
|
||||
&& player.MorphTics < duration - TICRATE
|
||||
&& GetMorphTics() < duration - TICRATE
|
||||
&& !FindInventory("PowerWeaponLevel2", true))
|
||||
{
|
||||
// Make a super chicken.
|
||||
|
@ -126,7 +126,9 @@ extend class PlayerPawn
|
|||
let morphed = PlayerPawn(Spawn(spawnType, Pos, NO_REPLACE));
|
||||
if (!MorphInto(morphed))
|
||||
{
|
||||
morphed.Destroy();
|
||||
if (morphed)
|
||||
morphed.Destroy();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -155,29 +157,35 @@ extend class PlayerPawn
|
|||
}
|
||||
|
||||
// special2 is no longer used here since Actors now have a proper field for it.
|
||||
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) | (bInvisible * MPROP_INVIS);
|
||||
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE)
|
||||
| (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR)
|
||||
| (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS);
|
||||
|
||||
morphed.bShadow |= bShadow;
|
||||
morphed.bNoGravity |= bNoGravity;
|
||||
morphed.bFly |= bFly;
|
||||
morphed.bGhost |= bGhost;
|
||||
|
||||
// Remove all armor.
|
||||
for (Inventory item = morphed.Inv; item;)
|
||||
if (!(style & MRF_KEEPARMOR))
|
||||
{
|
||||
Inventory next = item.Inv;
|
||||
if (item is "Armor")
|
||||
item.DepleteOrDestroy();
|
||||
for (Inventory item = morphed.Inv; item;)
|
||||
{
|
||||
Inventory next = item.Inv;
|
||||
if (item is "Armor")
|
||||
item.DepleteOrDestroy();
|
||||
|
||||
item = next;
|
||||
item = next;
|
||||
}
|
||||
}
|
||||
|
||||
// Players store their morph behavior into their PlayerInfo unlike regular Actors which use the
|
||||
// morph properties. This is needed for backwards compatibility and to give the HUD info.
|
||||
let p = morphed.player;
|
||||
p.MorphTics = duration;
|
||||
morphed.SetMorphTics(duration);
|
||||
morphed.SetMorphStyle(style);
|
||||
morphed.SetMorphExitFlash(exitFlash);
|
||||
p.MorphedPlayerClass = spawnType;
|
||||
p.MorphStyle = style;
|
||||
p.MorphExitFlash = exitFlash;
|
||||
p.PremorphWeapon = p.ReadyWeapon;
|
||||
p.Health = morphed.Health;
|
||||
p.Vel = (0.0, 0.0);
|
||||
|
@ -185,6 +193,10 @@ extend class PlayerPawn
|
|||
if (morphed.ViewHeight > p.ViewHeight && !p.DeltaViewHeight)
|
||||
p.DeltaViewHeight = p.GetDeltaViewHeight();
|
||||
|
||||
bNoInteraction = true;
|
||||
A_ChangeLinkFlags(true, true);
|
||||
|
||||
// Legacy
|
||||
bSolid = bShootable = false;
|
||||
bInvisible = true;
|
||||
|
||||
|
@ -242,7 +254,7 @@ extend class PlayerPawn
|
|||
|
||||
if (!res)
|
||||
{
|
||||
player.MorphTics = 2 * TICRATE;
|
||||
SetMorphTics(2 * TICRATE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -284,9 +296,12 @@ extend class PlayerPawn
|
|||
alt.bFly = bFly;
|
||||
alt.Vel = (0.0, 0.0, Vel.Z);
|
||||
|
||||
alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION);
|
||||
alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR));
|
||||
|
||||
let p = alt.player;
|
||||
class<Actor> exitFlash = p.MorphExitFlash;
|
||||
EMorphFlags style = p.MorphStyle;
|
||||
class<Actor> exitFlash = alt.GetMorphExitFlash();
|
||||
EMorphFlags style = alt.GetMorphStyle();
|
||||
Weapon premorphWeap = p.PremorphWeapon;
|
||||
|
||||
if (TID && (style & MRF_NEWTIDBEHAVIOUR))
|
||||
|
@ -295,10 +310,10 @@ extend class PlayerPawn
|
|||
ChangeTID(0);
|
||||
}
|
||||
|
||||
p.MorphTics = 0;
|
||||
alt.SetMorphTics(0);
|
||||
alt.SetMorphStyle(0);
|
||||
alt.SetMorphExitFlash(null);
|
||||
p.MorphedPlayerClass = null;
|
||||
p.MorphStyle = 0;
|
||||
p.MorphExitFlash = null;
|
||||
p.PremorphWeapon = null;
|
||||
p.ViewHeight = alt.ViewHeight;
|
||||
p.Vel = (0.0, 0.0);
|
||||
|
@ -347,9 +362,6 @@ extend class PlayerPawn
|
|||
alt.ClearFOVInterpolation();
|
||||
alt.InitAllPowerupEffects();
|
||||
|
||||
bInvisible = true;
|
||||
bSolid = bShootable = false;
|
||||
|
||||
PostUnmorph(alt, false); // This body is no longer current.
|
||||
alt.PostUnmorph(self, true); // altmo body is current.
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ class ArtiTeleport : Inventory
|
|||
Owner.Teleport(dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG);
|
||||
|
||||
bool canLaugh = Owner.player != null;
|
||||
EMorphFlags mStyle = Owner.player ? Owner.player.MorphStyle : Owner.MorphFlags;
|
||||
EMorphFlags mStyle = Owner.GetMorphStyle();
|
||||
if (Owner.Alternative && (mStyle & MRF_UNDOBYCHAOSDEVICE))
|
||||
{
|
||||
// Teleporting away will undo any morph effects (pig).
|
||||
|
|
|
@ -232,6 +232,7 @@ enum EMorphFlags
|
|||
MRF_UNDOBYTIMEOUT = 0x00001000,
|
||||
MRF_UNDOALWAYS = 0x00002000,
|
||||
MRF_TRANSFERTRANSLATION = 0x00004000,
|
||||
MRF_KEEPARMOR = 0x00008000,
|
||||
MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue