- 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 5 (Value 32): midtex3d
Bit 6 (Value 64): checkswitchrange Bit 6 (Value 64): checkswitchrange
Bit 7 (Value 128): firstsideonly Bit 7 (Value 128): firstsideonly
When used in special 208 this arg should be cleared afterward. 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 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 1.31 22.12.2019
Coloriation options added Coloriation options added
1.32 28.06.2021
Blocklandmonsters MBF21 flag
=============================================================================== ===============================================================================
EOF EOF
=============================================================================== ===============================================================================

View file

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

View file

@ -128,7 +128,7 @@ struct maplinedef2_t
// LineDef attributes. // LineDef attributes.
// //
enum ELineFlags : unsigned enum ELineFlags : uint32_t
{ {
ML_BLOCKING =0x00000001, // solid, is an obstacle ML_BLOCKING =0x00000001, // solid, is an obstacle
ML_BLOCKMONSTERS =0x00000002, // blocks monsters only ML_BLOCKMONSTERS =0x00000002, // blocks monsters only
@ -176,6 +176,8 @@ enum ELineFlags : unsigned
ML_REVEALED = 0x20000000, // set if revealed in automap ML_REVEALED = 0x20000000, // set if revealed in automap
ML_DRAWFULLHEIGHT = 0x40000000, // Draw the full height of the upper/lower sections 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.) 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 flags1 = flags;
uint32_t newflags = 0; uint32_t newflags = 0;
uint32_t newflags2 = 0;
for(int i=0;i<16;i++) 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) if ((flags1 & (1<<i)) && !translator->LineFlagTranslations[i].ismask)
{ {
switch (translator->LineFlagTranslations[i].newvalue) unsigned val = translator->LineFlagTranslations[i].newvalue;
switch ((int)val)
{ {
case -1: case -1:
passthrough = true; passthrough = true;
@ -92,12 +94,14 @@ void FLevelLocals::TranslateLineDef (line_t *ld, maplinedef_t *mld, int lineinde
ld->alpha = 0.25; ld->alpha = 0.25;
break; break;
default: default:
newflags |= translator->LineFlagTranslations[i].newvalue; if ((val & 0x80000000) && val != 0x80000000) newflags2 |= val;
else newflags |= val;
break; break;
} }
} }
} }
flags = newflags; flags = newflags;
ld->flags2 = newflags2;
if (lineindexforid >= 0) if (lineindexforid >= 0)
{ {

View file

@ -1438,7 +1438,7 @@ struct line_t
{ {
vertex_t *v1, *v2; // vertices, from v1 to v2 vertex_t *v1, *v2; // vertices, from v1 to v2
DVector2 delta; // precalculated v2 - v1 for side checking DVector2 delta; // precalculated v2 - v1 for side checking
uint32_t flags; uint32_t flags, flags2;
uint32_t activation; // activation type uint32_t activation; // activation type
int special; int special;
int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width) 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); Flag(ld->flags, ML_BLOCK_FLOATERS, key);
continue; 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: case NAME_Translucent:
CHECK_N(St | Zd | Zdt | Va) CHECK_N(St | Zd | Zdt | Va)
strifetrans = CheckBool(key); 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)) if (arc.BeginObject(key))
{ {
arc("flags", line.flags, def->flags) arc("flags", line.flags, def->flags)
("flags2", line.flags2, def->flags2)
("activation", line.activation, def->activation) ("activation", line.activation, def->activation)
("special", line.special, def->special) ("special", line.special, def->special)
("alpha", line.alpha, def->alpha) ("alpha", line.alpha, def->alpha)

View file

@ -178,3 +178,33 @@ inline bool AActor::isFrozen() const
return false; 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. // MBF bouncers are treated as missiles here.
bool Projectile = (tm.thing->flags & MF_MISSILE || tm.thing->BounceFlags & BOUNCE_MBF); 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; uint32_t ProjectileBlocking = ML_BLOCKEVERYTHING | ML_BLOCKPROJECTILE;
if ( tm.thing->flags8 & MF8_BLOCKASPLAYER ) ProjectileBlocking |= ML_BLOCK_PLAYERS | ML_BLOCKING; 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; rail = true;
} }
else if ((ld->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) || // explicitly blocking everything else if (P_IsBlockedByLine(tm.thing, ld) ||
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only ((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)))
(((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
{ {
if (cres.portalflags & FFCF_NOFLOOR) if (cres.portalflags & FFCF_NOFLOOR)
{ {
@ -3002,19 +2993,7 @@ void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end)
} }
goto isblocking; goto isblocking;
} }
if (li->flags & (ML_BLOCKING | ML_BLOCKEVERYTHING)) if (P_IsBlockedByLine(slidemo, li)) goto isblocking;
{
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;
}
// set openrange, opentop, openbottom // set openrange, opentop, openbottom
P_LineOpening(open, slidemo, li, it.InterceptPoint(in)); 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.top = LINEOPEN_MAX;
open.bottom = LINEOPEN_MIN; open.bottom = LINEOPEN_MIN;
// [TN] Check wether this actor gets blocked by the line. // [TN] Check wether this actor gets blocked by the line.
if (ld->backsector != nullptr && if (ld->backsector != nullptr && !P_IsBlockedByLine(mobj, ld)
!(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))
&& (!(ld->flags & ML_3DMIDTEX) || && (!(ld->flags & ML_3DMIDTEX) ||
(!P_LineOpening_3dMidtex(mobj, ld, open) && (!P_LineOpening_3dMidtex(mobj, ld, open) &&
(mobj->Top() < open.top) (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, v2)
DEFINE_FIELD_X(Line, line_t, delta) DEFINE_FIELD_X(Line, line_t, delta)
DEFINE_FIELD_X(Line, line_t, flags) 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, activation)
DEFINE_FIELD_X(Line, line_t, special) DEFINE_FIELD_X(Line, line_t, special)
DEFINE_FIELD_X(Line, line_t, args) 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 // Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got. // 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 // This is so that derivates can use the same savegame versions without worrying about engine compatibility
#define GAMESIG "GZDOOM" #define GAMESIG "GZDOOM"

View file

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

View file

@ -40,3 +40,5 @@ lineflag 8 = ML_MAPPED;
lineflag 9 = ML_PASSTHROUGH; lineflag 9 = ML_PASSTHROUGH;
lineflag 10 = ML_3DMIDTEX; 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 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 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 vertex v1, v2; // vertices, from v1 to v2
native readonly Vector2 delta; // precalculated v2 - v1 for side checking native readonly Vector2 delta; // precalculated v2 - v1 for side checking
native uint flags; native uint flags;
native uint flags2;
native uint activation; // activation type native uint activation; // activation type
native int special; native int special;
native int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width) native int args[5]; // <--- hexen-style arguments (expanded to ZDoom's full width)