mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- added a Boom (strict) compatibility mode.
- Restored some original Doom behavior that received complaints from users: * reactivated the old sliding against diagonal walls code and compatibility optioned it with COMPATF_WALLRUN. * re-added the original hitscan checking code using a cross-section of the actor instead of the bounding box, compatibility optioned with COMPATF_HITSCAN. SVN r2340 (trunk)
This commit is contained in:
parent
9dfdf2ecdd
commit
8f881be0fb
6 changed files with 171 additions and 100 deletions
|
@ -116,6 +116,7 @@ static FCompatOption Options[] =
|
||||||
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
|
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
|
||||||
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
|
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
|
||||||
{ "spritesort", COMPATF_SPRITESORT, 0 },
|
{ "spritesort", COMPATF_SPRITESORT, 0 },
|
||||||
|
{ "hitscan", COMPATF_HITSCAN, 0 },
|
||||||
{ NULL, 0, 0 }
|
{ NULL, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -500,7 +500,8 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
|
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
|
||||||
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
|
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
|
||||||
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
|
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
|
||||||
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS;
|
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|
|
||||||
|
COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: // Boom compat mode
|
case 3: // Boom compat mode
|
||||||
|
@ -516,6 +517,11 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||||
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 6: // Boom with some added settings to reenable spme 'broken' behavior
|
||||||
|
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MISSILECLIP|COMPATF_NO_PASSMOBJ|
|
||||||
|
COMPATF_INVISIBILITY|COMPATF_CORPSEGIBS|COMPATF_HITSCAN|COMPATF_WALLRUN|COMPATF_NOTOSSDROPS;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
compatflags = v;
|
compatflags = v;
|
||||||
}
|
}
|
||||||
|
@ -548,6 +554,7 @@ CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
|
||||||
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
||||||
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
|
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
|
||||||
CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT);
|
CVAR (Flag, compat_spritesort, compatflags,COMPATF_SPRITESORT);
|
||||||
|
CVAR (Flag, compat_hitscan, compatflags,COMPATF_HITSCAN);
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
|
|
|
@ -325,6 +325,7 @@ enum
|
||||||
COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs.
|
COMPATF_CORPSEGIBS = 1 << 25, // Crushed monsters are turned into gibs, rather than replaced by gibs.
|
||||||
COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines.
|
COMPATF_NOBLOCKFRIENDS = 1 << 26, // Friendly monsters aren't blocked by monster-blocking lines.
|
||||||
COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance
|
COMPATF_SPRITESORT = 1 << 27, // Invert sprite sorting order for sprites of equal distance
|
||||||
|
COMPATF_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Emulate old bugs for select maps. These are not exposed by a cvar
|
// Emulate old bugs for select maps. These are not exposed by a cvar
|
||||||
|
|
|
@ -149,13 +149,14 @@ value_t OffOn[2] = {
|
||||||
{ 1.0, "Off" }
|
{ 1.0, "Off" }
|
||||||
};
|
};
|
||||||
|
|
||||||
value_t CompatModes[6] = {
|
value_t CompatModes[] = {
|
||||||
{ 0.0, "Default" },
|
{ 0.0, "Default" },
|
||||||
{ 1.0, "Doom" },
|
{ 1.0, "Doom" },
|
||||||
{ 2.0, "Doom (strict)" },
|
{ 2.0, "Doom (strict)" },
|
||||||
{ 3.0, "Boom" },
|
{ 3.0, "Boom" },
|
||||||
{ 4.0, "ZDoom 2.0.63" },
|
{ 6.0, "Boom (strict)" },
|
||||||
{ 5.0, "MBF" },
|
{ 5.0, "MBF" },
|
||||||
|
{ 4.0, "ZDoom 2.0.63" },
|
||||||
};
|
};
|
||||||
|
|
||||||
menu_t *CurrentMenu;
|
menu_t *CurrentMenu;
|
||||||
|
@ -1092,7 +1093,7 @@ static menu_t DMFlagsMenu =
|
||||||
*=======================================*/
|
*=======================================*/
|
||||||
|
|
||||||
static menuitem_t CompatibilityItems[] = {
|
static menuitem_t CompatibilityItems[] = {
|
||||||
{ discrete, "Compatibility mode", {&compatmode}, {6.0}, {1.0}, {0.0}, {CompatModes} },
|
{ discrete, "Compatibility mode", {&compatmode}, {7.0}, {1.0}, {0.0}, {CompatModes} },
|
||||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||||
{ bitflag, "Find shortest textures like Doom", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SHORTTEX} },
|
{ bitflag, "Find shortest textures like Doom", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SHORTTEX} },
|
||||||
{ bitflag, "Use buggier stair building", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_STAIRINDEX} },
|
{ bitflag, "Use buggier stair building", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_STAIRINDEX} },
|
||||||
|
@ -1122,6 +1123,7 @@ static menuitem_t CompatibilityItems[] = {
|
||||||
{ bitflag, "Crushed monsters can be resurrected", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CORPSEGIBS} },
|
{ bitflag, "Crushed monsters can be resurrected", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CORPSEGIBS} },
|
||||||
{ bitflag, "Friendly monsters aren't blocked", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOBLOCKFRIENDS} },
|
{ bitflag, "Friendly monsters aren't blocked", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOBLOCKFRIENDS} },
|
||||||
{ bitflag, "Invert sprite sorting", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SPRITESORT} },
|
{ bitflag, "Invert sprite sorting", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SPRITESORT} },
|
||||||
|
{ bitflag, "Use Doom code for hitscan checks", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_HITSCAN} },
|
||||||
|
|
||||||
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
|
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
|
||||||
};
|
};
|
||||||
|
|
|
@ -2183,48 +2183,53 @@ void FSlide::HitSlideLine (line_t* ld)
|
||||||
} // ^
|
} // ^
|
||||||
else // |
|
else // |
|
||||||
{ // phares
|
{ // phares
|
||||||
#if 0
|
// Doom's original algorithm here does not work well due to imprecisions of the sine table.
|
||||||
fixed_t newlen;
|
// However, keep it active if the wallrunning compatibility flag is on
|
||||||
|
if (i_compatflags & COMPATF_WALLRUN)
|
||||||
if (deltaangle > ANG180)
|
|
||||||
deltaangle += ANG180;
|
|
||||||
// I_Error ("SlideLine: ang>ANG180");
|
|
||||||
|
|
||||||
lineangle >>= ANGLETOFINESHIFT;
|
|
||||||
deltaangle >>= ANGLETOFINESHIFT;
|
|
||||||
|
|
||||||
newlen = FixedMul (movelen, finecosine[deltaangle]);
|
|
||||||
|
|
||||||
tmxmove = FixedMul (newlen, finecosine[lineangle]);
|
|
||||||
tmymove = FixedMul (newlen, finesine[lineangle]);
|
|
||||||
#else
|
|
||||||
divline_t dll, dlv;
|
|
||||||
fixed_t inter1, inter2, inter3;
|
|
||||||
|
|
||||||
P_MakeDivline (ld, &dll);
|
|
||||||
|
|
||||||
dlv.x = slidemo->x;
|
|
||||||
dlv.y = slidemo->y;
|
|
||||||
dlv.dx = dll.dy;
|
|
||||||
dlv.dy = -dll.dx;
|
|
||||||
|
|
||||||
inter1 = P_InterceptVector(&dll, &dlv);
|
|
||||||
|
|
||||||
dlv.dx = tmxmove;
|
|
||||||
dlv.dy = tmymove;
|
|
||||||
inter2 = P_InterceptVector (&dll, &dlv);
|
|
||||||
inter3 = P_InterceptVector (&dlv, &dll);
|
|
||||||
|
|
||||||
if (inter3 != 0)
|
|
||||||
{
|
{
|
||||||
tmxmove = Scale (inter2-inter1, dll.dx, inter3);
|
fixed_t newlen;
|
||||||
tmymove = Scale (inter2-inter1, dll.dy, inter3);
|
|
||||||
|
if (deltaangle > ANG180)
|
||||||
|
deltaangle += ANG180;
|
||||||
|
// I_Error ("SlideLine: ang>ANG180");
|
||||||
|
|
||||||
|
lineangle >>= ANGLETOFINESHIFT;
|
||||||
|
deltaangle >>= ANGLETOFINESHIFT;
|
||||||
|
|
||||||
|
newlen = FixedMul (movelen, finecosine[deltaangle]);
|
||||||
|
|
||||||
|
tmxmove = FixedMul (newlen, finecosine[lineangle]);
|
||||||
|
tmymove = FixedMul (newlen, finesine[lineangle]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmxmove = tmymove = 0;
|
divline_t dll, dlv;
|
||||||
|
fixed_t inter1, inter2, inter3;
|
||||||
|
|
||||||
|
P_MakeDivline (ld, &dll);
|
||||||
|
|
||||||
|
dlv.x = slidemo->x;
|
||||||
|
dlv.y = slidemo->y;
|
||||||
|
dlv.dx = dll.dy;
|
||||||
|
dlv.dy = -dll.dx;
|
||||||
|
|
||||||
|
inter1 = P_InterceptVector(&dll, &dlv);
|
||||||
|
|
||||||
|
dlv.dx = tmxmove;
|
||||||
|
dlv.dy = tmymove;
|
||||||
|
inter2 = P_InterceptVector (&dll, &dlv);
|
||||||
|
inter3 = P_InterceptVector (&dlv, &dll);
|
||||||
|
|
||||||
|
if (inter3 != 0)
|
||||||
|
{
|
||||||
|
tmxmove = Scale (inter2-inter1, dll.dx, inter3);
|
||||||
|
tmymove = Scale (inter2-inter1, dll.dy, inter3);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmxmove = tmymove = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} // phares
|
} // phares
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
173
src/p_maputl.cpp
173
src/p_maputl.cpp
|
@ -970,81 +970,136 @@ void FPathTraverse::AddThingIntercepts (int bx, int by, FBlockThingsIterator &it
|
||||||
divline_t line;
|
divline_t line;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// [RH] Don't check a corner to corner crossection for hit.
|
|
||||||
// Instead, check against the actual bounding box.
|
|
||||||
|
|
||||||
// There's probably a smarter way to determine which two sides
|
if (!(i_compatflags & COMPATF_HITSCAN))
|
||||||
// of the thing face the trace than by trying all four sides...
|
|
||||||
for (i = 0; i < 4; ++i)
|
|
||||||
{
|
{
|
||||||
switch (i)
|
// [RH] Don't check a corner to corner crossection for hit.
|
||||||
|
// Instead, check against the actual bounding box (but not if compatibility optioned.)
|
||||||
|
|
||||||
|
// There's probably a smarter way to determine which two sides
|
||||||
|
// of the thing face the trace than by trying all four sides...
|
||||||
|
for (i = 0; i < 4; ++i)
|
||||||
{
|
{
|
||||||
case 0: // Top edge
|
switch (i)
|
||||||
line.x = thing->x + thing->radius;
|
|
||||||
line.y = thing->y + thing->radius;
|
|
||||||
line.dx = -thing->radius * 2;
|
|
||||||
line.dy = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: // Right edge
|
|
||||||
line.x = thing->x + thing->radius;
|
|
||||||
line.y = thing->y - thing->radius;
|
|
||||||
line.dx = 0;
|
|
||||||
line.dy = thing->radius * 2;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: // Bottom edge
|
|
||||||
line.x = thing->x - thing->radius;
|
|
||||||
line.y = thing->y - thing->radius;
|
|
||||||
line.dx = thing->radius * 2;
|
|
||||||
line.dy = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: // Left edge
|
|
||||||
line.x = thing->x - thing->radius;
|
|
||||||
line.y = thing->y + thing->radius;
|
|
||||||
line.dx = 0;
|
|
||||||
line.dy = thing->radius * -2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Check if this side is facing the trace origin
|
|
||||||
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
|
|
||||||
{
|
|
||||||
numfronts++;
|
|
||||||
|
|
||||||
// If it is, see if the trace crosses it
|
|
||||||
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
|
||||||
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
|
||||||
{
|
{
|
||||||
// It's a hit
|
case 0: // Top edge
|
||||||
fixed_t frac = P_InterceptVector (&trace, &line);
|
line.x = thing->x + thing->radius;
|
||||||
if (frac < 0)
|
line.y = thing->y + thing->radius;
|
||||||
{ // behind source
|
line.dx = -thing->radius * 2;
|
||||||
|
line.dy = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // Right edge
|
||||||
|
line.x = thing->x + thing->radius;
|
||||||
|
line.y = thing->y - thing->radius;
|
||||||
|
line.dx = 0;
|
||||||
|
line.dy = thing->radius * 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Bottom edge
|
||||||
|
line.x = thing->x - thing->radius;
|
||||||
|
line.y = thing->y - thing->radius;
|
||||||
|
line.dx = thing->radius * 2;
|
||||||
|
line.dy = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Left edge
|
||||||
|
line.x = thing->x - thing->radius;
|
||||||
|
line.y = thing->y + thing->radius;
|
||||||
|
line.dx = 0;
|
||||||
|
line.dy = thing->radius * -2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Check if this side is facing the trace origin
|
||||||
|
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
|
||||||
|
{
|
||||||
|
numfronts++;
|
||||||
|
|
||||||
|
// If it is, see if the trace crosses it
|
||||||
|
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
||||||
|
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
||||||
|
{
|
||||||
|
// It's a hit
|
||||||
|
fixed_t frac = P_InterceptVector (&trace, &line);
|
||||||
|
if (frac < 0)
|
||||||
|
{ // behind source
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
intercept_t newintercept;
|
||||||
|
newintercept.frac = frac;
|
||||||
|
newintercept.isaline = false;
|
||||||
|
newintercept.done = false;
|
||||||
|
newintercept.d.thing = thing;
|
||||||
|
intercepts.Push (newintercept);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If none of the sides was facing the trace, then the trace
|
||||||
|
// must have started inside the box, so add it as an intercept.
|
||||||
|
if (numfronts == 0)
|
||||||
|
{
|
||||||
|
intercept_t newintercept;
|
||||||
|
newintercept.frac = 0;
|
||||||
|
newintercept.isaline = false;
|
||||||
|
newintercept.done = false;
|
||||||
|
newintercept.d.thing = thing;
|
||||||
|
intercepts.Push (newintercept);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Old code for compatibility purposes
|
||||||
|
fixed_t x1, y1, x2, y2;
|
||||||
|
int s1, s2;
|
||||||
|
divline_t dl;
|
||||||
|
fixed_t frac;
|
||||||
|
|
||||||
|
bool tracepositive = (trace.dx ^ trace.dy)>0;
|
||||||
|
|
||||||
|
// check a corner to corner crossection for hit
|
||||||
|
if (tracepositive)
|
||||||
|
{
|
||||||
|
x1 = thing->x - thing->radius;
|
||||||
|
y1 = thing->y + thing->radius;
|
||||||
|
|
||||||
|
x2 = thing->x + thing->radius;
|
||||||
|
y2 = thing->y - thing->radius;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1 = thing->x - thing->radius;
|
||||||
|
y1 = thing->y - thing->radius;
|
||||||
|
|
||||||
|
x2 = thing->x + thing->radius;
|
||||||
|
y2 = thing->y + thing->radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
s1 = P_PointOnDivlineSide (x1, y1, &trace);
|
||||||
|
s2 = P_PointOnDivlineSide (x2, y2, &trace);
|
||||||
|
|
||||||
|
if (s1 != s2)
|
||||||
|
{
|
||||||
|
dl.x = x1;
|
||||||
|
dl.y = y1;
|
||||||
|
dl.dx = x2-x1;
|
||||||
|
dl.dy = y2-y1;
|
||||||
|
|
||||||
|
frac = P_InterceptVector (&trace, &dl);
|
||||||
|
|
||||||
|
if (frac >= 0)
|
||||||
|
{
|
||||||
intercept_t newintercept;
|
intercept_t newintercept;
|
||||||
newintercept.frac = frac;
|
newintercept.frac = frac;
|
||||||
newintercept.isaline = false;
|
newintercept.isaline = false;
|
||||||
newintercept.done = false;
|
newintercept.done = false;
|
||||||
newintercept.d.thing = thing;
|
newintercept.d.thing = thing;
|
||||||
intercepts.Push (newintercept);
|
intercepts.Push (newintercept);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If none of the sides was facing the trace, then the trace
|
|
||||||
// must have started inside the box, so add it as an intercept.
|
|
||||||
if (numfronts == 0)
|
|
||||||
{
|
|
||||||
intercept_t newintercept;
|
|
||||||
newintercept.frac = 0;
|
|
||||||
newintercept.isaline = false;
|
|
||||||
newintercept.done = false;
|
|
||||||
newintercept.d.thing = thing;
|
|
||||||
intercepts.Push (newintercept);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue