- wrap access to portal properties into sector_t:: member functions.

This commit is contained in:
Christoph Oelckers 2016-04-19 11:35:28 +02:00
parent c795f29cc4
commit 322b9fc0ae
11 changed files with 109 additions and 96 deletions

View file

@ -287,22 +287,21 @@ void P_ThinkParticles ()
particle->Pos.Z += particle->Vel.Z; particle->Pos.Z += particle->Vel.Z;
particle->Vel += particle->Acc; particle->Vel += particle->Acc;
particle->subsector = R_PointInSubsector(particle->Pos); particle->subsector = R_PointInSubsector(particle->Pos);
sector_t *s = particle->subsector->sector;
// Handle crossing a sector portal. // Handle crossing a sector portal.
if (!particle->subsector->sector->PortalBlocksMovement(sector_t::ceiling)) if (!s->PortalBlocksMovement(sector_t::ceiling))
{ {
AActor *skybox = particle->subsector->sector->SkyBoxes[sector_t::ceiling]; if (particle->Pos.Z > s->GetPortalPlaneZ(sector_t::ceiling))
if (particle->Pos.Z > skybox->specialf1)
{ {
particle->Pos += skybox->Scale; particle->Pos += s->GetPortalDisplacement(sector_t::ceiling);
particle->subsector = NULL; particle->subsector = NULL;
} }
} }
else if (!particle->subsector->sector->PortalBlocksMovement(sector_t::floor)) else if (!s->PortalBlocksMovement(sector_t::floor))
{ {
AActor *skybox = particle->subsector->sector->SkyBoxes[sector_t::floor]; if (particle->Pos.Z < s->GetPortalPlaneZ(sector_t::floor))
if (particle->Pos.Z < skybox->specialf1)
{ {
particle->Pos += skybox->Scale; particle->Pos += s->GetPortalDisplacement(sector_t::floor);
particle->subsector = NULL; particle->subsector = NULL;
} }
} }

View file

