- refactored sector portal data so that it does not rely on actors.
This is necessary because otherwise the level data cannot be serialized before the actors.
This commit is contained in:
parent
3532dd9ea1
commit
082042818b
23 changed files with 410 additions and 284 deletions
192
src/portal.cpp
192
src/portal.cpp
|
|
@ -64,6 +64,8 @@ FPortalBlockmap PortalBlockmap;
|
|||
TArray<FLinePortal> linePortals;
|
||||
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
|
||||
|
||||
TArray<FSectorPortal> sectorPortals;
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// This is used to mark processed portals for some collection functions.
|
||||
|
|
@ -213,6 +215,26 @@ FArchive &operator<< (FArchive &arc, FLinePortal &port)
|
|||
return arc;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// Save a sector portal for savegames.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
FArchive &operator<< (FArchive &arc, FSectorPortal &port)
|
||||
{
|
||||
arc << port.mType
|
||||
<< port.mFlags
|
||||
<< port.mPartner
|
||||
<< port.mPlane
|
||||
<< port.mOrigin
|
||||
<< port.mDestination
|
||||
<< port.mDisplacement
|
||||
<< port.mPlaneZ
|
||||
<< port.mSkybox;
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
|
@ -487,7 +509,7 @@ bool P_ChangePortal(line_t *ln, int thisid, int destid)
|
|||
|
||||
//============================================================================
|
||||
//
|
||||
// clears all portal dat for a new level start
|
||||
// clears all portal data for a new level start
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
|
|
@ -496,9 +518,17 @@ void P_ClearPortals()
|
|||
Displacements.Create(1);
|
||||
linePortals.Clear();
|
||||
linkedPortals.Clear();
|
||||
sectorPortals.Resize(2);
|
||||
// The first entry must always be the default skybox. This is what every sector gets by default.
|
||||
memset(§orPortals[0], 0, sizeof(sectorPortals[0]));
|
||||
sectorPortals[0].mType = PORTS_SKYVIEWPOINT;
|
||||
sectorPortals[0].mFlags = PORTSF_SKYFLATONLY;
|
||||
// The second entry will be the default sky. This is for forcing a regular sky through the skybox picker
|
||||
memset(§orPortals[1], 0, sizeof(sectorPortals[0]));
|
||||
sectorPortals[1].mType = PORTS_SKYVIEWPOINT;
|
||||
sectorPortals[1].mFlags = PORTSF_SKYFLATONLY;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// check if this line is between portal and the viewer. clip away if it is.
|
||||
|
|
@ -637,6 +667,74 @@ void P_TranslatePortalZ(line_t* src, double& z)
|
|||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_GetSkyboxPortal
|
||||
//
|
||||
// Gets a portal for a SkyViewpoint
|
||||
// If none exists yet, it will create a new one.
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
unsigned P_GetSkyboxPortal(ASkyViewpoint *actor)
|
||||
{
|
||||
if (actor == NULL) return 1; // this means a regular sky.
|
||||
for (unsigned i = 0;i<sectorPortals.Size();i++)
|
||||
{
|
||||
if (sectorPortals[i].mSkybox == actor) return i;
|
||||
}
|
||||
unsigned i = sectorPortals.Reserve(1);
|
||||
memset(§orPortals[i], 0, sizeof(sectorPortals[i]));
|
||||
sectorPortals[i].mType = PORTS_SKYVIEWPOINT;
|
||||
sectorPortals[i].mFlags = actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(ASkyCamCompat)) ? 0 : PORTSF_SKYFLATONLY;
|
||||
sectorPortals[i].mSkybox = actor;
|
||||
sectorPortals[i].mDestination = actor->Sector;
|
||||
return i;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_GetPortal
|
||||
//
|
||||
// Creates a portal struct for a linedef-based portal
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
unsigned P_GetPortal(int type, int plane, sector_t *from, sector_t *to, const DVector2 &displacement)
|
||||
{
|
||||
unsigned i = sectorPortals.Reserve(1);
|
||||
memset(§orPortals[i], 0, sizeof(sectorPortals[i]));
|
||||
sectorPortals[i].mType = type;
|
||||
sectorPortals[i].mPlane = plane;
|
||||
sectorPortals[i].mOrigin = from;
|
||||
sectorPortals[i].mDestination = to;
|
||||
sectorPortals[i].mDisplacement = displacement;
|
||||
sectorPortals[i].mPlaneZ = type == PORTS_LINKEDPORTAL? from->GetPlaneTexZF(plane) : FLT_MAX;
|
||||
return i;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_GetStackPortal
|
||||
//
|
||||
// Creates a portal for a stacked sector thing
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
unsigned P_GetStackPortal(AActor *point, int plane)
|
||||
{
|
||||
unsigned i = sectorPortals.Reserve(1);
|
||||
memset(§orPortals[i], 0, sizeof(sectorPortals[i]));
|
||||
sectorPortals[i].mType = PORTS_STACKEDSECTORTHING;
|
||||
sectorPortals[i].mPlane = plane;
|
||||
sectorPortals[i].mOrigin = point->target->Sector;
|
||||
sectorPortals[i].mDestination = point->Sector;
|
||||
sectorPortals[i].mPlaneZ = FLT_MAX;
|
||||
sectorPortals[i].mSkybox = point;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_GetOffsetPosition
|
||||
|
|
@ -756,35 +854,35 @@ static bool CollectSectors(int groupid, sector_t *origin)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
static void AddDisplacementForPortal(AStackPoint *portal)
|
||||
static void AddDisplacementForPortal(FSectorPortal *portal)
|
||||
{
|
||||
int thisgroup = portal->Mate->Sector->PortalGroup;
|
||||
int othergroup = portal->Sector->PortalGroup;
|
||||
int thisgroup = portal->mOrigin->PortalGroup;
|
||||
int othergroup = portal->mDestination->PortalGroup;
|
||||
if (thisgroup == othergroup)
|
||||
{
|
||||
Printf("Portal between sectors %d and %d has both sides in same group and will be disabled\n", portal->Sector->sectornum, portal->Mate->Sector->sectornum);
|
||||
portal->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
||||
Printf("Portal between sectors %d and %d has both sides in same group and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
|
||||
portal->mType = PORTS_PORTAL;
|
||||
return;
|
||||
}
|
||||
if (thisgroup <= 0 || thisgroup >= Displacements.size || othergroup <= 0 || othergroup >= Displacements.size)
|
||||
{
|
||||
Printf("Portal between sectors %d and %d has invalid group and will be disabled\n", portal->Sector->sectornum, portal->Mate->Sector->sectornum);
|
||||
portal->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
||||
Printf("Portal between sectors %d and %d has invalid group and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
|
||||
portal->mType = PORTS_PORTAL;
|
||||
return;
|
||||
}
|
||||
|
||||
FDisplacement & disp = Displacements(thisgroup, othergroup);
|
||||
if (!disp.isSet)
|
||||
{
|
||||
disp.pos = portal->Scale;
|
||||
disp.pos = portal->mDisplacement;
|
||||
disp.isSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (disp.pos != portal->Scale)
|
||||
if (disp.pos != portal->mDisplacement)
|
||||
{
|
||||
Printf("Portal between sectors %d and %d has displacement mismatch and will be disabled\n", portal->Sector->sectornum, portal->Mate->Sector->sectornum);
|
||||
portal->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
||||
Printf("Portal between sectors %d and %d has displacement mismatch and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
|
||||
portal->mType = PORTS_PORTAL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -895,55 +993,43 @@ static bool ConnectGroups()
|
|||
|
||||
void P_CreateLinkedPortals()
|
||||
{
|
||||
TThinkerIterator<AStackPoint> it;
|
||||
AStackPoint *mo;
|
||||
TArray<AStackPoint *> orgs;
|
||||
TArray<FSectorPortal *> orgs;
|
||||
int id = 1;
|
||||
bool bogus = false;
|
||||
|
||||
while ((mo = it.Next()))
|
||||
for(auto &s : sectorPortals)
|
||||
{
|
||||
if (mo->special1 == SKYBOX_LINKEDPORTAL)
|
||||
if (s.mType == PORTS_LINKEDPORTAL)
|
||||
{
|
||||
if (mo->Mate != NULL)
|
||||
{
|
||||
orgs.Push(mo);
|
||||
mo->reactiontime = ++id;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this should never happen, but if it does, the portal needs to be removed
|
||||
mo->Destroy();
|
||||
}
|
||||
orgs.Push(&s);
|
||||
}
|
||||
}
|
||||
id = 1;
|
||||
if (orgs.Size() != 0)
|
||||
{
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
for (int i = 0; i < numsectors; i++)
|
||||
{
|
||||
AActor *box = sectors[i].SkyBoxes[j];
|
||||
if (box != NULL && box->special1 == SKYBOX_LINKEDPORTAL)
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
secplane_t &plane = j == 0 ? sectors[i].floorplane : sectors[i].ceilingplane;
|
||||
if (plane.isSlope())
|
||||
if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL)
|
||||
{
|
||||
// The engine cannot deal with portals on a sloped plane.
|
||||
sectors[i].SkyBoxes[j] = NULL;
|
||||
Printf("Portal on %s of sector %d is sloped and will be disabled\n", j == 0 ? "floor" : "ceiling", i);
|
||||
secplane_t &plane = j == 0 ? sectors[i].floorplane : sectors[i].ceilingplane;
|
||||
if (plane.isSlope())
|
||||
{
|
||||
// The engine cannot deal with portals on a sloped plane.
|
||||
sectors[i].ClearPortal(j);
|
||||
Printf("Portal on %s of sector %d is sloped and will be disabled\n", j == 0 ? "floor" : "ceiling", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Group all sectors, starting at each portal origin.
|
||||
for (unsigned i = 0; i < orgs.Size(); i++)
|
||||
{
|
||||
if (CollectSectors(id, orgs[i]->Sector)) id++;
|
||||
if (CollectSectors(id, orgs[i]->Mate->Sector)) id++;
|
||||
}
|
||||
// Group all sectors, starting at each portal origin.
|
||||
for (unsigned i = 0; i < orgs.Size(); i++)
|
||||
{
|
||||
if (CollectSectors(id, orgs[i]->mOrigin)) id++;
|
||||
if (CollectSectors(id, orgs[i]->mDestination)) id++;
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||
{
|
||||
|
|
@ -960,17 +1046,9 @@ void P_CreateLinkedPortals()
|
|||
{
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
ASkyViewpoint *box = barrier_cast<ASkyViewpoint*>(sectors[i].SkyBoxes[j]);
|
||||
if (box != NULL)
|
||||
if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL && sectors[i].PortalGroup == 0)
|
||||
{
|
||||
if (box->special1 == SKYBOX_LINKEDPORTAL && sectors[i].PortalGroup == 0)
|
||||
{
|
||||
// Note: the linked actor will be on the other side of the portal.
|
||||
// To get this side's group we will have to look at the mate object.
|
||||
CollectSectors(box->Mate->Sector->PortalGroup, §ors[i]);
|
||||
// We cannot process the backlink here because all we can access is the anchor object
|
||||
// If necessary that will have to be done for the other side's portal.
|
||||
}
|
||||
CollectSectors(sectors[i].GetOppositePortalGroup(j), §ors[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1060,11 +1138,11 @@ void P_CreateLinkedPortals()
|
|||
double fp = sectors[i].floorplane.fD();
|
||||
if (cp < fp || fz == fp)
|
||||
{
|
||||
sectors[i].SkyBoxes[sector_t::ceiling] = NULL;
|
||||
sectors[i].ClearPortal(sector_t::ceiling);
|
||||
}
|
||||
else
|
||||
{
|
||||
sectors[i].SkyBoxes[sector_t::floor] = NULL;
|
||||
sectors[i].ClearPortal(sector_t::floor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue