Skip to content

Commit 6c64a44

Browse files
Boondorlmadame-rachelle
authored andcommitted
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.
1 parent 12dc5c1 commit 6c64a44

File tree

6 files changed

+124
-47
lines changed

6 files changed

+124
-47
lines changed

wadsrc/static/zscript/actors/heretic/hereticartifacts.zs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ Class ArtiTomeOfPower : PowerupGiver
6868

6969
override bool Use(bool pickup)
7070
{
71-
EMorphFlags mStyle = Owner.player ? Owner.player.MorphStyle : Owner.MorphFlags;
71+
EMorphFlags mStyle = Owner.GetMorphStyle();
7272
if (Owner.Alternative && (mStyle & MRF_UNDOBYTOMEOFPOWER))
7373
{
7474
// Attempt to undo chicken.

wadsrc/static/zscript/actors/inventory/powerups.zs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1928,12 +1928,10 @@ class PowerMorph : Powerup
19281928

19291929
// Abort if owner is dead; their Die() method will
19301930
// take care of any required unmorphing on death.
1931-
if (MorphedPlayer ? MorphedPlayer.Health <= 0 : Owner.Health <= 0)
1931+
if (Owner.player ? Owner.player.Health <= 0 : Owner.Health <= 0)
19321932
return;
19331933

1934-
EMorphFlags mStyle = MorphedPlayer ? MorphedPlayer.MorphStyle : MorphStyle;
1935-
1936-
Owner.Unmorph(Owner, force: mStyle & MRF_UNDOALWAYS);
1934+
Owner.Unmorph(Owner, force: Owner.GetMorphStyle() & MRF_UNDOALWAYS);
19371935
MorphedPlayer = null;
19381936
}
19391937
}

wadsrc/static/zscript/actors/morph.zs

Lines changed: 87 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,69 @@
2323

2424
extend class Actor
2525
{
26+
// Blockmap, sector, and no interaction are the only relevant flags but the old ones are kept around
27+
// for legacy reasons.
2628
enum EPremorphProperty
2729
{
28-
MPROP_SOLID = 1 << 1,
29-
MPROP_SHOOTABLE = 1 << 2,
30-
MPROP_INVIS = 1 << 6,
30+
MPROP_SOLID = 1 << 1,
31+
MPROP_SHOOTABLE = 1 << 2,
32+
MPROP_NO_BLOCKMAP = 1 << 3,
33+
MPROP_NO_SECTOR = 1 << 4,
34+
MPROP_NO_INTERACTION = 1 << 5,
35+
MPROP_INVIS = 1 << 6,
3136
}
3237

3338
int UnmorphTime;
3439
EMorphFlags MorphFlags;
3540
class<Actor> MorphExitFlash;
3641
EPremorphProperty PremorphProperties;
3742

43+
// Players still track these separately for legacy reasons.
44+
void SetMorphStyle(EMorphFlags flags)
45+
{
46+
if (player)
47+
player.MorphStyle = flags;
48+
else
49+
MorphFlags = flags;
50+
}
51+
52+
clearscope EMorphFlags GetMorphStyle() const
53+
{
54+
return player ? player.MorphStyle : MorphFlags;
55+
}
56+
57+
void SetMorphExitFlash(class<Actor> flash)
58+
{
59+
if (player)
60+
player.MorphExitFlash = flash;
61+
else
62+
MorphExitFlash = flash;
63+
}
64+
65+
clearscope class<Actor> GetMorphExitFlash() const
66+
{
67+
return player ? player.MorphExitFlash : MorphExitFlash;
68+
}
69+
70+
void SetMorphTics(int dur)
71+
{
72+
if (player)
73+
player.MorphTics = dur;
74+
else
75+
UnmorphTime = Level.Time + dur;
76+
}
77+
78+
clearscope int GetMorphTics() const
79+
{
80+
if (player)
81+
return player.MorphTics;
82+
83+
if (UnmorphTime <= 0)
84+
return UnmorphTime;
85+
86+
return UnmorphTime > Level.Time ? UnmorphTime - Level.Time : 0;
87+
}
88+
3889
// This function doesn't return anything anymore since allowing so would be too volatile
3990
// for morphing management. Instead it's now a function that lets special actions occur
4091
// when a morphed Actor dies.
@@ -113,8 +164,12 @@ extend class Actor
113164
Actor morphed = Spawn(spawnType, Pos, ALLOW_REPLACE);
114165
if (!MorphInto(morphed))
115166
{
116-
morphed.ClearCounters();
117-
morphed.Destroy();
167+
if (morphed)
168+
{
169+
morphed.ClearCounters();
170+
morphed.Destroy();
171+
}
172+
118173
return false;
119174
}
120175

@@ -146,30 +201,39 @@ extend class Actor
146201
morphed.CopyFriendliness(self, true);
147202

148203
// Remove all armor.
149-
for (Inventory item = morphed.Inv; item;)
204+
if (!(style & MRF_KEEPARMOR))
150205
{
151-
Inventory next = item.Inv;
152-
if (item is "Armor")
153-
item.DepleteOrDestroy();
206+
for (Inventory item = morphed.Inv; item;)
207+
{
208+
Inventory next = item.Inv;
209+
if (item is "Armor")
210+
item.DepleteOrDestroy();
154211

155-
item = next;
212+
item = next;
213+
}
156214
}
157215

158-
morphed.UnmorphTime = Level.Time + (duration ? duration : DEFMORPHTICS) + Random[morphmonst]();
159-
morphed.MorphFlags = style;
160-
morphed.MorphExitFlash = exitFlash;
161-
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) | (bInvisible * MPROP_INVIS);
216+
morphed.SetMorphTics((duration ? duration : DEFMORPHTICS) + Random[morphmonst]());
217+
morphed.SetMorphStyle(style);
218+
morphed.SetMorphExitFlash(exitFlash);
219+
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE)
220+
| (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR)
221+
| (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS);
162222