@ -162,12 +162,12 @@ void P_RecursiveSound (sector_t *sec, AActor *soundtarget, bool splash, int soun
// I wish there was a better method to do this than randomly looking through the portal at a few places... // I wish there was a better method to do this than randomly looking through the portal at a few places...
if (checkabove) if (checkabove)
{ {
sector_t *upper = P_PointInSector(check->v1->fPos() + check->Delta() / 2 + sec->SkyBoxes[sector_t::ceiling]->Scale); sector_t *upper = P_PointInSector(check->v1->fPos() + check->Delta() / 2 + sec->GetPortalDisplacement(sector_t::ceiling));
P_RecursiveSound(upper, soundtarget, splash, soundblocks, emitter, maxdist); P_RecursiveSound(upper, soundtarget, splash, soundblocks, emitter, maxdist);
} }
if (checkbelow) if (checkbelow)
{ {
sector_t *lower = P_PointInSector(check->v1->fPos() + check->Delta() / 2 + sec->SkyBoxes[sector_t::floor]->Scale); sector_t *lower = P_PointInSector(check->v1->fPos() + check->Delta() / 2 + sec->GetPortalDisplacement(sector_t::floor));
P_RecursiveSound(lower, soundtarget, splash, soundblocks, emitter, maxdist); P_RecursiveSound(lower, soundtarget, splash, soundblocks, emitter, maxdist);
} }
FLinePortal *port = check->getPortal(); FLinePortal *port = check->getPortal();

View file

@ -656,20 +656,21 @@ double P_GetMoveFactor(const AActor *mo, double *frictionp)
// - 0 when intersecting // - 0 when intersecting
// - -1 when outside the portal // - -1 when outside the portal
// //
// Note that this check is done from the 'other' side of the portal
// so plane names seem to be inverted.
//
//========================================================================== //==========================================================================
static int LineIsAbove(line_t *line, AActor *actor) static int LineIsAbove(line_t *line, AActor *actor)
{ {
AActor *point = line->frontsector->SkyBoxes[sector_t::floor]; if (line->frontsector->PortalBlocksMovement(sector_t::floor)) return -1;
if (point == NULL) return -1; return line->frontsector->GetPortalPlaneZ(sector_t::floor) >= actor->Top();
return point->specialf1 >= actor->Top();
} }
static int LineIsBelow(line_t *line, AActor *actor) static int LineIsBelow(line_t *line, AActor *actor)
{ {
AActor *point = line->frontsector->SkyBoxes[sector_t::ceiling]; if (line->frontsector->PortalBlocksMovement(sector_t::ceiling)) return -1;
if (point == NULL) return -1; return line->frontsector->GetPortalPlaneZ(sector_t::ceiling) <= actor->Z();
return point->specialf1 <= actor->Z();
} }
// //
@ -762,7 +763,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (state == 1) if (state == 1)
{ {
// the line should not block but we should set the ceilingz to the portal boundary so that we can't float up into that line. // the line should not block but we should set the ceilingz to the portal boundary so that we can't float up into that line.
double portalz = cres.line->frontsector->SkyBoxes[sector_t::floor]->specialf1; double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::floor);
if (portalz < tm.ceilingz) if (portalz < tm.ceilingz)
{ {
tm.ceilingz = portalz; tm.ceilingz = portalz;
@ -778,7 +779,7 @@ bool PIT_CheckLine(FMultiBlockLinesIterator &mit, FMultiBlockLinesIterator::Chec
if (state == -1) return true; if (state == -1) return true;
if (state == 1) if (state == 1)
{ {
double portalz = cres.line->frontsector->SkyBoxes[sector_t::ceiling]->specialf1; double portalz = cres.line->frontsector->GetPortalPlaneZ(sector_t::ceiling);
if (portalz > tm.floorz) if (portalz > tm.floorz)
{ {
tm.floorz = portalz; tm.floorz = portalz;
@ -3529,20 +3530,20 @@ struct aim_t
void EnterSectorPortal(int position, double frac, sector_t *entersec, DAngle newtoppitch, DAngle newbottompitch) void EnterSectorPortal(int position, double frac, sector_t *entersec, DAngle newtoppitch, DAngle newbottompitch)
{ {
AActor *portal = entersec->SkyBoxes[position]; double portalz = entersec->GetPortalPlaneZ(position);
if (position == sector_t::ceiling && portal->specialf1 < limitz) return; if (position == sector_t::ceiling && portalz < limitz) return;
else if (position == sector_t::floor && portal->specialf1 > limitz) return; else if (position == sector_t::floor && portalz > limitz) return;
aim_t newtrace = Clone(); aim_t newtrace = Clone();
newtrace.toppitch = newtoppitch; newtrace.toppitch = newtoppitch;
newtrace.bottompitch = newbottompitch; newtrace.bottompitch = newbottompitch;
newtrace.aimdir = position == sector_t::ceiling? aim_t::aim_up : aim_t::aim_down; newtrace.aimdir = position == sector_t::ceiling? aim_t::aim_up : aim_t::aim_down;
newtrace.startpos = startpos + portal->Scale; newtrace.startpos = startpos + entersec->GetPortalDisplacement(position);
newtrace.startfrac = frac + 1. / attackrange; // this is to skip the transition line to the portal which would produce a bogus opening newtrace.startfrac = frac + 1. / attackrange; // this is to skip the transition line to the portal which would produce a bogus opening
newtrace.lastsector = P_PointInSector(newtrace.startpos + aimtrace * newtrace.startfrac); newtrace.lastsector = P_PointInSector(newtrace.startpos + aimtrace * newtrace.startfrac);
newtrace.limitz = portal->specialf1; newtrace.limitz = portalz;
if (aimdebug) if (aimdebug)
Printf("-----Entering %s portal from sector %d to sector %d\n", position ? "ceiling" : "floor", lastsector->sectornum, newtrace.lastsector->sectornum); Printf("-----Entering %s portal from sector %d to sector %d\n", position ? "ceiling" : "floor", lastsector->sectornum, newtrace.lastsector->sectornum);
newtrace.AimTraverse(); newtrace.AimTraverse();
@ -6253,22 +6254,22 @@ void AActor::UpdateRenderSectorList()
ClearRenderSectorList(); ClearRenderSectorList();
while (!sec->PortalBlocksMovement(sector_t::ceiling)) while (!sec->PortalBlocksMovement(sector_t::ceiling))
{ {
double planeh = sec->SkyBoxes[sector_t::ceiling]->specialf1; double planeh = sec->GetPortalPlaneZ(sector_t::ceiling);
if (planeh < lasth) break; // broken setup. if (planeh < lasth) break; // broken setup.
if (Top() + SPRITE_SPACE < planeh) break; if (Top() + SPRITE_SPACE < planeh) break;
lasth = planeh; lasth = planeh;
DVector2 newpos = Pos() + sec->SkyBoxes[sector_t::ceiling]->Scale; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::ceiling);
sec = P_PointInSector(newpos); sec = P_PointInSector(newpos);
render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist);
} }
lasth = FLT_MAX; lasth = FLT_MAX;
while (!sec->PortalBlocksMovement(sector_t::floor)) while (!sec->PortalBlocksMovement(sector_t::floor))
{ {
double planeh = sec->SkyBoxes[sector_t::floor]->specialf1; double planeh = sec->GetPortalPlaneZ(sector_t::floor);
if (planeh > lasth) break; // broken setup. if (planeh > lasth) break; // broken setup.
if (Z() - SPRITE_SPACE > planeh) break; if (Z() - SPRITE_SPACE > planeh) break;
lasth = planeh; lasth = planeh;
DVector2 newpos = Pos() + sec->SkyBoxes[sector_t::floor]->Scale; DVector2 newpos = Pos() + sec->GetPortalDisplacement(sector_t::floor);
sec = P_PointInSector(newpos); sec = P_PointInSector(newpos);
render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist);
} }

View file

@ -174,7 +174,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co
{ {
// We must check through the portal for the actual dropoff. // We must check through the portal for the actual dropoff.
// If there's no lines in the lower sections we'd never get a usable value otherwise. // If there's no lines in the lower sections we'd never get a usable value otherwise.
open.lowfloor = back->NextLowestFloorAt(pos.X, pos.Y, back->SkyBoxes[sector_t::floor]->specialf1-1); open.lowfloor = back->NextLowestFloorAt(pos.X, pos.Y, back->GetPortalPlaneZ(sector_t::floor) - EQUAL_EPSILON);
} }
} }
else else
@ -188,7 +188,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co
{ {
// We must check through the portal for the actual dropoff. // We must check through the portal for the actual dropoff.
// If there's no lines in the lower sections we'd never get a usable value otherwise. // If there's no lines in the lower sections we'd never get a usable value otherwise.
open.lowfloor = front->NextLowestFloorAt(pos.X, pos.Y, front->SkyBoxes[sector_t::floor]->specialf1 - 1); open.lowfloor = front->NextLowestFloorAt(pos.X, pos.Y, front->GetPortalPlaneZ(sector_t::floor) - EQUAL_EPSILON);
} }
} }
open.frontfloorplane = front->floorplane; open.frontfloorplane = front->floorplane;
@ -735,7 +735,7 @@ bool FMultiBlockLinesIterator::GoUp(double x, double y)
{ {
if (!cursector->PortalBlocksMovement(sector_t::ceiling)) if (!cursector->PortalBlocksMovement(sector_t::ceiling))
{ {
startIteratorForGroup(cursector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup); startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::ceiling));
portalflags = FFCF_NOFLOOR; portalflags = FFCF_NOFLOOR;
return true; return true;
} }
@ -756,7 +756,7 @@ bool FMultiBlockLinesIterator::GoDown(double x, double y)
{ {
if (!cursector->PortalBlocksMovement(sector_t::floor)) if (!cursector->PortalBlocksMovement(sector_t::floor))
{ {
startIteratorForGroup(cursector->SkyBoxes[sector_t::floor]->Sector->PortalGroup); startIteratorForGroup(cursector->GetOppositePortalGroup(sector_t::floor));
portalflags = FFCF_NOCEILING; portalflags = FFCF_NOCEILING;
return true; return true;
} }

View file

@ -3169,10 +3169,9 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec)
while (!sec->PortalBlocksMovement(sector_t::ceiling)) while (!sec->PortalBlocksMovement(sector_t::ceiling))
{ {
AActor *port = sec->SkyBoxes[sector_t::ceiling]; if (testz > sec->GetPortalPlaneZ(sector_t::ceiling))
if (testz > port->specialf1)
{ {
pos = PosRelative(port->Sector); pos = PosRelative(sec->GetOppositePortalGroup(sector_t::ceiling));
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
moved = true; moved = true;
} }
@ -3182,10 +3181,9 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec)
{ {
while (!sec->PortalBlocksMovement(sector_t::floor)) while (!sec->PortalBlocksMovement(sector_t::floor))
{ {
AActor *port = sec->SkyBoxes[sector_t::floor]; if (testz <= sec->GetPortalPlaneZ(sector_t::floor))
if (testz <= port->specialf1)
{ {
pos = PosRelative(port->Sector); pos = PosRelative(sec->GetOppositePortalGroup(sector_t::floor));
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
} }
else break; else break;
@ -3202,12 +3200,11 @@ void AActor::CheckPortalTransition(bool islinked)
bool moved = false; bool moved = false;
while (!Sector->PortalBlocksMovement(sector_t::ceiling)) while (!Sector->PortalBlocksMovement(sector_t::ceiling))
{ {
AActor *port = Sector->SkyBoxes[sector_t::ceiling]; if (Z() > Sector->GetPortalPlaneZ(sector_t::ceiling))
if (Z() > port->specialf1)
{ {
DVector3 oldpos = Pos(); DVector3 oldpos = Pos();
if (islinked && !moved) UnlinkFromWorld(); if (islinked && !moved) UnlinkFromWorld();
SetXYZ(PosRelative(port->Sector)); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::ceiling)));
Prev = Pos() - oldpos; Prev = Pos() - oldpos;
Sector = P_PointInSector(Pos()); Sector = P_PointInSector(Pos());
PrevPortalGroup = Sector->PortalGroup; PrevPortalGroup = Sector->PortalGroup;
@ -3219,12 +3216,12 @@ void AActor::CheckPortalTransition(bool islinked)
{ {
while (!Sector->PortalBlocksMovement(sector_t::floor)) while (!Sector->PortalBlocksMovement(sector_t::floor))
{ {
AActor *port = Sector->SkyBoxes[sector_t::floor]; double portalz = Sector->GetPortalPlaneZ(sector_t::floor);
if (Z() < port->specialf1 && floorz < port->specialf1) if (Z() < portalz && floorz < portalz)
{ {
DVector3 oldpos = Pos(); DVector3 oldpos = Pos();
if (islinked && !moved) UnlinkFromWorld(); if (islinked && !moved) UnlinkFromWorld();
SetXYZ(PosRelative(port->Sector)); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::floor)));
Prev = Pos() - oldpos; Prev = Pos() - oldpos;
Sector = P_PointInSector(Pos()); Sector = P_PointInSector(Pos());
PrevPortalGroup = Sector->PortalGroup; PrevPortalGroup = Sector->PortalGroup;

View file

@ -895,10 +895,10 @@ double sector_t::HighestCeilingAt(const DVector2 &p, sector_t **resultsec)
DVector2 pos = p; DVector2 pos = p;
// Continue until we find a blocking portal or a portal below where we actually are. // Continue until we find a blocking portal or a portal below where we actually are.
while (!check->PortalBlocksMovement(ceiling) && planeheight < check->SkyBoxes[ceiling]->specialf1) while (!check->PortalBlocksMovement(ceiling) && planeheight < check->GetPortalPlaneZ(ceiling))
{ {
pos += check->SkyBoxes[ceiling]->Scale; pos += check->GetPortalDisplacement(ceiling);
planeheight = check->SkyBoxes[ceiling]->specialf1; planeheight = check->GetPortalPlaneZ(ceiling);
check = P_PointInSector(pos); check = P_PointInSector(pos);
} }
if (resultsec) *resultsec = check; if (resultsec) *resultsec = check;
@ -918,10 +918,10 @@ double sector_t::LowestFloorAt(const DVector2 &p, sector_t **resultsec)
DVector2 pos = p; DVector2 pos = p;
// Continue until we find a blocking portal or a portal above where we actually are. // Continue until we find a blocking portal or a portal above where we actually are.
while (!check->PortalBlocksMovement(floor) && planeheight > check->SkyBoxes[floor]->specialf1) while (!check->PortalBlocksMovement(floor) && planeheight > check->GetPortalPlaneZ(floor))
{ {
pos += check->SkyBoxes[floor]->Scale; pos += check->GetPortalDisplacement(floor);
planeheight = check->SkyBoxes[floor]->specialf1; planeheight = check->GetPortalPlaneZ(ceiling);
check = P_PointInSector(pos); check = P_PointInSector(pos);
} }
if (resultsec) *resultsec = check; if (resultsec) *resultsec = check;
@ -956,7 +956,7 @@ double sector_t::NextHighestCeilingAt(double x, double y, double bottomz, double
return ff_bottom; return ff_bottom;
} }
} }
if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(ceiling) || planeheight >= sec->SkyBoxes[ceiling]->specialf1) if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(ceiling) || planeheight >= sec->GetPortalPlaneZ(ceiling))
{ // Use sector's floor { // Use sector's floor
if (resultffloor) *resultffloor = NULL; if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec; if (resultsec) *resultsec = sec;
@ -964,10 +964,10 @@ double sector_t::NextHighestCeilingAt(double x, double y, double bottomz, double
} }
else else
{ {
DVector2 pos = sec->SkyBoxes[ceiling]->Scale; DVector2 pos = sec->GetPortalDisplacement(ceiling);
x += pos.X; x += pos.X;
y += pos.Y; y += pos.Y;
planeheight = sec->SkyBoxes[ceiling]->specialf1; planeheight = sec->GetPortalPlaneZ(ceiling);
sec = P_PointInSector(x, y); sec = P_PointInSector(x, y);
} }
} }
@ -1001,7 +1001,7 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub
} }
} }
} }
if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(sector_t::floor) || planeheight <= sec->SkyBoxes[floor]->specialf1) if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(sector_t::floor) || planeheight <= sec->GetPortalPlaneZ(floor))
{ // Use sector's floor { // Use sector's floor
if (resultffloor) *resultffloor = NULL; if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec; if (resultsec) *resultsec = sec;
@ -1009,10 +1009,10 @@ double sector_t::NextLowestFloorAt(double x, double y, double z, int flags, doub
} }
else else
{ {
DVector2 pos = sec->SkyBoxes[floor]->Scale; DVector2 pos = sec->GetPortalDisplacement(floor);
x += pos.X; x += pos.X;
y += pos.Y; y += pos.Y;
planeheight = sec->SkyBoxes[floor]->specialf1; planeheight = sec->GetPortalPlaneZ(floor);
sec = P_PointInSector(x, y); sec = P_PointInSector(x, y);
} }
} }

