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 },
|
||||
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
|
||||
{ "spritesort", COMPATF_SPRITESORT, 0 },
|
||||
{ "hitscan", COMPATF_HITSCAN, 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)
|
||||
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|COMPATF_SPRITESORT|
|
||||
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;
|
||||
|
||||
case 3: // Boom compat mode
|
||||
|
@ -516,6 +517,11 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
|||
COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
||||
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;
|
||||
}
|
||||
|
@ -548,6 +554,7 @@ CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
|
|||
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
||||
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
|
||||
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_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_HITSCAN = 1 << 28, // Hitscans use original blockmap anf hit check code.
|
||||
};
|
||||
|
||||
// Emulate old bugs for select maps. These are not exposed by a cvar
|
||||
|
|
|
@ -149,13 +149,14 @@ value_t OffOn[2] = {
|
|||
{ 1.0, "Off" }
|
||||
};
|
||||
|
||||
value_t CompatModes[6] = {
|
||||
value_t CompatModes[] = {
|
||||
{ 0.0, "Default" },
|
||||
{ 1.0, "Doom" },
|
||||
{ 2.0, "Doom (strict)" },
|
||||
{ 3.0, "Boom" },
|
||||
{ 4.0, "ZDoom 2.0.63" },
|
||||
{ 6.0, "Boom (strict)" },
|
||||
{ 5.0, "MBF" },
|
||||
{ 4.0, "ZDoom 2.0.63" },
|
||||
};
|
||||
|
||||
menu_t *CurrentMenu;
|
||||
|
@ -1092,7 +1093,7 @@ static menu_t DMFlagsMenu =
|
|||
*=======================================*/
|
||||
|
||||
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} },
|
||||
{ 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} },
|
||||
|
@ -1122,6 +1123,7 @@ static menuitem_t CompatibilityItems[] = {
|
|||
{ 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, "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} },
|
||||
};
|
||||
|
|
|
@ -2183,48 +2183,53 @@ void FSlide::HitSlideLine (line_t* ld)
|
|||
} // ^
|
||||
else // |
|
||||
{ // phares
|
||||
#if 0
|
||||
fixed_t newlen;
|
||||
|
||||
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)
|
||||
// Doom's original algorithm here does not work well due to imprecisions of the sine table.
|
||||
// However, keep it active if the wallrunning compatibility flag is on
|
||||
if (i_compatflags & COMPATF_WALLRUN)
|
||||
{
|
||||
tmxmove = Scale (inter2-inter1, dll.dx, inter3);
|
||||
tmymove = Scale (inter2-inter1, dll.dy, inter3);
|
||||
fixed_t newlen;
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
|
|
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;
|
||||
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
|
||||
// of the thing face the trace than by trying all four sides...
|
||||
for (i = 0; i < 4; ++i)
|
||||
if (!(i_compatflags & COMPATF_HITSCAN))
|
||||
{
|
||||
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
|
||||
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))
|
||||
switch (i)
|
||||
{
|
||||
// It's a hit
|
||||
fixed_t frac = P_InterceptVector (&trace, &line);
|
||||
if (frac < 0)
|
||||
{ // behind source
|
||||
case 0: // Top edge
|
||||
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
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = false;
|
||||
newintercept.done = false;
|
||||
newintercept.d.thing = thing;
|
||||
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