163223
// This is just here for backwards compatibility as MorphedMonster used to be required.
164224
let morphMon = MorphedMonster(morphed);
165225
if (morphMon)
166226
{
167227
morphMon.UnmorphedMe = morphMon.Alternative;
168-
morphMon.MorphStyle = morphMon.MorphFlags;
228+
morphMon.MorphStyle = morphMon.GetMorphStyle();
169229
morphMon.FlagsSave = morphMon.PremorphProperties;
170230
}
171231

172232
Special = 0;
233+
bNoInteraction = true;
234+
A_ChangeLinkFlags(true, true);
235+
236+
// Legacy
173237
bInvisible = true;
174238
bSolid = bShootable = false;
175239

@@ -219,7 +283,7 @@ extend class Actor
219283
// Didn't fit.
220284
if (!res)
221285
{
222-
UnmorphTime = Level.Time + 5*TICRATE; // Next try in 5 seconds.
286+
SetMorphTics(5 * TICRATE);
223287
return false;
224288
}
225289
}
@@ -249,7 +313,11 @@ extend class Actor
249313
alt.Vel = Vel;
250314
alt.Score = Score;
251315

252-
if (TID && (MorphFlags & MRF_NEWTIDBEHAVIOUR))
316+
alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION);
317+
alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR));
318+
319+
EMorphFlags style = GetMorphStyle();
320+
if (TID && (style & MRF_NEWTIDBEHAVIOUR))
253321
{
254322
alt.ChangeTID(TID);
255323
ChangeTID(0);
@@ -262,14 +330,12 @@ extend class Actor
262330
alt.Tracer = Tracer;
263331
alt.Master = Master;
264332
alt.CopyFriendliness(self, true, false);
265-
if (Health > 0 || (MorphFlags & MRF_UNDOBYDEATHSAVES))
333+
if (Health > 0 || (style & MRF_UNDOBYDEATHSAVES))
266334
alt.Health = alt.SpawnHealth();
267335
else
268336
alt.Health = Health;
269337

270338
Special = 0;
271-
bInvisible = true;
272-
bSolid = bShootable = false;
273339

274340
PostUnmorph(alt, false); // From is false here: Leaving the caller's body.
275341
alt.PostUnmorph(self, true); // True here: Entering this body from here.
@@ -347,7 +413,7 @@ class MorphedMonster : Actor
347413
override bool UndoMonsterMorph(bool force)
348414
{
349415
Alternative = UnmorphedMe;
350-
MorphFlags = MorphStyle;
416+
SetMorphStyle(MorphStyle);
351417
PremorphProperties = FlagsSave;
352418
return super.UndoMonsterMorph(force);
353419
}

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

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ extend class PlayerPawn
110110
{
111111
// Player is already a beast.
112112
if (bCanSuperMorph && spawnType == GetClass()
113-
&& player.MorphTics < duration - TICRATE
113+
&& GetMorphTics() < duration - TICRATE
114114
&& !FindInventory("PowerWeaponLevel2", true))
115115
{
116116
// Make a super chicken.
@@ -126,7 +126,9 @@ extend class PlayerPawn
126126
let morphed = PlayerPawn(Spawn(spawnType, Pos, NO_REPLACE));
127127
if (!MorphInto(morphed))
128128
{
129-
morphed.Destroy();
129+
if (morphed)
130+
morphed.Destroy();
131+
130132
return false;
131133
}
132134

@@ -155,36 +157,46 @@ extend class PlayerPawn
155157
}
156158

157159
// special2 is no longer used here since Actors now have a proper field for it.
158-
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE) | (bInvisible * MPROP_INVIS);
160+
morphed.PremorphProperties = (bSolid * MPROP_SOLID) | (bShootable * MPROP_SHOOTABLE)
161+
| (bNoBlockmap * MPROP_NO_BLOCKMAP) | (bNoSector * MPROP_NO_SECTOR)
162+
| (bNoInteraction * MPROP_NO_INTERACTION) | (bInvisible * MPROP_INVIS);
163+
159164
morphed.bShadow |= bShadow;
160165
morphed.bNoGravity |= bNoGravity;
161166
morphed.bFly |= bFly;
162167
morphed.bGhost |= bGhost;
163168

164169
// Remove all armor.
165-
for (Inventory item = morphed.Inv; item;)
170+
if (!(style & MRF_KEEPARMOR))
166171
{
167-
Inventory next = item.Inv;
168-
if (item is "Armor")
169-
item.DepleteOrDestroy();
172+
for (Inventory item = morphed.Inv; item;)
173+
{
174+
Inventory next = item.Inv;
175+
if (item is "Armor")
176+
item.DepleteOrDestroy();
170177

171-
item = next;
178+
item = next;
179+
}
172180
}
173181

174182
// Players store their morph behavior into their PlayerInfo unlike regular Actors which use the
175183
// morph properties. This is needed for backwards compatibility and to give the HUD info.
176184
let p = morphed.player;
177-
p.MorphTics = duration;
185+
morphed.SetMorphTics(duration);
186+
morphed.SetMorphStyle(style);
187+
morphed.SetMorphExitFlash(exitFlash);
178188
p.MorphedPlayerClass = spawnType;
179-
p.MorphStyle = style;
180-
p.MorphExitFlash = exitFlash;
181189
p.PremorphWeapon = p.ReadyWeapon;
182190
p.Health = morphed.Health;
183191
p.Vel = (0.0, 0.0);
184192
// If the new view height is higher than the old one, start moving toward it.
185193
if (morphed.ViewHeight > p.ViewHeight && !p.DeltaViewHeight)
186194
p.DeltaViewHeight = p.GetDeltaViewHeight();
187195

196+
bNoInteraction = true;
197+
A_ChangeLinkFlags(true, true);
198+
199+
// Legacy
188200
bSolid = bShootable = false;
189201
bInvisible = true;
190202

@@ -242,7 +254,7 @@ extend class PlayerPawn
242254

243255
if (!res)
244256
{
245-
player.MorphTics = 2 * TICRATE;
257+
SetMorphTics(2 * TICRATE);
246258
return false;
247259
}
248260
}
@@ -284,9 +296,12 @@ extend class PlayerPawn
284296
alt.bFly = bFly;
285297
alt.Vel = (0.0, 0.0, Vel.Z);
286298