View file

@ -254,11 +254,11 @@ bool SightCheck::PTR_SightTraverse (intercept_t *in)
if (portaldir != sector_t::floor && (open.portalflags & SO_TOPBACK) && !(open.portalflags & SO_TOPFRONT)) if (portaldir != sector_t::floor && (open.portalflags & SO_TOPBACK) && !(open.portalflags & SO_TOPFRONT))
{ {
portals.Push({ in->frac, topslope, bottomslope, sector_t::ceiling, backsec->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup }); portals.Push({ in->frac, topslope, bottomslope, sector_t::ceiling, backsec->GetOppositePortalGroup(sector_t::ceiling) });
} }
if (portaldir != sector_t::ceiling && (open.portalflags & SO_BOTTOMBACK) && !(open.portalflags & SO_BOTTOMFRONT)) if (portaldir != sector_t::ceiling && (open.portalflags & SO_BOTTOMBACK) && !(open.portalflags & SO_BOTTOMFRONT))
{ {
portals.Push({ in->frac, topslope, bottomslope, sector_t::floor, backsec->SkyBoxes[sector_t::floor]->Sector->PortalGroup }); portals.Push({ in->frac, topslope, bottomslope, sector_t::floor, backsec->GetOppositePortalGroup(sector_t::floor) });
} }
} }
if (lport) if (lport)
@ -628,11 +628,11 @@ bool SightCheck::P_SightPathTraverse ()
// We also must check if the starting sector contains portals, and start sight checks in those as well. // We also must check if the starting sector contains portals, and start sight checks in those as well.
if (portaldir != sector_t::floor && checkceiling && !lastsector->PortalBlocksSight(sector_t::ceiling)) if (portaldir != sector_t::floor && checkceiling && !lastsector->PortalBlocksSight(sector_t::ceiling))
{ {
portals.Push({ 0, topslope, bottomslope, sector_t::ceiling, lastsector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup }); portals.Push({ 0, topslope, bottomslope, sector_t::ceiling, lastsector->GetOppositePortalGroup(sector_t::ceiling) });
} }
if (portaldir != sector_t::ceiling && checkfloor && !lastsector->PortalBlocksSight(sector_t::floor)) if (portaldir != sector_t::ceiling && checkfloor && !lastsector->PortalBlocksSight(sector_t::floor))
{ {
portals.Push({ 0, topslope, bottomslope, sector_t::floor, lastsector->SkyBoxes[sector_t::floor]->Sector->PortalGroup }); portals.Push({ 0, topslope, bottomslope, sector_t::floor, lastsector->GetOppositePortalGroup(sector_t::floor) });
} }
x1 -= bmaporgx; x1 -= bmaporgx;

