- MBF21: implemented new line flags.

While 'block players' was just a simple remap, 'block land monsters' required quite a bit of work...
This also fixes the bug that BLOCK_FLOATERS was never checked for sliding against a wall.
This commit is contained in:
Christoph Oelckers 2021-06-28 20:17:08 +02:00
parent 057cc0678b
commit c4ed0cefde
15 changed files with 65 additions and 35 deletions

View file

@ -393,7 +393,6 @@ Note: All <bool> fields default to false unless mentioned otherwise.
Bit 5 (Value 32): midtex3d
Bit 6 (Value 64): checkswitchrange
Bit 7 (Value 128): firstsideonly
When used in special 208 this arg should be cleared afterward.
Special 121 is not being used by UDMF maps in ZDoom and should be completely
@ -508,6 +507,9 @@ Replaced tabs with spaces.
1.31 22.12.2019
Coloriation options added
1.32 28.06.2021
Blocklandmonsters MBF21 flag
===============================================================================
EOF
===============================================================================

View file

@ -495,6 +495,7 @@ xx(Blockeverything)
xx(Zoneboundary)
xx(Jumpover)
xx(Blockfloaters)
xx(Blocklandmonsters)
xx(Clipmidtex)
xx(Wrapmidtex)
xx(Midtex3d)

View file

@ -128,7 +128,7 @@ struct maplinedef2_t
// LineDef attributes.
//
enum ELineFlags : unsigned
enum ELineFlags : uint32_t
{
ML_BLOCKING =0x00000001, // solid, is an obstacle
ML_BLOCKMONSTERS =0x00000002, // blocks monsters only
@ -176,6 +176,8 @@ enum ELineFlags : unsigned
ML_REVEALED = 0x20000000, // set if revealed in automap
ML_DRAWFULLHEIGHT = 0x40000000, // Draw the full height of the upper/lower sections
ML_PORTALCONNECT = 0x80000000, // for internal use only: This line connects to a sector with a linked portal (used to speed up sight checks.)
// Flag words may not exceed 32 bit due to VM limitations.
ML2_BLOCKLANDMONSTERS = 0x1, // MBF21
};

View file

@ -68,6 +68,7 @@ void FLevelLocals::TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineinde
uint32_t flags1 = flags;
uint32_t newflags = 0;
uint32_t newflags2 = 0;
for(int i=0;i<16;i++)
{
@ -80,7 +81,8 @@ void FLevelLocals::TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineinde
{
if ((flags1 & (1<<i)) && !translator->LineFlagTranslations[i].ismask)
{
switch (translator->LineFlagTranslations[i].newvalue)
unsigned val = translator->LineFlagTranslations[i].newvalue;
switch ((int)val)
{
case -1:
passthrough = true;
@ -92,12 +94,14 @@ void FLevelLocals::TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineinde
ld->alpha = 0.25;
break;
default:
newflags |= translator->LineFlagTranslations[i].newvalue;
if ((val & 0x80000000) && val != 0x80000000) newflags2 |= val;
else newflags |= val;
break;
}
}
}
flags = newflags;
ld->flags2 = newflags2;
if (lineindexforid >= 0)
{

View file

@ -1438,7 +1438,7 @@ struct line_t
{
vertex_t *v1, *v2; // vertices, from v1 to v2
DVector2 delta; // precalculated v2 - v1 for side checking
uint32_t flags;
uint32_t flags, flags2;
uint32_t activation; // activation type
int special;
int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)

View file

@ -928,6 +928,12 @@ public:
Flag(ld->flags, ML_BLOCK_FLOATERS, key);
continue;
case NAME_Blocklandmonsters:
// This is from MBF21 so it may later be needed for a lower level namespace.
CHECK_N(St | Zd | Zdt | Va)
Flag(ld->flags2, ML2_BLOCKLANDMONSTERS, key);
continue;
case NAME_Translucent:
CHECK_N(St | Zd | Zdt | Va)
strifetrans = CheckBool(key);

View file

@ -75,6 +75,7 @@ FSerializer &Serialize(FSerializer &arc, const char *key, line_t &line, line_t *
if (arc.BeginObject(key))
{
arc("flags", line.flags, def->flags)
("flags2", line.flags2, def->flags2)
("activation", line.activation, def->activation)
("special", line.special, def->special)
("alpha", line.alpha, def->alpha)

View file

@ -178,3 +178,33 @@ inline bool AActor::isFrozen() const
return false;
}
// Consolidated from all (incomplete) variants that check if a line should block.
inline bool P_IsBlockedByLine(AActor* actor, line_t* line)
{
// Keep this stuff readable - so no chained and nested 'if's!
// Unconditional blockers.
if (line->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) return true;
// MBF considers that friendly monsters are not blocked by monster-blocking lines.
// This is added here as a compatibility option. Note that monsters that are dehacked
// into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this
// just optionally generalizes the behavior to other friendly monsters.
if (!((actor->flags3 & MF3_NOBLOCKMONST)
|| ((actor->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (actor->flags & MF_FRIENDLY))))
{
// the regular 'blockmonsters' flag.
if (line->flags & ML_BLOCKMONSTERS) return true;
// MBF21's flag for walking monsters
if ((line->flags2 & ML2_BLOCKLANDMONSTERS) && !(actor->flags & MF_FLOAT)) return true;
}
// Blocking players
if (((actor->player != nullptr) || (actor->flags8 & MF8_BLOCKASPLAYER)) && (line->flags & ML_BLOCK_PLAYERS)) return true;
// Blocking floaters.
if ((actor->flags & MF_FLOAT) && (line->flags & ML_BLOCK_FLOATERS)) return true;
return false;
}

View file

@ -849,12 +849,6 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
// MBF bouncers are treated as missiles here.
bool Projectile = (tm.thing->flags & MF_MISSILE || tm.thing->BounceFlags & BOUNCE_MBF);
// MBF considers that friendly monsters are not blocked by monster-blocking lines.
// This is added here as a compatibility option. Note that monsters that are dehacked
// into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this
// just optionally generalizes the behavior to other friendly monsters.
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|| ((tm.thing->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE;
if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING;
@ -865,11 +859,8 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
{
rail = true;
}
else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
(((tm.thing->player != NULL) || (tm.thing->flags8 & MF8_BLOCKASPLAYER)) && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
else if (P_IsBlockedByLine(tm.thing, ld) ||
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)))
{
if (cres.portalflags & FFCF_NOFLOOR)
{
@ -3002,19 +2993,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end)
}
goto isblocking;
}
if (li->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING))
{
goto isblocking;
}
if (li->flags & ML_BLOCK_PLAYERS && ((slidemo->player != NULL) || (slidemo->flags8 & MF8_BLOCKASPLAYER)))
{
goto isblocking;
}
if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST)
|| ((slidemo->Level->i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY))))
{
goto isblocking;
}
if (P_IsBlockedByLine(slidemo, li)) goto isblocking;
// set openrange, opentop, openbottom
P_LineOpening(open, slidemo, li, it.InterceptPoint(in));

