mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 05:51:20 +00:00
- fixed sight checking through portals.
Notes: * It is actually not enough to disable the early-out condition for the current block if there's a portal. It must be disabled for the entire rest of the trace because otherwise the collected lines never get processed. * The block bounds check cannot be done globally with portals in the game. The actual trace can easily end up outside the blockmap bounds if portal offsets are factored into the distance between the two actors.
This commit is contained in:
parent
bd29f0994f
commit
2cd74118f6
3 changed files with 36 additions and 16 deletions
|
@ -1217,6 +1217,7 @@ public:
|
||||||
return __pos;
|
return __pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fixedvec3 PosRelative(int grp) const;
|
||||||
fixedvec3 PosRelative(const AActor *other) const;
|
fixedvec3 PosRelative(const AActor *other) const;
|
||||||
fixedvec3 PosRelative(sector_t *sec) const;
|
fixedvec3 PosRelative(sector_t *sec) const;
|
||||||
fixedvec3 PosRelative(line_t *line) const;
|
fixedvec3 PosRelative(line_t *line) const;
|
||||||
|
|
|
@ -97,6 +97,7 @@ class SightCheck
|
||||||
int Flags;
|
int Flags;
|
||||||
divline_t trace;
|
divline_t trace;
|
||||||
int portaldir;
|
int portaldir;
|
||||||
|
bool portalfound;
|
||||||
unsigned int myseethrough;
|
unsigned int myseethrough;
|
||||||
|
|
||||||
void P_SightOpening(SightOpening &open, const line_t *linedef, fixed_t x, fixed_t y);
|
void P_SightOpening(SightOpening &open, const line_t *linedef, fixed_t x, fixed_t y);
|
||||||
|
@ -110,8 +111,8 @@ public:
|
||||||
|
|
||||||
void init(AActor * t1, AActor * t2, sector_t *startsector, SightTask *task, int flags)
|
void init(AActor * t1, AActor * t2, sector_t *startsector, SightTask *task, int flags)
|
||||||
{
|
{
|
||||||
sightstart = t1->PosRelative(startsector);
|
sightstart = t1->PosRelative(task->portalgroup);
|
||||||
sightend = t2->PosRelative(startsector);
|
sightend = t2->PosRelative(task->portalgroup);
|
||||||
sightstart.z += t1->height - (t1->height >> 2);
|
sightstart.z += t1->height - (t1->height >> 2);
|
||||||
|
|
||||||
startfrac = task->frac;
|
startfrac = task->frac;
|
||||||
|
@ -123,6 +124,7 @@ public:
|
||||||
bottomslope = task->bottomslope;
|
bottomslope = task->bottomslope;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
portaldir = task->direction;
|
portaldir = task->direction;
|
||||||
|
portalfound = false;
|
||||||
|
|
||||||
myseethrough = FF_SEETHROUGH;
|
myseethrough = FF_SEETHROUGH;
|
||||||
|
|
||||||
|
@ -251,7 +253,7 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in)
|
||||||
{
|
{
|
||||||
frontsec = li->backsector;
|
frontsec = li->backsector;
|
||||||
if (!frontsec) return false; // We are looking through the backside of a one-sided line. Just abort if that happens.
|
if (!frontsec) return false; // We are looking through the backside of a one-sided line. Just abort if that happens.
|
||||||
backsec = li->backsector;
|
backsec = li->frontsector;
|
||||||
open.SwapSides(); // swap flags to make the next checks simpler.
|
open.SwapSides(); // swap flags to make the next checks simpler.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,17 +454,19 @@ int SightCheck::P_SightBlockLinesIterator (int x, int y)
|
||||||
int offset;
|
int offset;
|
||||||
int *list;
|
int *list;
|
||||||
int res = 1;
|
int res = 1;
|
||||||
bool portals;
|
|
||||||
|
|
||||||
polyblock_t *polyLink;
|
polyblock_t *polyLink;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
extern polyblock_t **PolyBlockMap;
|
extern polyblock_t **PolyBlockMap;
|
||||||
|
|
||||||
offset = y*bmapwidth+x;
|
offset = y*bmapwidth+x;
|
||||||
portals = PortalBlockmap(x, y).containsLinkedPortals;
|
|
||||||
|
// if any of the previous blocks may contain a portal we may abort the collection of lines here, but we may not abort the sight check.
|
||||||
|
// (We still try to delay activating this for as long as possible.)
|
||||||
|
portalfound = portalfound || PortalBlockmap(x, y).containsLinkedPortals;
|
||||||
|
|
||||||
polyLink = PolyBlockMap[offset];
|
polyLink = PolyBlockMap[offset];
|
||||||
portals |= (polyLink && PortalBlockmap.hasLinkedPolyPortals);
|
portalfound |= (polyLink && PortalBlockmap.hasLinkedPolyPortals);
|
||||||
while (polyLink)
|
while (polyLink)
|
||||||
{
|
{
|
||||||
if (polyLink->polyobj)
|
if (polyLink->polyobj)
|
||||||
|
@ -474,7 +478,7 @@ int SightCheck::P_SightBlockLinesIterator (int x, int y)
|
||||||
{
|
{
|
||||||
if (!P_SightCheckLine(polyLink->polyobj->Linedefs[i]))
|
if (!P_SightCheckLine(polyLink->polyobj->Linedefs[i]))
|
||||||
{
|
{
|
||||||
if (!portals) return 0;
|
if (!portalfound) return 0;
|
||||||
else res = -1;
|
else res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,7 +493,7 @@ int SightCheck::P_SightBlockLinesIterator (int x, int y)
|
||||||
{
|
{
|
||||||
if (!P_SightCheckLine (&lines[*list]))
|
if (!P_SightCheckLine (&lines[*list]))
|
||||||
{
|
{
|
||||||
if (!portals) return 0;
|
if (!portalfound) return 0;
|
||||||
else res = -1;
|
else res = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,6 +527,11 @@ bool SightCheck::P_SightTraverseIntercepts ()
|
||||||
scan = &intercepts[scanpos];
|
scan = &intercepts[scanpos];
|
||||||
P_MakeDivline (scan->d.line, &dl);
|
P_MakeDivline (scan->d.line, &dl);
|
||||||
scan->frac = P_InterceptVector (&trace, &dl);
|
scan->frac = P_InterceptVector (&trace, &dl);
|
||||||
|
if (scan->frac < startfrac)
|
||||||
|
{
|
||||||
|
scan->frac = FIXED_MAX;
|
||||||
|
count--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -646,12 +655,6 @@ bool SightCheck::P_SightPathTraverse ()
|
||||||
xt2 = int(_x2 >> MAPBLOCKSHIFT);
|
xt2 = int(_x2 >> MAPBLOCKSHIFT);
|
||||||
yt2 = int(_y2 >> MAPBLOCKSHIFT);
|
yt2 = int(_y2 >> MAPBLOCKSHIFT);
|
||||||
|
|
||||||
// points should never be out of bounds, but check once instead of
|
|
||||||
// each block
|
|
||||||
if (xt1<0 || yt1<0 || xt1>=bmapwidth || yt1>=bmapheight
|
|
||||||
|| xt2<0 || yt2<0 || xt2>=bmapwidth || yt2>=bmapheight)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (xt2 > xt1)
|
if (xt2 > xt1)
|
||||||
{
|
{
|
||||||
mapxstep = 1;
|
mapxstep = 1;
|
||||||
|
@ -722,10 +725,16 @@ bool SightCheck::P_SightPathTraverse ()
|
||||||
|
|
||||||
for (count = 0 ; count < 100 ; count++)
|
for (count = 0 ; count < 100 ; count++)
|
||||||
{
|
{
|
||||||
|
// end traversing when reaching the end of the blockmap
|
||||||
|
// an early out is not possible because with portals a trace can easily land outside the map's bounds.
|
||||||
|
if (mapx < 0 || mapx >= bmapwidth || mapy < 0 || mapy >= bmapheight)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
int res = P_SightBlockLinesIterator(mapx, mapy);
|
int res = P_SightBlockLinesIterator(mapx, mapy);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
sightcounts[1]++;
|
sightcounts[1]++;
|
||||||
return false; // early out
|
return false; // early out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -868,6 +877,7 @@ sightcounts[0]++;
|
||||||
// Now look from eyes of t1 to any part of t2.
|
// Now look from eyes of t1 to any part of t2.
|
||||||
|
|
||||||
validcount++;
|
validcount++;
|
||||||
|
portals.Clear();
|
||||||
{
|
{
|
||||||
sector_t *sec;
|
sector_t *sec;
|
||||||
fixed_t lookheight = t1->height - (t1->height >> 2);
|
fixed_t lookheight = t1->height - (t1->height >> 2);
|
||||||
|
@ -888,7 +898,11 @@ sightcounts[0]++;
|
||||||
{
|
{
|
||||||
portals[i].frac += FixedDiv(FRACUNIT, dist);
|
portals[i].frac += FixedDiv(FRACUNIT, dist);
|
||||||
s.init(t1, t2, NULL, &portals[i], flags);
|
s.init(t1, t2, NULL, &portals[i], flags);
|
||||||
if (s.P_SightPathTraverse()) break;
|
if (s.P_SightPathTraverse())
|
||||||
|
{
|
||||||
|
res = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1267,6 +1267,11 @@ inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
|
||||||
return P_PointInSubsector(x, y)->sector;
|
return P_PointInSubsector(x, y)->sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fixedvec3 AActor::PosRelative(int portalgroup) const
|
||||||
|
{
|
||||||
|
return __pos + Displacements.getOffset(Sector->PortalGroup, portalgroup);
|
||||||
|
}
|
||||||
|
|
||||||
inline fixedvec3 AActor::PosRelative(const AActor *other) const
|
inline fixedvec3 AActor::PosRelative(const AActor *other) const
|
||||||
{
|
{
|
||||||
return __pos + Displacements.getOffset(Sector->PortalGroup, other->Sector->PortalGroup);
|
return __pos + Displacements.getOffset(Sector->PortalGroup, other->Sector->PortalGroup);
|
||||||
|
|
Loading…
Reference in a new issue