View file

@ -112,10 +112,9 @@ static void GetPortalTransition(DVector3 &pos, sector_t *&sec)
while (!sec->PortalBlocksMovement(sector_t::ceiling)) while (!sec->PortalBlocksMovement(sector_t::ceiling))
{ {
AActor *port = sec->SkyBoxes[sector_t::ceiling]; if (pos.Z > sec->GetPortalPlaneZ(sector_t::ceiling))
if (pos.Z > port->specialf1)
{ {
pos += port->Scale; pos += sec->GetPortalDisplacement(sector_t::ceiling);
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
moved = true; moved = true;
} }
@ -125,10 +124,9 @@ static void GetPortalTransition(DVector3 &pos, sector_t *&sec)
{ {
while (!sec->PortalBlocksMovement(sector_t::floor)) while (!sec->PortalBlocksMovement(sector_t::floor))
{ {
AActor *port = sec->SkyBoxes[sector_t::floor]; if (pos.Z <= sec->GetPortalPlaneZ(sector_t::floor))
if (pos.Z <= port->specialf1)
{ {
pos += port->Scale; pos += sec->GetPortalDisplacement(sector_t::floor);
sec = P_PointInSector(pos); sec = P_PointInSector(pos);
} }
else break; else break;
@ -208,18 +206,17 @@ bool Trace(const DVector3 &start, sector_t *sector, const DVector3 &direction, d
void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac, sector_t *entersec) void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac, sector_t *entersec)
{ {
AActor *portal = entersec->SkyBoxes[position]; DVector2 displacement = entersec->GetPortalDisplacement(position);;
double enterdist = MaxDist * frac; double enterdist = MaxDist * frac;
DVector3 exit = Start + enterdist * Vec; DVector3 exit = Start + enterdist * Vec;
DVector3 enter = exit + portal->Scale; DVector3 enter = exit + displacement;
Start += portal->Scale; Start += displacement;
CurSector = P_PointInSector(enter); CurSector = P_PointInSector(enter);
inshootthrough = true; inshootthrough = true;
startfrac = frac; startfrac = frac;
EnterDist = enterdist; EnterDist = enterdist;
pt.PortalRelocate(portal, ptflags, frac); pt.PortalRelocate(entersec->SkyBoxes[position], ptflags, frac);
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL) if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
{ {
@ -763,7 +760,7 @@ bool FTraceInfo::TraceTraverse (int ptflags)
if (Vec.Z < 0 && !CurSector->PortalBlocksMovement(sector_t::floor)) if (Vec.Z < 0 && !CurSector->PortalBlocksMovement(sector_t::floor))
{ {
// calculate position where the portal is crossed // calculate position where the portal is crossed
double portz = CurSector->SkyBoxes[sector_t::floor]->specialf1; double portz = CurSector->GetPortalPlaneZ(sector_t::floor);
if (hit.Z < portz && limitz > portz) if (hit.Z < portz && limitz > portz)
{ {
limitz = portz; limitz = portz;
@ -775,7 +772,7 @@ bool FTraceInfo::TraceTraverse (int ptflags)
else if (Vec.Z > 0 && !CurSector->PortalBlocksMovement(sector_t::ceiling)) else if (Vec.Z > 0 && !CurSector->PortalBlocksMovement(sector_t::ceiling))
{ {
// calculate position where the portal is crossed // calculate position where the portal is crossed
double portz = CurSector->SkyBoxes[sector_t::ceiling]->specialf1; double portz = CurSector->GetPortalPlaneZ(sector_t::ceiling);
if (hit.Z > portz && limitz < portz) if (hit.Z > portz && limitz < portz)
{ {
limitz = portz; limitz = portz;

View file

@ -1050,8 +1050,8 @@ void P_CreateLinkedPortals()
} }
if (sectors[i].PortalIsLinked(sector_t::ceiling) && sectors[i].PortalIsLinked(sector_t::floor)) if (sectors[i].PortalIsLinked(sector_t::ceiling) && sectors[i].PortalIsLinked(sector_t::floor))
{ {
double cz = sectors[i].SkyBoxes[sector_t::ceiling]->specialf1; double cz = sectors[i].GetPortalPlaneZ(sector_t::ceiling);
double fz = sectors[i].SkyBoxes[sector_t::floor]->specialf1; double fz = sectors[i].GetPortalPlaneZ(sector_t::floor);
if (cz < fz) if (cz < fz)
{ {
// This is a fatal condition. We have to remove one of the two portals. Choose the one that doesn't match the current plane // This is a fatal condition. We have to remove one of the two portals. Choose the one that doesn't match the current plane
@ -1162,22 +1162,22 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
{ {
sector_t *sec = P_PointInSector(position); sector_t *sec = P_PointInSector(position);
sector_t *wsec = sec; sector_t *wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->SkyBoxes[sector_t::ceiling]->specialf1) while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->GetPortalPlaneZ(sector_t::ceiling))
{ {
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector; int othergroup = wsec->GetOppositePortalGroup(sector_t::ceiling);
DVector2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup) + position; DVector2 pos = Displacements.getOffset(startgroup, othergroup) + position;
processMask.setBit(othersec->PortalGroup); processMask.setBit(othergroup);
out.Add(othersec->PortalGroup | FPortalGroupArray::UPPER); out.Add(othergroup | FPortalGroupArray::UPPER);
wsec = P_PointInSector(pos); // get upper sector at the exact spot we want to check and repeat wsec = P_PointInSector(pos); // get upper sector at the exact spot we want to check and repeat
retval = true; retval = true;
} }
wsec = sec; wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::floor) && position.Z < wsec->SkyBoxes[sector_t::floor]->specialf1) while (!wsec->PortalBlocksMovement(sector_t::floor) && position.Z < wsec->GetPortalPlaneZ(sector_t::floor))
{ {
sector_t *othersec = wsec->SkyBoxes[sector_t::floor]->Sector; int othergroup = wsec->GetOppositePortalGroup(sector_t::floor);
DVector2 pos = Displacements.getOffset(startgroup, othersec->PortalGroup) + position; DVector2 pos = Displacements.getOffset(startgroup, othergroup) + position;
processMask.setBit(othersec->PortalGroup | FPortalGroupArray::LOWER); processMask.setBit(othergroup | FPortalGroupArray::LOWER);
out.Add(othersec->PortalGroup); out.Add(othergroup);
wsec = P_PointInSector(pos); // get lower sector at the exact spot we want to check and repeat wsec = P_PointInSector(pos); // get lower sector at the exact spot we want to check and repeat
retval = true; retval = true;
} }
@ -1204,9 +1204,9 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
sector_t *sec = s ? ld->backsector : ld->frontsector; sector_t *sec = s ? ld->backsector : ld->frontsector;
if (sec && !(sec->PortalBlocksMovement(sector_t::ceiling))) if (sec && !(sec->PortalBlocksMovement(sector_t::ceiling)))
{ {
if (sec->SkyBoxes[sector_t::ceiling]->specialf1 < upperz) if (sec->GetPortalPlaneZ(sector_t::ceiling) < upperz)
{ {
int grp = sec->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup; int grp = sec->GetOppositePortalGroup(sector_t::ceiling);
if (!(processMask.getBit(grp))) if (!(processMask.getBit(grp)))
{ {
processMask.setBit(grp); processMask.setBit(grp);
@ -1223,9 +1223,9 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
sector_t *sec = s ? ld->backsector : ld->frontsector; sector_t *sec = s ? ld->backsector : ld->frontsector;
if (sec && !(sec->PortalBlocksMovement(sector_t::floor))) if (sec && !(sec->PortalBlocksMovement(sector_t::floor)))
{ {
if (sec->SkyBoxes[sector_t::floor]->specialf1 > position.Z) if (sec->GetPortalPlaneZ(sector_t::floor) > position.Z)
{ {
int grp = sec->SkyBoxes[sector_t::floor]->Sector->PortalGroup; int grp = sec->GetOppositePortalGroup(sector_t::floor);
if (!(processMask.getBit(grp))) if (!(processMask.getBit(grp)))
{ {
processMask.setBit(grp); processMask.setBit(grp);

View file

@ -931,7 +931,7 @@ public:
bool PortalBlocksView(int plane) bool PortalBlocksView(int plane)
{ {
if (SkyBoxes[plane] == NULL) return true; if (SkyBoxes[plane] == NULL) return true;
if (SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return false; if (GetPortalType(plane) != SKYBOX_LINKEDPORTAL) return false;
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED)); return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
} }
@ -952,7 +952,28 @@ public:
bool PortalIsLinked(int plane) bool PortalIsLinked(int plane)
{ {
return (SkyBoxes[plane] != NULL && SkyBoxes[plane]->special1 == SKYBOX_LINKEDPORTAL); return (SkyBoxes[plane] != NULL && GetPortalType(plane) == SKYBOX_LINKEDPORTAL);
}
// These intentionally do not validate the SkyBoxes pointers.
double GetPortalPlaneZ(int plane)
{
return SkyBoxes[plane]->specialf1;
}
DVector2 GetPortalDisplacement(int plane)
{
return SkyBoxes[plane]->Scale;
}
int GetPortalType(int plane)
{
return SkyBoxes[plane]->special1;
}
int GetOppositePortalGroup(int plane)
{
return SkyBoxes[plane]->Sector->PortalGroup;
} }
int GetTerrain(int pos) const; int GetTerrain(int pos) const;

View file

@ -694,10 +694,9 @@ void R_InterpolateView (player_t *player, double Frac, InterpolationViewer *ivie
bool moved = false; bool moved = false;
while (!viewsector->PortalBlocksMovement(sector_t::ceiling)) while (!viewsector->PortalBlocksMovement(sector_t::ceiling))
{ {
AActor *point = viewsector->SkyBoxes[sector_t::ceiling]; if (ViewPos.Z > viewsector->GetPortalPlaneZ(sector_t::ceiling))
if (ViewPos.Z > point->specialf1)
{ {
ViewPos += point->Scale; ViewPos += viewsector->GetPortalDisplacement(sector_t::ceiling);
viewsector = R_PointInSubsector(ViewPos)->sector; viewsector = R_PointInSubsector(ViewPos)->sector;
moved = true; moved = true;
} }
@ -707,10 +706,9 @@ void R_InterpolateView (player_t *player, double Frac, InterpolationViewer *ivie
{ {
while (!viewsector->PortalBlocksMovement(sector_t::floor)) while (!viewsector->PortalBlocksMovement(sector_t::floor))
{ {
AActor *point = viewsector->SkyBoxes[sector_t::floor]; if (ViewPos.Z < viewsector->GetPortalPlaneZ(sector_t::floor))
if (ViewPos.Z < point->specialf1)
{ {
ViewPos += point->Scale; ViewPos += viewsector->GetPortalDisplacement(sector_t::floor);
viewsector = R_PointInSubsector(ViewPos)->sector; viewsector = R_PointInSubsector(ViewPos)->sector;
moved = true; moved = true;
} }