View file

@ -1080,11 +1080,7 @@ bool FPolyObj::CheckMobjBlocking (side_t *sd)
open.top = LINEOPEN_MAX;
open.bottom = LINEOPEN_MIN;
// [TN] Check wether this actor gets blocked by the line.
if (ld->backsector != nullptr &&
!(ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING))
&& !(ld->flags & ML_BLOCK_PLAYERS && (mobj->player || (mobj->flags8 & MF8_BLOCKASPLAYER)))
&& !(ld->flags & ML_BLOCKMONSTERS && mobj->flags3 & MF3_ISMONSTER)
&& !((mobj->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))
if (ld->backsector != nullptr && !P_IsBlockedByLine(mobj, ld)
&& (!(ld->flags & ML_3DMIDTEX) ||
(!P_LineOpening_3dMidtex(mobj, ld, open) &&
(mobj->Top() < open.top)

View file

@ -2768,6 +2768,7 @@ DEFINE_FIELD_X(Line, line_t, v1)
DEFINE_FIELD_X(Line, line_t, v2)
DEFINE_FIELD_X(Line, line_t, delta)
DEFINE_FIELD_X(Line, line_t, flags)
DEFINE_FIELD_X(Line, line_t, flags2)
DEFINE_FIELD_X(Line, line_t, activation)
DEFINE_FIELD_X(Line, line_t, special)
DEFINE_FIELD_X(Line, line_t, args)

View file

@ -88,7 +88,7 @@ const char *GetVersionString();
// Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got.
#define SAVEVER 4558
#define SAVEVER 4559
// This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "GZDOOM"

View file

@ -236,6 +236,7 @@ enum
ML_FIRSTSIDEONLY = 0x00800000,
ML_BLOCKPROJECTILE = 0x01000000,
ML_BLOCKUSE = 0x02000000,
ML_BLOCKLANDMONSTERS = 0x80000001, // goes into the second flag word.
//
ML_PASSTHROUGH = -1,

View file

@ -40,3 +40,5 @@ lineflag 8 = ML_MAPPED;
lineflag 9 = ML_PASSTHROUGH;
lineflag 10 = ML_3DMIDTEX;
lineflag 11 & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_TWOSIDED|ML_DONTPEGTOP|ML_DONTPEGBOTTOM|ML_SECRET|ML_SOUNDBLOCK|ML_DONTDRAW|ML_MAPPED);
lineflag 12 = ML_BLOCKLANDMONSTERS;
lineflag 13 = ML_BLOCK_PLAYERS;

View file

@ -162,10 +162,15 @@ struct Line native play
ML_3DMIDTEX_IMPASS = 0x10000000, // [TP] if 3D midtex, behaves like a height-restricted ML_BLOCKING
};
enum ELineFlags2
{
ML2_BLOCKLANDMONSTERS = 1,
}
native readonly vertex v1, v2; // vertices, from v1 to v2
native readonly Vector2 delta; // precalculated v2 - v1 for side checking
native uint flags;
native uint flags2;
native uint activation; // activation type
native int special;
native int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)