299+
alt.bNoInteraction = (PremorphProperties & MPROP_NO_INTERACTION);
300+
alt.A_ChangeLinkFlags((PremorphProperties & MPROP_NO_BLOCKMAP), (PremorphProperties & MPROP_NO_SECTOR));
301+
287302
let p = alt.player;
288-
class<Actor> exitFlash = p.MorphExitFlash;
289-
EMorphFlags style = p.MorphStyle;
303+
class<Actor> exitFlash = alt.GetMorphExitFlash();
304+
EMorphFlags style = alt.GetMorphStyle();
290305
Weapon premorphWeap = p.PremorphWeapon;
291306

292307
if (TID && (style & MRF_NEWTIDBEHAVIOUR))
@@ -295,10 +310,10 @@ extend class PlayerPawn
295310
ChangeTID(0);
296311
}
297312

298-
p.MorphTics = 0;
313+
alt.SetMorphTics(0);
314+
alt.SetMorphStyle(0);
315+
alt.SetMorphExitFlash(null);
299316
p.MorphedPlayerClass = null;
300-
p.MorphStyle = 0;
301-
p.MorphExitFlash = null;
302317
p.PremorphWeapon = null;
303318
p.ViewHeight = alt.ViewHeight;
304319
p.Vel = (0.0, 0.0);
@@ -347,9 +362,6 @@ extend class PlayerPawn
347362
alt.ClearFOVInterpolation();
348363
alt.InitAllPowerupEffects();
349364

350-
bInvisible = true;
351-
bSolid = bShootable = false;
352-
353365
PostUnmorph(alt, false); // This body is no longer current.
354366
alt.PostUnmorph(self, true); // altmo body is current.
355367

wadsrc/static/zscript/actors/raven/artitele.zs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class ArtiTeleport : Inventory
3838
Owner.Teleport(dest, destAngle, TELF_SOURCEFOG | TELF_DESTFOG);
3939

4040
bool canLaugh = Owner.player != null;
41-
EMorphFlags mStyle = Owner.player ? Owner.player.MorphStyle : Owner.MorphFlags;
41+
EMorphFlags mStyle = Owner.GetMorphStyle();
4242
if (Owner.Alternative && (mStyle & MRF_UNDOBYCHAOSDEVICE))
4343
{
4444
// Teleporting away will undo any morph effects (pig).

wadsrc/static/zscript/constants.zs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ enum EMorphFlags
232232
MRF_UNDOBYTIMEOUT = 0x00001000,
233233
MRF_UNDOALWAYS = 0x00002000,
234234
MRF_TRANSFERTRANSLATION = 0x00004000,
235+
MRF_KEEPARMOR = 0x00008000,
235236
MRF_STANDARDUNDOING = MRF_UNDOBYTOMEOFPOWER | MRF_UNDOBYCHAOSDEVICE | MRF_UNDOBYTIMEOUT,
236237
};
237238

0 commit comments

Comments
 (0)