mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-31 05:40:44 +00:00
- 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
|
@ -384,6 +384,15 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
||||||
changed += players[i].FixPointers (old, notOld);
|
changed += players[i].FixPointers (old, notOld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &s : sectorPortals)
|
||||||
|
{
|
||||||
|
if (s.mSkybox == old)
|
||||||
|
{
|
||||||
|
s.mSkybox = static_cast<ASkyViewpoint*>(notOld);
|
||||||
|
changed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Go through sectors.
|
// Go through sectors.
|
||||||
if (sectors != NULL)
|
if (sectors != NULL)
|
||||||
{
|
{
|
||||||
|
@ -392,8 +401,6 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
||||||
#define SECTOR_CHECK(f,t) \
|
#define SECTOR_CHECK(f,t) \
|
||||||
if (sectors[i].f.p == static_cast<t *>(old)) { sectors[i].f = static_cast<t *>(notOld); changed++; }
|
if (sectors[i].f.p == static_cast<t *>(old)) { sectors[i].f = static_cast<t *>(notOld); changed++; }
|
||||||
SECTOR_CHECK( SoundTarget, AActor );
|
SECTOR_CHECK( SoundTarget, AActor );
|
||||||
SECTOR_CHECK( SkyBoxes[sector_t::ceiling], ASkyViewpoint );
|
|
||||||
SECTOR_CHECK( SkyBoxes[sector_t::floor], ASkyViewpoint );
|
|
||||||
SECTOR_CHECK( SecActTarget, ASectorAction );
|
SECTOR_CHECK( SecActTarget, ASectorAction );
|
||||||
SECTOR_CHECK( floordata, DSectorEffect );
|
SECTOR_CHECK( floordata, DSectorEffect );
|
||||||
SECTOR_CHECK( ceilingdata, DSectorEffect );
|
SECTOR_CHECK( ceilingdata, DSectorEffect );
|
||||||
|
|
|
@ -327,7 +327,10 @@ static void MarkRoot()
|
||||||
DThinker::MarkRoots();
|
DThinker::MarkRoots();
|
||||||
FCanvasTextureInfo::Mark();
|
FCanvasTextureInfo::Mark();
|
||||||
Mark(DACSThinker::ActiveThinker);
|
Mark(DACSThinker::ActiveThinker);
|
||||||
Mark(level.DefaultSkybox);
|
for (auto &s : sectorPortals)
|
||||||
|
{
|
||||||
|
Mark(s.mSkybox);
|
||||||
|
}
|
||||||
// Mark dead bodies.
|
// Mark dead bodies.
|
||||||
for (i = 0; i < BODYQUESIZE; ++i)
|
for (i = 0; i < BODYQUESIZE; ++i)
|
||||||
{
|
{
|
||||||
|
@ -680,8 +683,6 @@ size_t DSectorMarker::PropagateMark()
|
||||||
{
|
{
|
||||||
sector_t *sec = §ors[SecNum + i];
|
sector_t *sec = §ors[SecNum + i];
|
||||||
GC::Mark(sec->SoundTarget);
|
GC::Mark(sec->SoundTarget);
|
||||||
GC::Mark(sec->SkyBoxes[sector_t::ceiling]);
|
|
||||||
GC::Mark(sec->SkyBoxes[sector_t::floor]);
|
|
||||||
GC::Mark(sec->SecActTarget);
|
GC::Mark(sec->SecActTarget);
|
||||||
GC::Mark(sec->floordata);
|
GC::Mark(sec->floordata);
|
||||||
GC::Mark(sec->ceilingdata);
|
GC::Mark(sec->ceilingdata);
|
||||||
|
|
|
@ -298,6 +298,7 @@ template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
|
||||||
template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw);
|
template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw);
|
||||||
template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da);
|
template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da);
|
||||||
FArchive &operator<< (FArchive &arc, FLinePortal &da);
|
FArchive &operator<< (FArchive &arc, FLinePortal &da);
|
||||||
|
FArchive &operator<< (FArchive &arc, FSectorPortal &da);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1386,7 +1386,6 @@ void G_InitLevelLocals ()
|
||||||
NormalLight.ChangeFade (level.fadeto);
|
NormalLight.ChangeFade (level.fadeto);
|
||||||
|
|
||||||
level.DefaultEnvironment = info->DefaultEnvironment;
|
level.DefaultEnvironment = info->DefaultEnvironment;
|
||||||
level.DefaultSkybox = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -1538,7 +1537,7 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
|
||||||
P_SerializeSubsectors(arc);
|
P_SerializeSubsectors(arc);
|
||||||
StatusBar->Serialize (arc);
|
StatusBar->Serialize (arc);
|
||||||
|
|
||||||
arc << level.DefaultSkybox << level.total_monsters << level.total_items << level.total_secrets;
|
arc << level.total_monsters << level.total_items << level.total_secrets;
|
||||||
|
|
||||||
// Does this level have custom translations?
|
// Does this level have custom translations?
|
||||||
FRemapTable *trans;
|
FRemapTable *trans;
|
||||||
|
|
|
@ -435,8 +435,6 @@ struct FLevelLocals
|
||||||
int airsupply;
|
int airsupply;
|
||||||
int DefaultEnvironment; // Default sound environment.
|
int DefaultEnvironment; // Default sound environment.
|
||||||
|
|
||||||
TObjPtr<class ASkyViewpoint> DefaultSkybox;
|
|
||||||
|
|
||||||
FSectorScrollValues *Scrolls; // NULL if no DScrollers in this level
|
FSectorScrollValues *Scrolls; // NULL if no DScrollers in this level
|
||||||
|
|
||||||
SBYTE WallVertLight; // Light diffs for vert/horiz walls
|
SBYTE WallVertLight; // Light diffs for vert/horiz walls
|
||||||
|
|
|
@ -91,14 +91,9 @@ public:
|
||||||
class ASkyViewpoint : public AActor
|
class ASkyViewpoint : public AActor
|
||||||
{
|
{
|
||||||
DECLARE_CLASS (ASkyViewpoint, AActor)
|
DECLARE_CLASS (ASkyViewpoint, AActor)
|
||||||
HAS_OBJECT_POINTERS
|
|
||||||
public:
|
public:
|
||||||
void Serialize (FArchive &arc);
|
|
||||||
void BeginPlay ();
|
void BeginPlay ();
|
||||||
void Destroy ();
|
void Destroy ();
|
||||||
bool bInSkybox;
|
|
||||||
bool bAlways;
|
|
||||||
TObjPtr<ASkyViewpoint> Mate;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// For an EE compatible linedef based definition.
|
// For an EE compatible linedef based definition.
|
||||||
|
|
|
@ -38,49 +38,42 @@
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "farchive.h"
|
#include "farchive.h"
|
||||||
#include "r_sky.h"
|
#include "r_sky.h"
|
||||||
|
#include "portal.h"
|
||||||
|
|
||||||
// arg0 = Visibility*4 for this skybox
|
// arg0 = Visibility*4 for this skybox
|
||||||
|
|
||||||
IMPLEMENT_POINTY_CLASS (ASkyViewpoint)
|
IMPLEMENT_CLASS (ASkyViewpoint)
|
||||||
DECLARE_POINTER(Mate)
|
|
||||||
END_POINTERS
|
|
||||||
|
|
||||||
// If this actor has no TID, make it the default sky box
|
// If this actor has no TID, make it the default sky box
|
||||||
void ASkyViewpoint::BeginPlay ()
|
void ASkyViewpoint::BeginPlay ()
|
||||||
{
|
{
|
||||||
Super::BeginPlay ();
|
Super::BeginPlay ();
|
||||||
|
|
||||||
if (tid == 0 && level.DefaultSkybox == NULL)
|
if (tid == 0 && sectorPortals[0].mSkybox == nullptr)
|
||||||
{
|
{
|
||||||
level.DefaultSkybox = this;
|
sectorPortals[0].mSkybox = this;
|
||||||
|
sectorPortals[0].mDestination = Sector;
|
||||||
}
|
}
|
||||||
special1 = SKYBOX_SKYVIEWPOINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ASkyViewpoint::Serialize (FArchive &arc)
|
|
||||||
{
|
|
||||||
Super::Serialize (arc);
|
|
||||||
arc << bInSkybox << bAlways << Mate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASkyViewpoint::Destroy ()
|
void ASkyViewpoint::Destroy ()
|
||||||
{
|
{
|
||||||
// remove all sector references to ourselves.
|
// remove all sector references to ourselves.
|
||||||
for (int i = 0; i <numsectors; i++)
|
for (int i = 0; i < numsectors; i++)
|
||||||
{
|
{
|
||||||
if (sectors[i].SkyBoxes[sector_t::floor] == this)
|
if (sectors[i].GetPortal(sector_t::floor)->mSkybox == this)
|
||||||
{
|
sectors[i].ClearPortal(sector_t::floor);
|
||||||
sectors[i].SkyBoxes[sector_t::floor] = NULL;
|
if (sectors[i].GetPortal(sector_t::ceiling)->mSkybox == this)
|
||||||
}
|
sectors[i].ClearPortal(sector_t::ceiling);
|
||||||
if (sectors[i].SkyBoxes[sector_t::ceiling] == this)
|
|
||||||
{
|
|
||||||
sectors[i].SkyBoxes[sector_t::ceiling] = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (level.DefaultSkybox == this)
|
for (auto &s : sectorPortals)
|
||||||
{
|
{
|
||||||
level.DefaultSkybox = NULL;
|
if (s.mSkybox == this) s.mSkybox = 0;
|
||||||
|
// This is necessary to entirely disable EE-style skyboxes
|
||||||
|
// if their viewpoint gets deleted.
|
||||||
|
s.mFlags |= PORTSF_SKYFLATONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Super::Destroy();
|
Super::Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,10 +83,8 @@ void ASkyCamCompat::BeginPlay()
|
||||||
{
|
{
|
||||||
// Do not call the SkyViewpoint's super method because it would trash our setup
|
// Do not call the SkyViewpoint's super method because it would trash our setup
|
||||||
AActor::BeginPlay();
|
AActor::BeginPlay();
|
||||||
special1 = SKYBOX_SKYVIEWPOINT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
// arg0 = tid of matching SkyViewpoint
|
// arg0 = tid of matching SkyViewpoint
|
||||||
|
@ -130,20 +121,18 @@ void ASkyPicker::PostBeginPlay ()
|
||||||
|
|
||||||
if (box == NULL && args[0] != 0)
|
if (box == NULL && args[0] != 0)
|
||||||
{
|
{
|
||||||
Printf ("Can't find SkyViewpoint %d for sector %td\n",
|
Printf ("Can't find SkyViewpoint %d for sector %td\n", args[0], Sector - sectors);
|
||||||
args[0], Sector - sectors);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int boxindex = P_GetSkyboxPortal(box);
|
||||||
if (0 == (args[1] & 2))
|
if (0 == (args[1] & 2))
|
||||||
{
|
{
|
||||||
Sector->SkyBoxes[sector_t::ceiling] = box;
|
Sector->Portals[sector_t::ceiling] = boxindex;
|
||||||
if (box == NULL) Sector->MoreFlags |= SECF_NOCEILINGSKYBOX; // sector should ignore the level's default skybox
|
|
||||||
}
|
}
|
||||||
if (0 == (args[1] & 1))
|
if (0 == (args[1] & 1))
|
||||||
{
|
{
|
||||||
Sector->SkyBoxes[sector_t::floor] = box;
|
Sector->Portals[sector_t::floor] = boxindex;
|
||||||
if (box == NULL) Sector->MoreFlags |= SECF_NOFLOORSKYBOX; // sector should ignore the level's default skybox
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Destroy ();
|
Destroy ();
|
||||||
|
@ -160,9 +149,6 @@ void AStackPoint::BeginPlay ()
|
||||||
{
|
{
|
||||||
// Skip SkyViewpoint's initialization
|
// Skip SkyViewpoint's initialization
|
||||||
AActor::BeginPlay ();
|
AActor::BeginPlay ();
|
||||||
|
|
||||||
bAlways = true;
|
|
||||||
special1 = SKYBOX_STACKEDSECTORTHING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
|
@ -1629,10 +1629,10 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, DVector3 *optpos)
|
||||||
return saved->getPortal()->mType == PORTT_LINKED? 1:-1;
|
return saved->getPortal()->mType == PORTT_LINKED? 1:-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FPathTraverse::PortalRelocate(AActor *portalthing, int flags, double hitfrac)
|
void FPathTraverse::PortalRelocate(const DVector2 &displacement, int flags, double hitfrac)
|
||||||
{
|
{
|
||||||
double hitx = trace.x + portalthing->Scale.X;
|
double hitx = trace.x + displacement.X;
|
||||||
double hity = trace.y + portalthing->Scale.Y;
|
double hity = trace.y + displacement.Y;
|
||||||
double endx = hitx + trace.dx;
|
double endx = hitx + trace.dx;
|
||||||
double endy = hity + trace.dy;
|
double endy = hity + trace.dy;
|
||||||
intercepts.Resize(intercept_index);
|
intercepts.Resize(intercept_index);
|
||||||
|
|
|
@ -373,7 +373,7 @@ public:
|
||||||
}
|
}
|
||||||
void init(double x1, double y1, double x2, double y2, int flags, double startfrac = 0);
|
void init(double x1, double y1, double x2, double y2, int flags, double startfrac = 0);
|
||||||
int PortalRelocate(intercept_t *in, int flags, DVector3 *optpos = NULL);
|
int PortalRelocate(intercept_t *in, int flags, DVector3 *optpos = NULL);
|
||||||
void PortalRelocate(AActor *portalthing, int flags, double hitfrac);
|
void PortalRelocate(const DVector2 &disp, int flags, double hitfrac);
|
||||||
virtual ~FPathTraverse();
|
virtual ~FPathTraverse();
|
||||||
const divline_t &Trace() const { return trace; }
|
const divline_t &Trace() const { return trace; }
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,7 @@ void P_SerializeWorld (FArchive &arc)
|
||||||
<< sec->sky
|
<< sec->sky
|
||||||
<< sec->MoreFlags
|
<< sec->MoreFlags
|
||||||
<< sec->Flags
|
<< sec->Flags
|
||||||
<< sec->SkyBoxes[sector_t::floor] << sec->SkyBoxes[sector_t::ceiling]
|
<< sec->Portals[sector_t::floor] << sec->Portals[sector_t::ceiling]
|
||||||
<< sec->ZoneNumber;
|
<< sec->ZoneNumber;
|
||||||
arc << sec->interpolations[0]
|
arc << sec->interpolations[0]
|
||||||
<< sec->interpolations[1]
|
<< sec->interpolations[1]
|
||||||
|
@ -449,7 +449,7 @@ void P_SerializeWorld (FArchive &arc)
|
||||||
arc << zn->Environment;
|
arc << zn->Environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
arc << linePortals;
|
arc << linePortals << sectorPortals;
|
||||||
P_CollectLinkedPortals();
|
P_CollectLinkedPortals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,22 +565,8 @@ void P_SerializePolyobjs (FArchive &arc)
|
||||||
I_Error ("UnarchivePolyobjs: Invalid polyobj tag");
|
I_Error ("UnarchivePolyobjs: Invalid polyobj tag");
|
||||||
}
|
}
|
||||||
arc << angle << delta << po->interpolation;
|
arc << angle << delta << po->interpolation;
|
||||||
if (SaveVersion >= 4537)
|
arc << po->bBlocked;
|
||||||
{
|
arc << po->bHasPortals;
|
||||||
arc << po->bBlocked;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
po->bBlocked = false;
|
|
||||||
}
|
|
||||||
if (SaveVersion >= 4538)
|
|
||||||
{
|
|
||||||
arc << po->bHasPortals;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
po->bHasPortals = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
po->RotatePolyobj (angle, true);
|
po->RotatePolyobj (angle, true);
|
||||||
delta -= po->StartSpot.pos;
|
delta -= po->StartSpot.pos;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "r_utility.h"
|
#include "r_utility.h"
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
|
#include "r_sky.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -803,11 +804,13 @@ int sector_t::GetCeilingLight () const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ASkyViewpoint *sector_t::GetSkyBox(int which)
|
FSectorPortal *sector_t::ValidatePortal(int which)
|
||||||
{
|
{
|
||||||
if (SkyBoxes[which] != NULL) return barrier_cast<ASkyViewpoint*>(SkyBoxes[which]);
|
FSectorPortal *port = GetPortal(which);
|
||||||
if (MoreFlags & (SECF_NOFLOORSKYBOX << which)) return NULL;
|
if (port->mType == PORTS_SKYVIEWPOINT && port->mSkybox == nullptr) return nullptr; // A skybox without a viewpoint is just a regular sky.
|
||||||
return level.DefaultSkybox;
|
if (PortalBlocksView(which)) return nullptr; // disabled or obstructed linked portal.
|
||||||
|
if ((port->mFlags & PORTSF_SKYFLATONLY) && GetTexture(which) != skyflatnum) return nullptr; // Skybox without skyflat texture
|
||||||
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -873,13 +876,13 @@ int sector_t::GetTerrain(int pos) const
|
||||||
|
|
||||||
void sector_t::CheckPortalPlane(int plane)
|
void sector_t::CheckPortalPlane(int plane)
|
||||||
{
|
{
|
||||||
AActor *portal = SkyBoxes[plane];
|
if (GetPortalType(plane) == PORTS_LINKEDPORTAL)
|
||||||
if (!portal || portal->special1 != SKYBOX_LINKEDPORTAL) return;
|
{
|
||||||
|
double portalh = GetPortalPlaneZ(plane);
|
||||||
double planeh = GetPlaneTexZF(plane);
|
double planeh = GetPlaneTexZF(plane);
|
||||||
int obstructed = PLANEF_OBSTRUCTED * (plane == sector_t::floor ?
|
int obstructed = PLANEF_OBSTRUCTED * (plane == sector_t::floor ? planeh > portalh : planeh < portalh);
|
||||||
planeh > portal->specialf1 : planeh < portal->specialf1);
|
planes[plane].Flags = (planes[plane].Flags & ~PLANEF_OBSTRUCTED) | obstructed;
|
||||||
planes[plane].Flags = (planes[plane].Flags & ~PLANEF_OBSTRUCTED) | obstructed;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
106
src/p_spec.cpp
106
src/p_spec.cpp
|
@ -838,12 +838,13 @@ static void SetupFloorPortal (AStackPoint *point)
|
||||||
NActorIterator it (NAME_LowerStackLookOnly, point->tid);
|
NActorIterator it (NAME_LowerStackLookOnly, point->tid);
|
||||||
sector_t *Sector = point->Sector;
|
sector_t *Sector = point->Sector;
|
||||||
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
||||||
Sector->SkyBoxes[sector_t::floor] = skyv;
|
if (skyv != NULL)
|
||||||
if (skyv != NULL && skyv->bAlways)
|
|
||||||
{
|
{
|
||||||
skyv->Mate = point;
|
skyv->target = point;
|
||||||
if (Sector->GetAlphaF(sector_t::floor) == 1.)
|
if (Sector->GetAlphaF(sector_t::floor) == 1.)
|
||||||
Sector->SetAlpha(sector_t::floor, clamp(point->args[0], 0, 255) / 255.);
|
Sector->SetAlpha(sector_t::floor, clamp(point->args[0], 0, 255) / 255.);
|
||||||
|
|
||||||
|
Sector->Portals[sector_t::floor] = P_GetStackPortal(skyv, sector_t::floor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,12 +853,13 @@ static void SetupCeilingPortal (AStackPoint *point)
|
||||||
NActorIterator it (NAME_UpperStackLookOnly, point->tid);
|
NActorIterator it (NAME_UpperStackLookOnly, point->tid);
|
||||||
sector_t *Sector = point->Sector;
|
sector_t *Sector = point->Sector;
|
||||||
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
||||||
Sector->SkyBoxes[sector_t::ceiling] = skyv;
|
if (skyv != NULL)
|
||||||
if (skyv != NULL && skyv->bAlways)
|
|
||||||
{
|
{
|
||||||
skyv->Mate = point;
|
skyv->target = point;
|
||||||
if (Sector->GetAlphaF(sector_t::ceiling) == 1.)
|
if (Sector->GetAlphaF(sector_t::ceiling) == 1.)
|
||||||
Sector->SetAlpha(sector_t::ceiling, clamp(point->args[0], 0, 255) / 255.);
|
Sector->SetAlpha(sector_t::ceiling, clamp(point->args[0], 0, 255) / 255.);
|
||||||
|
|
||||||
|
Sector->Portals[sector_t::ceiling] = P_GetStackPortal(skyv, sector_t::ceiling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -881,42 +883,68 @@ void P_SetupPortals()
|
||||||
pt->special1 = 0;
|
pt->special1 = 0;
|
||||||
points.Push(pt);
|
points.Push(pt);
|
||||||
}
|
}
|
||||||
|
// the semantics here are incredibly lax so the final setup can only be done once all portals have been created,
|
||||||
|
// because later stackpoints will happily overwrite info in older ones, if there are multiple links.
|
||||||
|
for (auto &s : sectorPortals)
|
||||||
|
{
|
||||||
|
if (s.mType == PORTS_STACKEDSECTORTHING && s.mSkybox)
|
||||||
|
{
|
||||||
|
for (auto &ss : sectorPortals)
|
||||||
|
{
|
||||||
|
if (ss.mType == PORTS_STACKEDSECTORTHING && ss.mSkybox == s.mSkybox->target)
|
||||||
|
{
|
||||||
|
s.mPartner = (&ss) - §orPortals[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Now we can finally set the displacement and delete the stackpoint reference.
|
||||||
|
for (auto &s : sectorPortals)
|
||||||
|
{
|
||||||
|
if (s.mType == PORTS_STACKEDSECTORTHING && s.mSkybox)
|
||||||
|
{
|
||||||
|
s.mDisplacement = s.mSkybox->Pos() - s.mSkybox->target->Pos();
|
||||||
|
s.mSkybox = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, double alpha)
|
static void SetPortal(sector_t *sector, int plane, unsigned pnum, double alpha)
|
||||||
{
|
{
|
||||||
// plane: 0=floor, 1=ceiling, 2=both
|
// plane: 0=floor, 1=ceiling, 2=both
|
||||||
if (plane > 0)
|
if (plane > 0)
|
||||||
{
|
{
|
||||||
if (sector->SkyBoxes[sector_t::ceiling] == NULL || !barrier_cast<ASkyViewpoint*>(sector->SkyBoxes[sector_t::ceiling])->bAlways)
|
if (sector->GetPortalType(sector_t::ceiling) == PORTS_SKYVIEWPOINT)
|
||||||
{
|
{
|
||||||
sector->SkyBoxes[sector_t::ceiling] = portal;
|
sector->Portals[sector_t::ceiling] = pnum;
|
||||||
if (sector->GetAlphaF(sector_t::ceiling) == 1.)
|
if (sector->GetAlphaF(sector_t::ceiling) == 1.)
|
||||||
sector->SetAlpha(sector_t::ceiling, alpha);
|
sector->SetAlpha(sector_t::ceiling, alpha);
|
||||||
|
|
||||||
if (!portal->bAlways) sector->SetTexture(sector_t::ceiling, skyflatnum);
|
if (sectorPortals[pnum].mFlags & PORTSF_SKYFLATONLY)
|
||||||
|
sector->SetTexture(sector_t::ceiling, skyflatnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (plane == 2 || plane == 0)
|
if (plane == 2 || plane == 0)
|
||||||
{
|
{
|
||||||
if (sector->SkyBoxes[sector_t::floor] == NULL || !barrier_cast<ASkyViewpoint*>(sector->SkyBoxes[sector_t::floor])->bAlways)
|
if (sector->GetPortalType(sector_t::floor) == PORTS_SKYVIEWPOINT)
|
||||||
{
|
{
|
||||||
sector->SkyBoxes[sector_t::floor] = portal;
|
sector->Portals[sector_t::floor] = pnum;
|
||||||
}
|
}
|
||||||
if (sector->GetAlphaF(sector_t::floor) == 1.)
|
if (sector->GetAlphaF(sector_t::floor) == 1.)
|
||||||
sector->SetAlpha(sector_t::floor, alpha);
|
sector->SetAlpha(sector_t::floor, alpha);
|
||||||
|
|
||||||
if (!portal->bAlways) sector->SetTexture(sector_t::floor, skyflatnum);
|
if (sectorPortals[pnum].mFlags & PORTSF_SKYFLATONLY)
|
||||||
|
sector->SetTexture(sector_t::floor, skyflatnum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CopyPortal(int sectortag, int plane, ASkyViewpoint *origin, double alpha, bool tolines)
|
static void CopyPortal(int sectortag, int plane, unsigned pnum, double alpha, bool tolines)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
FSectorTagIterator itr(sectortag);
|
FSectorTagIterator itr(sectortag);
|
||||||
while ((s = itr.Next()) >= 0)
|
while ((s = itr.Next()) >= 0)
|
||||||
{
|
{
|
||||||
SetPortal(§ors[s], plane, origin, alpha);
|
SetPortal(§ors[s], plane, pnum, alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j=0;j<numlines;j++)
|
for (int j=0;j<numlines;j++)
|
||||||
|
@ -930,20 +958,21 @@ static void CopyPortal(int sectortag, int plane, ASkyViewpoint *origin, double a
|
||||||
{
|
{
|
||||||
if (lines[j].args[0] == 0)
|
if (lines[j].args[0] == 0)
|
||||||
{
|
{
|
||||||
SetPortal(lines[j].frontsector, plane, origin, alpha);
|
SetPortal(lines[j].frontsector, plane, pnum, alpha);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
FSectorTagIterator itr(lines[j].args[0]);
|
FSectorTagIterator itr(lines[j].args[0]);
|
||||||
while ((s = itr.Next()) >= 0)
|
while ((s = itr.Next()) >= 0)
|
||||||
{
|
{
|
||||||
SetPortal(§ors[s], plane, origin, alpha);
|
SetPortal(§ors[s], plane, pnum, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void P_SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int linked)
|
void P_SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int linked)
|
||||||
{
|
{
|
||||||
if (plane < 0 || plane > 2 || (linked && plane == 2)) return;
|
if (plane < 0 || plane > 2 || (linked && plane == 2)) return;
|
||||||
|
@ -958,36 +987,10 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int li
|
||||||
lines[i].args[3] == 1)
|
lines[i].args[3] == 1)
|
||||||
{
|
{
|
||||||
// beware of overflows.
|
// beware of overflows.
|
||||||
DVector3 pos1((line->v1->fX() + line->v2->fX()) / 2, (line->v1->fY() + line->v2->fY()) / 2, 0);
|
DVector2 pos1 = line->v1->fPos() + line->Delta() / 2;
|
||||||
DVector3 pos2((lines[i].v1->fX() + lines[i].v2->fX()) / 2, (lines[i].v1->fY() + lines[i].v2->fY()) / 2, 0);
|
DVector2 pos2 = lines[i].v1->fPos() + lines[i].Delta() / 2;
|
||||||
double z = linked ? line->frontsector->GetPlaneTexZF(plane) : 0; // the map's sector height defines the portal plane for linked portals
|
unsigned pnum = P_GetPortal(linked ? PORTS_LINKEDPORTAL : PORTS_PORTAL, plane, line->frontsector, lines[i].frontsector, pos2 - pos1);
|
||||||
|
CopyPortal(sectortag, plane, pnum, bytealpha / 255., false);
|
||||||
double alpha = bytealpha / 255.;
|
|
||||||
|
|
||||||
AStackPoint *anchor = Spawn<AStackPoint>(pos1, NO_REPLACE);
|
|
||||||
AStackPoint *reference = Spawn<AStackPoint>(pos2, NO_REPLACE);
|
|
||||||
|
|
||||||
// In some situations it can happen that the sector here is not the frontsector of the anchor linedef,
|
|
||||||
// because some colinear node line with opposite direction causes this to be positioned on the wrong side.
|
|
||||||
// Fortunately these things will never move so it should be sufficient to set the intended sector directly.
|
|
||||||
anchor->Sector = line->frontsector;
|
|
||||||
reference->Sector = lines[i].frontsector;
|
|
||||||
|
|
||||||
reference->special1 = linked ? SKYBOX_LINKEDPORTAL : SKYBOX_PORTAL;
|
|
||||||
anchor->special1 = SKYBOX_ANCHOR;
|
|
||||||
// store the portal displacement in the unused scaleX/Y members of the portal reference actor.
|
|
||||||
anchor->Scale = -(reference->Scale = pos2 - pos1);
|
|
||||||
anchor->specialf1 = reference->specialf1 = z;
|
|
||||||
|
|
||||||
reference->Mate = anchor;
|
|
||||||
anchor->Mate = reference;
|
|
||||||
|
|
||||||
// This is so that the renderer can distinguish these portals from
|
|
||||||
// the ones spawned with the '*StackLookOnly' things.
|
|
||||||
reference->flags |= MF_JUSTATTACKED;
|
|
||||||
anchor->flags |= MF_JUSTATTACKED;
|
|
||||||
|
|
||||||
CopyPortal(sectortag, plane, reference, alpha, false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1012,7 +1015,8 @@ void P_SpawnSkybox(ASkyViewpoint *origin)
|
||||||
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
if (refline->special == Sector_SetPortal && refline->args[1] == 2)
|
||||||
{
|
{
|
||||||
// We found the setup linedef for this skybox, so let's use it for our init.
|
// We found the setup linedef for this skybox, so let's use it for our init.
|
||||||
CopyPortal(refline->args[0], refline->args[2], origin, 0, true);
|
unsigned pnum = P_GetSkyboxPortal(origin);
|
||||||
|
CopyPortal(refline->args[0], refline->args[2], pnum, 0, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1334,6 +1338,12 @@ void P_SpawnSpecials (void)
|
||||||
{
|
{
|
||||||
P_SpawnPortal(&lines[i], lines[i].args[0], lines[i].args[2], lines[i].args[4], lines[i].args[1]);
|
P_SpawnPortal(&lines[i], lines[i].args[0], lines[i].args[2], lines[i].args[4], lines[i].args[1]);
|
||||||
}
|
}
|
||||||
|
else if (lines[i].args[1] == 3 || lines[i].args[1] == 4)
|
||||||
|
{
|
||||||
|
line_t *line = &lines[i];
|
||||||
|
unsigned pnum = P_GetPortal(line->args[1] == 3 ? PORTS_PLANE : PORTS_HORIZON, line->args[2], line->frontsector, NULL, { 0,0 });
|
||||||
|
CopyPortal(line->args[0], line->args[2], pnum, 0, true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Line_SetPortal:
|
case Line_SetPortal:
|
||||||
|
|
|
@ -216,7 +216,7 @@ void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac,
|
||||||
inshootthrough = true;
|
inshootthrough = true;
|
||||||
startfrac = frac;
|
startfrac = frac;
|
||||||
EnterDist = enterdist;
|
EnterDist = enterdist;
|
||||||
pt.PortalRelocate(entersec->SkyBoxes[position], ptflags, frac);
|
pt.PortalRelocate(entersec->GetPortal(position)->mDisplacement, ptflags, frac);
|
||||||
|
|
||||||
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
||||||
{
|
{
|
||||||
|
@ -321,7 +321,7 @@ void FTraceInfo::Setup3DFloors()
|
||||||
{
|
{
|
||||||
CurSector->floorplane = *rover->top.plane;
|
CurSector->floorplane = *rover->top.plane;
|
||||||
CurSector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
CurSector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||||
CurSector->SkyBoxes[sector_t::floor] = nullptr;
|
CurSector->ClearPortal(sector_t::floor);
|
||||||
bf = ff_top;
|
bf = ff_top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ void FTraceInfo::Setup3DFloors()
|
||||||
CurSector->ceilingplane = *rover->bottom.plane;
|
CurSector->ceilingplane = *rover->bottom.plane;
|
||||||
CurSector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
CurSector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||||
bc = ff_bottom;
|
bc = ff_bottom;
|
||||||
CurSector->SkyBoxes[sector_t::ceiling] = nullptr;
|
CurSector->ClearPortal(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -343,7 +343,7 @@ void FTraceInfo::Setup3DFloors()
|
||||||
{
|
{
|
||||||
CurSector->floorplane = *rover->bottom.plane;
|
CurSector->floorplane = *rover->bottom.plane;
|
||||||
CurSector->SetTexture(sector_t::floor, *rover->bottom.texture, false);
|
CurSector->SetTexture(sector_t::floor, *rover->bottom.texture, false);
|
||||||
CurSector->SkyBoxes[sector_t::floor] = nullptr;
|
CurSector->ClearPortal(sector_t::floor);
|
||||||
bf = ff_bottom;
|
bf = ff_bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +351,7 @@ void FTraceInfo::Setup3DFloors()
|
||||||
{
|
{
|
||||||
CurSector->ceilingplane = *rover->top.plane;
|
CurSector->ceilingplane = *rover->top.plane;
|
||||||
CurSector->SetTexture(sector_t::ceiling, *rover->top.texture, false);
|
CurSector->SetTexture(sector_t::ceiling, *rover->top.texture, false);
|
||||||
CurSector->SkyBoxes[sector_t::ceiling] = nullptr;
|
CurSector->ClearPortal(sector_t::ceiling);
|
||||||
bc = ff_top;
|
bc = ff_top;
|
||||||
}
|
}
|
||||||
inshootthrough = false;
|
inshootthrough = false;
|
||||||
|
@ -499,7 +499,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
||||||
{
|
{
|
||||||
entersector->floorplane = *rover->top.plane;
|
entersector->floorplane = *rover->top.plane;
|
||||||
entersector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
entersector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||||
entersector->SkyBoxes[sector_t::floor] = NULL;
|
entersector->ClearPortal(sector_t::floor);
|
||||||
bf = ff_top;
|
bf = ff_top;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -510,7 +510,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
||||||
{
|
{
|
||||||
entersector->ceilingplane = *rover->bottom.plane;
|
entersector->ceilingplane = *rover->bottom.plane;
|
||||||
entersector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
entersector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||||
entersector->SkyBoxes[sector_t::ceiling] = NULL;
|
entersector->ClearPortal(sector_t::ceiling);
|
||||||
bc = ff_bottom;
|
bc = ff_bottom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
192
src/portal.cpp
192
src/portal.cpp
|
@ -64,6 +64,8 @@ FPortalBlockmap PortalBlockmap;
|
||||||
TArray<FLinePortal> linePortals;
|
TArray<FLinePortal> linePortals;
|
||||||
TArray<FLinePortal*> linkedPortals; // only the linked portals, this is used to speed up looking for them in P_CollectConnectedGroups.
|
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.
|
// This is used to mark processed portals for some collection functions.
|
||||||
|
@ -213,6 +215,26 @@ FArchive &operator<< (FArchive &arc, FLinePortal &port)
|
||||||
return arc;
|
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);
|
Displacements.Create(1);
|
||||||
linePortals.Clear();
|
linePortals.Clear();
|
||||||
linkedPortals.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.
|
// 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
|
// 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 thisgroup = portal->mOrigin->PortalGroup;
|
||||||
int othergroup = portal->Sector->PortalGroup;
|
int othergroup = portal->mDestination->PortalGroup;
|
||||||
if (thisgroup == othergroup)
|
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);
|
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->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
portal->mType = PORTS_PORTAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (thisgroup <= 0 || thisgroup >= Displacements.size || othergroup <= 0 || othergroup >= Displacements.size)
|
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);
|
Printf("Portal between sectors %d and %d has invalid group and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
|
||||||
portal->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
portal->mType = PORTS_PORTAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
FDisplacement & disp = Displacements(thisgroup, othergroup);
|
FDisplacement & disp = Displacements(thisgroup, othergroup);
|
||||||
if (!disp.isSet)
|
if (!disp.isSet)
|
||||||
{
|
{
|
||||||
disp.pos = portal->Scale;
|
disp.pos = portal->mDisplacement;
|
||||||
disp.isSet = true;
|
disp.isSet = true;
|
||||||
}
|
}
|
||||||
else
|
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);
|
Printf("Portal between sectors %d and %d has displacement mismatch and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
|
||||||
portal->special1 = portal->Mate->special1 = SKYBOX_PORTAL;
|
portal->mType = PORTS_PORTAL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -895,55 +993,43 @@ static bool ConnectGroups()
|
||||||
|
|
||||||
void P_CreateLinkedPortals()
|
void P_CreateLinkedPortals()
|
||||||
{
|
{
|
||||||
TThinkerIterator<AStackPoint> it;
|
TArray<FSectorPortal *> orgs;
|
||||||
AStackPoint *mo;
|
|
||||||
TArray<AStackPoint *> orgs;
|
|
||||||
int id = 1;
|
int id = 1;
|
||||||
bool bogus = false;
|
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(&s);
|
||||||
{
|
|
||||||
orgs.Push(mo);
|
|
||||||
mo->reactiontime = ++id;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// this should never happen, but if it does, the portal needs to be removed
|
|
||||||
mo->Destroy();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id = 1;
|
id = 1;
|
||||||
if (orgs.Size() != 0)
|
if (orgs.Size() != 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numsectors; i++)
|
for (int i = 0; i < numsectors; i++)
|
||||||
{
|
|
||||||
for (int j = 0; j < 2; j++)
|
|
||||||
{
|
{
|
||||||
AActor *box = sectors[i].SkyBoxes[j];
|
for (int j = 0; j < 2; j++)
|
||||||
if (box != NULL && box->special1 == SKYBOX_LINKEDPORTAL)
|
|
||||||
{
|
{
|
||||||
secplane_t &plane = j == 0 ? sectors[i].floorplane : sectors[i].ceilingplane;
|
if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL)
|
||||||
if (plane.isSlope())
|
|
||||||
{
|
{
|
||||||
// The engine cannot deal with portals on a sloped plane.
|
secplane_t &plane = j == 0 ? sectors[i].floorplane : sectors[i].ceilingplane;
|
||||||
sectors[i].SkyBoxes[j] = NULL;
|
if (plane.isSlope())
|
||||||
Printf("Portal on %s of sector %d is sloped and will be disabled\n", j == 0 ? "floor" : "ceiling", i);
|
{
|
||||||
|
// 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.
|
// Group all sectors, starting at each portal origin.
|
||||||
for (unsigned i = 0; i < orgs.Size(); i++)
|
for (unsigned i = 0; i < orgs.Size(); i++)
|
||||||
{
|
{
|
||||||
if (CollectSectors(id, orgs[i]->Sector)) id++;
|
if (CollectSectors(id, orgs[i]->mOrigin)) id++;
|
||||||
if (CollectSectors(id, orgs[i]->Mate->Sector)) id++;
|
if (CollectSectors(id, orgs[i]->mDestination)) id++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (unsigned i = 0; i < linePortals.Size(); i++)
|
for (unsigned i = 0; i < linePortals.Size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -960,17 +1046,9 @@ void P_CreateLinkedPortals()
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 2; j++)
|
for (int j = 0; j < 2; j++)
|
||||||
{
|
{
|
||||||
ASkyViewpoint *box = barrier_cast<ASkyViewpoint*>(sectors[i].SkyBoxes[j]);
|
if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL && sectors[i].PortalGroup == 0)
|
||||||
if (box != NULL)
|
|
||||||
{
|
{
|
||||||
if (box->special1 == SKYBOX_LINKEDPORTAL && sectors[i].PortalGroup == 0)
|
CollectSectors(sectors[i].GetOppositePortalGroup(j), §ors[i]);
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1060,11 +1138,11 @@ void P_CreateLinkedPortals()
|
||||||
double fp = sectors[i].floorplane.fD();
|
double fp = sectors[i].floorplane.fD();
|
||||||
if (cp < fp || fz == fp)
|
if (cp < fp || fz == fp)
|
||||||
{
|
{
|
||||||
sectors[i].SkyBoxes[sector_t::ceiling] = NULL;
|
sectors[i].ClearPortal(sector_t::ceiling);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sectors[i].SkyBoxes[sector_t::floor] = NULL;
|
sectors[i].ClearPortal(sector_t::floor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
57
src/portal.h
57
src/portal.h
|
@ -6,6 +6,7 @@
|
||||||
#include "m_bbox.h"
|
#include "m_bbox.h"
|
||||||
|
|
||||||
struct FPortalGroupArray;
|
struct FPortalGroupArray;
|
||||||
|
class ASkyViewpoint;
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// This table holds the offsets for the different parts of a map
|
// This table holds the offsets for the different parts of a map
|
||||||
|
@ -173,8 +174,6 @@ enum
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// All information about a line-to-line portal (all types)
|
// All information about a line-to-line portal (all types)
|
||||||
// There is no structure for sector plane portals because for historic
|
|
||||||
// reasons those use actors to connect.
|
|
||||||
//
|
//
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
@ -190,10 +189,61 @@ struct FLinePortal
|
||||||
DAngle mAngleDiff;
|
DAngle mAngleDiff;
|
||||||
double mSinRot;
|
double mSinRot;
|
||||||
double mCosRot;
|
double mCosRot;
|
||||||
|
void *mRenderData;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TArray<FLinePortal> linePortals;
|
extern TArray<FLinePortal> linePortals;
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// All information about a sector plane portal
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PORTS_SKYVIEWPOINT = 0, // a regular skybox
|
||||||
|
PORTS_STACKEDSECTORTHING, // stacked sectors with the thing method
|
||||||
|
PORTS_PORTAL, // stacked sectors with Sector_SetPortal
|
||||||
|
PORTS_LINKEDPORTAL, // linked portal (interactive)
|
||||||
|
PORTS_PLANE, // EE-style plane portal (not implemented in SW renderer)
|
||||||
|
PORTS_HORIZON, // EE-style horizon portal (not implemented in SW renderer)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PORTSF_SKYFLATONLY = 1, // portal is only active on skyflatnum
|
||||||
|
PORTSF_INSKYBOX = 2, // to avoid recursion
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FSectorPortal
|
||||||
|
{
|
||||||
|
int mType;
|
||||||
|
int mFlags;
|
||||||
|
unsigned mPartner;
|
||||||
|
int mPlane;
|
||||||
|
sector_t *mOrigin;
|
||||||
|
sector_t *mDestination;
|
||||||
|
DVector2 mDisplacement;
|
||||||
|
double mPlaneZ;
|
||||||
|
TObjPtr<AActor> mSkybox;
|
||||||
|
void *mRenderData;
|
||||||
|
|
||||||
|
bool MergeAllowed() const
|
||||||
|
{
|
||||||
|
// For thing based stack sectors and regular skies the portal has no relevance for merging visplanes.
|
||||||
|
return (mType == PORTS_STACKEDSECTORTHING || (mType == PORTS_SKYVIEWPOINT && (mFlags & PORTSF_SKYFLATONLY)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern TArray<FSectorPortal> sectorPortals;
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// Functions
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
void P_ClearPortals();
|
void P_ClearPortals();
|
||||||
void P_SpawnLinePortal(line_t* line);
|
void P_SpawnLinePortal(line_t* line);
|
||||||
void P_FinalizePortals();
|
void P_FinalizePortals();
|
||||||
|
@ -205,6 +255,9 @@ inline int P_NumPortalGroups()
|
||||||
{
|
{
|
||||||
return Displacements.size;
|
return Displacements.size;
|
||||||
}
|
}
|
||||||
|
unsigned P_GetSkyboxPortal(ASkyViewpoint *actor);
|
||||||
|
unsigned P_GetPortal(int type, int plane, sector_t *orgsec, sector_t *destsec, const DVector2 &displacement);
|
||||||
|
unsigned P_GetStackPortal(AActor *point, int plane);
|
||||||
|
|
||||||
|
|
||||||
/* code ported from prototype */
|
/* code ported from prototype */
|
||||||
|
|
|
@ -515,18 +515,18 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
|
||||||
|
|
||||||
bool R_SkyboxCompare(sector_t *frontsector, sector_t *backsector)
|
bool R_SkyboxCompare(sector_t *frontsector, sector_t *backsector)
|
||||||
{
|
{
|
||||||
AActor *frontc = frontsector->SkyBoxes[sector_t::ceiling];
|
FSectorPortal *frontc = frontsector->GetPortal(sector_t::ceiling);
|
||||||
AActor *frontf = frontsector->SkyBoxes[sector_t::floor];
|
FSectorPortal *frontf = frontsector->GetPortal(sector_t::floor);
|
||||||
AActor *backc = backsector->SkyBoxes[sector_t::ceiling];
|
FSectorPortal *backc = backsector->GetPortal(sector_t::ceiling);
|
||||||
AActor *backf = backsector->SkyBoxes[sector_t::floor];
|
FSectorPortal *backf = backsector->GetPortal(sector_t::floor);
|
||||||
|
|
||||||
// return true if any of the planes has a linedef-based portal (unless both sides have the same one.
|
// return true if any of the planes has a linedef-based portal (unless both sides have the same one.
|
||||||
// Ideally this should also check thing based portals but the omission of this check had been abused to hell and back for those.
|
// Ideally this should also check thing based portals but the omission of this check had been abused to hell and back for those.
|
||||||
// (Note: This may require a compatibility option if some maps ran into this for line based portals as well.)
|
// (Note: This may require a compatibility option if some maps ran into this for line based portals as well.)
|
||||||
if (frontc != NULL && (frontc->special1 == SKYBOX_PORTAL || frontc->special1 == SKYBOX_LINKEDPORTAL)) return (frontc != backc);
|
if (!frontc->MergeAllowed()) return (frontc != backc);
|
||||||
if (frontf != NULL && (frontf->special1 == SKYBOX_PORTAL || frontf->special1 == SKYBOX_LINKEDPORTAL)) return (frontf != backf);
|
if (!frontf->MergeAllowed()) return (frontf != backf);
|
||||||
if (backc != NULL && (backc->special1 == SKYBOX_PORTAL || backc->special1 == SKYBOX_LINKEDPORTAL)) return true;
|
if (!backc->MergeAllowed()) return true;
|
||||||
if (backf != NULL && (backf->special1 == SKYBOX_PORTAL || backf->special1 == SKYBOX_LINKEDPORTAL)) return true;
|
if (!backf->MergeAllowed()) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1046,7 +1046,7 @@ void R_Subsector (subsector_t *sub)
|
||||||
int ceilinglightlevel; // killough 4/11/98
|
int ceilinglightlevel; // killough 4/11/98
|
||||||
bool outersubsector;
|
bool outersubsector;
|
||||||
int fll, cll, position;
|
int fll, cll, position;
|
||||||
ASkyViewpoint *skybox;
|
FSectorPortal *portal;
|
||||||
|
|
||||||
// kg3D - fake floor stuff
|
// kg3D - fake floor stuff
|
||||||
visplane_t *backupfp;
|
visplane_t *backupfp;
|
||||||
|
@ -1114,12 +1114,11 @@ void R_Subsector (subsector_t *sub)
|
||||||
basecolormap = frontsector->ColorMap;
|
basecolormap = frontsector->ColorMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
skybox = frontsector->GetSkyBox(sector_t::ceiling);
|
portal = frontsector->ValidatePortal(sector_t::ceiling);
|
||||||
if (skybox != NULL && skybox->special1 >= SKYBOX_PLANE) skybox = NULL; // skip unsupported portal types
|
|
||||||
|
|
||||||
ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 ||
|
ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 ||
|
||||||
frontsector->GetTexture(sector_t::ceiling) == skyflatnum ||
|
frontsector->GetTexture(sector_t::ceiling) == skyflatnum ||
|
||||||
(skybox != NULL && skybox->bAlways) ||
|
portal != NULL ||
|
||||||
(frontsector->heightsec &&
|
(frontsector->heightsec &&
|
||||||
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||||
frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ?
|
frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ?
|
||||||
|
@ -1134,7 +1133,7 @@ void R_Subsector (subsector_t *sub)
|
||||||
frontsector->GetYScale(sector_t::ceiling),
|
frontsector->GetYScale(sector_t::ceiling),
|
||||||
frontsector->GetAngle(sector_t::ceiling),
|
frontsector->GetAngle(sector_t::ceiling),
|
||||||
frontsector->sky,
|
frontsector->sky,
|
||||||
skybox
|
portal
|
||||||
) : NULL;
|
) : NULL;
|
||||||
|
|
||||||
if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size())
|
if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size())
|
||||||
|
@ -1156,12 +1155,11 @@ void R_Subsector (subsector_t *sub)
|
||||||
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
|
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
|
||||||
// killough 3/16/98: add floorlightlevel
|
// killough 3/16/98: add floorlightlevel
|
||||||
// killough 10/98: add support for skies transferred from sidedefs
|
// killough 10/98: add support for skies transferred from sidedefs
|
||||||
skybox = frontsector->GetSkyBox(sector_t::floor);
|
portal = frontsector->ValidatePortal(sector_t::floor);
|
||||||
if (skybox != NULL && skybox->special1 >= SKYBOX_PLANE) skybox = NULL; // skip unsupported portal types
|
|
||||||
|
|
||||||
floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98
|
floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98
|
||||||
frontsector->GetTexture(sector_t::floor) == skyflatnum ||
|
frontsector->GetTexture(sector_t::floor) == skyflatnum ||
|
||||||
(skybox != NULL && skybox->bAlways) ||
|
portal != NULL ||
|
||||||
(frontsector->heightsec &&
|
(frontsector->heightsec &&
|
||||||
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||||
frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ?
|
frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ?
|
||||||
|
@ -1176,7 +1174,7 @@ void R_Subsector (subsector_t *sub)
|
||||||
frontsector->GetYScale(sector_t::floor),
|
frontsector->GetYScale(sector_t::floor),
|
||||||
frontsector->GetAngle(sector_t::floor),
|
frontsector->GetAngle(sector_t::floor),
|
||||||
frontsector->sky,
|
frontsector->sky,
|
||||||
skybox
|
portal
|
||||||
) : NULL;
|
) : NULL;
|
||||||
|
|
||||||
// kg3D - fake planes rendering
|
// kg3D - fake planes rendering
|
||||||
|
|
46
src/r_defs.h
46
src/r_defs.h
|
@ -58,19 +58,6 @@ enum
|
||||||
extern size_t MaxDrawSegs;
|
extern size_t MaxDrawSegs;
|
||||||
struct FDisplacement;
|
struct FDisplacement;
|
||||||
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
SKYBOX_ANCHOR = -1,
|
|
||||||
SKYBOX_SKYVIEWPOINT = 0, // a regular skybox
|
|
||||||
SKYBOX_STACKEDSECTORTHING, // stacked sectors with the thing method
|
|
||||||
SKYBOX_PORTAL, // stacked sectors with Sector_SetPortal
|
|
||||||
SKYBOX_LINKEDPORTAL, // linked portal (interactive)
|
|
||||||
SKYBOX_PLANE, // EE-style plane portal (not implemented in SW renderer)
|
|
||||||
SKYBOX_HORIZON, // EE-style horizon portal (not implemented in SW renderer)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// INTERNAL MAP TYPES
|
// INTERNAL MAP TYPES
|
||||||
// used by play and refresh
|
// used by play and refresh
|
||||||
|
@ -499,8 +486,6 @@ enum
|
||||||
SECF_UNDERWATERMASK = 32+64,
|
SECF_UNDERWATERMASK = 32+64,
|
||||||
SECF_DRAWN = 128, // sector has been drawn at least once
|
SECF_DRAWN = 128, // sector has been drawn at least once
|
||||||
SECF_HIDDEN = 256, // Do not draw on textured automap
|
SECF_HIDDEN = 256, // Do not draw on textured automap
|
||||||
SECF_NOFLOORSKYBOX = 512, // force use of regular sky
|
|
||||||
SECF_NOCEILINGSKYBOX = 1024, // force use of regular sky (do not separate from NOFLOORSKYBOX!!!)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -668,7 +653,7 @@ public:
|
||||||
|
|
||||||
DInterpolation *SetInterpolation(int position, bool attach);
|
DInterpolation *SetInterpolation(int position, bool attach);
|
||||||
|
|
||||||
ASkyViewpoint *GetSkyBox(int which);
|
FSectorPortal *ValidatePortal(int which);
|
||||||
void CheckPortalPlane(int plane);
|
void CheckPortalPlane(int plane);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -930,8 +915,7 @@ public:
|
||||||
|
|
||||||
bool PortalBlocksView(int plane)
|
bool PortalBlocksView(int plane)
|
||||||
{
|
{
|
||||||
if (SkyBoxes[plane] == NULL) return true;
|
if (GetPortalType(plane) != PORTS_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,28 +936,37 @@ public:
|
||||||
|
|
||||||
bool PortalIsLinked(int plane)
|
bool PortalIsLinked(int plane)
|
||||||
{
|
{
|
||||||
return (SkyBoxes[plane] != NULL && GetPortalType(plane) == SKYBOX_LINKEDPORTAL);
|
return (GetPortalType(plane) == PORTS_LINKEDPORTAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearPortal(int plane)
|
||||||
|
{
|
||||||
|
Portals[plane] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FSectorPortal *GetPortal(int plane)
|
||||||
|
{
|
||||||
|
return §orPortals[Portals[plane]];
|
||||||
}
|
}
|
||||||
|
|
||||||
// These intentionally do not validate the SkyBoxes pointers.
|
|
||||||
double GetPortalPlaneZ(int plane)
|
double GetPortalPlaneZ(int plane)
|
||||||
{
|
{
|
||||||
return SkyBoxes[plane]->specialf1;
|
return sectorPortals[Portals[plane]].mPlaneZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
DVector2 GetPortalDisplacement(int plane)
|
DVector2 GetPortalDisplacement(int plane)
|
||||||
{
|
{
|
||||||
return SkyBoxes[plane]->Scale;
|
return sectorPortals[Portals[plane]].mDisplacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetPortalType(int plane)
|
int GetPortalType(int plane)
|
||||||
{
|
{
|
||||||
return SkyBoxes[plane]->special1;
|
return sectorPortals[Portals[plane]].mType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetOppositePortalGroup(int plane)
|
int GetOppositePortalGroup(int plane)
|
||||||
{
|
{
|
||||||
return SkyBoxes[plane]->Sector->PortalGroup;
|
return sectorPortals[Portals[plane]].mDestination->PortalGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetTerrain(int pos) const;
|
int GetTerrain(int pos) const;
|
||||||
|
@ -1083,9 +1076,8 @@ public:
|
||||||
// occurs, SecActTarget's TriggerAction method is called.
|
// occurs, SecActTarget's TriggerAction method is called.
|
||||||
TObjPtr<ASectorAction> SecActTarget;
|
TObjPtr<ASectorAction> SecActTarget;
|
||||||
|
|
||||||
// [RH] The sky box to render for this sector. NULL means use a
|
// [RH] The portal or skybox to render for this sector.
|
||||||
// regular sky.
|
unsigned Portals[2];
|
||||||
TObjPtr<AActor> SkyBoxes[2];
|
|
||||||
int PortalGroup;
|
int PortalGroup;
|
||||||
|
|
||||||
int sectornum; // for comparing sector copies
|
int sectornum; // for comparing sector copies
|
||||||
|
|
|
@ -693,7 +693,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
||||||
fixed_t starty = viewy;
|
fixed_t starty = viewy;
|
||||||
fixed_t startz = viewz;
|
fixed_t startz = viewz;
|
||||||
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
|
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
|
||||||
int savedvisibility = camera->renderflags & RF_INVISIBLE;
|
int savedvisibility = camera? camera->renderflags & RF_INVISIBLE : 0;
|
||||||
|
|
||||||
CurrentPortalUniq++;
|
CurrentPortalUniq++;
|
||||||
|
|
||||||
|
@ -746,7 +746,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
||||||
viewz = FLOAT2FIXED(view.Z);
|
viewz = FLOAT2FIXED(view.Z);
|
||||||
viewangle = va.BAMs();
|
viewangle = va.BAMs();
|
||||||
|
|
||||||
if (!r_showviewer)
|
if (!r_showviewer && camera)
|
||||||
{
|
{
|
||||||
double distp = (ViewPath[0] - ViewPath[1]).Length();
|
double distp = (ViewPath[0] - ViewPath[1]).Length();
|
||||||
if (distp > EQUAL_EPSILON)
|
if (distp > EQUAL_EPSILON)
|
||||||
|
@ -802,11 +802,11 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
||||||
InSubsector = NULL;
|
InSubsector = NULL;
|
||||||
R_RenderBSPNode (nodes + numnodes - 1);
|
R_RenderBSPNode (nodes + numnodes - 1);
|
||||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||||
if (!savedvisibility) camera->renderflags &= ~RF_INVISIBLE;
|
if (!savedvisibility && camera) camera->renderflags &= ~RF_INVISIBLE;
|
||||||
|
|
||||||
PlaneCycles.Clock();
|
PlaneCycles.Clock();
|
||||||
R_DrawPlanes ();
|
R_DrawPlanes ();
|
||||||
R_DrawSkyBoxes ();
|
R_DrawPortals ();
|
||||||
PlaneCycles.Unclock();
|
PlaneCycles.Unclock();
|
||||||
|
|
||||||
fixed_t vzp = viewz;
|
fixed_t vzp = viewz;
|
||||||
|
@ -961,7 +961,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
||||||
{
|
{
|
||||||
PlaneCycles.Clock();
|
PlaneCycles.Clock();
|
||||||
R_DrawPlanes ();
|
R_DrawPlanes ();
|
||||||
R_DrawSkyBoxes ();
|
R_DrawPortals ();
|
||||||
PlaneCycles.Unclock();
|
PlaneCycles.Unclock();
|
||||||
|
|
||||||
// [RH] Walk through mirrors
|
// [RH] Walk through mirrors
|
||||||
|
|
|
@ -584,7 +584,7 @@ static visplane_t *new_visplane (unsigned hash)
|
||||||
visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightlevel, fixed_t alpha, bool additive,
|
visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightlevel, fixed_t alpha, bool additive,
|
||||||
fixed_t xoffs, fixed_t yoffs,
|
fixed_t xoffs, fixed_t yoffs,
|
||||||
fixed_t xscale, fixed_t yscale, angle_t angle,
|
fixed_t xscale, fixed_t yscale, angle_t angle,
|
||||||
int sky, ASkyViewpoint *skybox)
|
int sky, FSectorPortal *portal)
|
||||||
{
|
{
|
||||||
secplane_t plane;
|
secplane_t plane;
|
||||||
visplane_t *check;
|
visplane_t *check;
|
||||||
|
@ -606,9 +606,9 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
// same column but separated by a wall. If they both try to reside in the
|
// same column but separated by a wall. If they both try to reside in the
|
||||||
// same visplane, then only the floor sky will be drawn.
|
// same visplane, then only the floor sky will be drawn.
|
||||||
plane.set(0., 0., height.fC(), 0.);
|
plane.set(0., 0., height.fC(), 0.);
|
||||||
isskybox = skybox != NULL && !skybox->bInSkybox;
|
isskybox = portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX);
|
||||||
}
|
}
|
||||||
else if (skybox != NULL && skybox->bAlways && !skybox->bInSkybox)
|
else if (portal != NULL && !(portal->mFlags & PORTSF_INSKYBOX))
|
||||||
{
|
{
|
||||||
plane = height;
|
plane = height;
|
||||||
isskybox = true;
|
isskybox = true;
|
||||||
|
@ -622,7 +622,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
// and ->alpha is for stacked sectors
|
// and ->alpha is for stacked sectors
|
||||||
if (fake3D & (FAKE3D_FAKEFLOOR|FAKE3D_FAKECEILING)) sky = 0x80000000 | fakeAlpha;
|
if (fake3D & (FAKE3D_FAKEFLOOR|FAKE3D_FAKECEILING)) sky = 0x80000000 | fakeAlpha;
|
||||||
else sky = 0; // not skyflatnum so it can't be a sky
|
else sky = 0; // not skyflatnum so it can't be a sky
|
||||||
skybox = NULL;
|
portal = NULL;
|
||||||
alpha = OPAQUE;
|
alpha = OPAQUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,9 +633,9 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
{
|
{
|
||||||
if (isskybox)
|
if (isskybox)
|
||||||
{
|
{
|
||||||
if (skybox == check->skybox && plane == check->height)
|
if (portal == check->portal && plane == check->height)
|
||||||
{
|
{
|
||||||
if (skybox->Mate != NULL)
|
if (portal->mType != PORTS_SKYVIEWPOINT)
|
||||||
{ // This skybox is really a stacked sector, so we need to
|
{ // This skybox is really a stacked sector, so we need to
|
||||||
// check even more.
|
// check even more.
|
||||||
if (check->extralight == stacked_extralight &&
|
if (check->extralight == stacked_extralight &&
|
||||||
|
@ -645,7 +645,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
check->viewz == stacked_viewz &&
|
check->viewz == stacked_viewz &&
|
||||||
(
|
(
|
||||||
// headache inducing logic... :(
|
// headache inducing logic... :(
|
||||||
(!(skybox->flags & MF_JUSTATTACKED)) ||
|
(portal->mType != PORTS_STACKEDSECTORTHING) ||
|
||||||
(
|
(
|
||||||
check->Alpha == alpha &&
|
check->Alpha == alpha &&
|
||||||
check->Additive == additive &&
|
check->Additive == additive &&
|
||||||
|
@ -710,7 +710,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
||||||
check->angle = angle;
|
check->angle = angle;
|
||||||
check->colormap = basecolormap; // [RH] Save colormap
|
check->colormap = basecolormap; // [RH] Save colormap
|
||||||
check->sky = sky;
|
check->sky = sky;
|
||||||
check->skybox = skybox;
|
check->portal = portal;
|
||||||
check->left = viewwidth; // Was SCREENWIDTH -- killough 11/98
|
check->left = viewwidth; // Was SCREENWIDTH -- killough 11/98
|
||||||
check->right = 0;
|
check->right = 0;
|
||||||
check->extralight = stacked_extralight;
|
check->extralight = stacked_extralight;
|
||||||
|
@ -781,7 +781,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
||||||
// make a new visplane
|
// make a new visplane
|
||||||
unsigned hash;
|
unsigned hash;
|
||||||
|
|
||||||
if (pl->skybox != NULL && !pl->skybox->bInSkybox && (pl->picnum == skyflatnum || pl->skybox->bAlways) && viewactive)
|
if (pl->portal != NULL && !(pl->portal->mFlags & PORTSF_INSKYBOX) && viewactive)
|
||||||
{
|
{
|
||||||
hash = MAXVISPLANES;
|
hash = MAXVISPLANES;
|
||||||
}
|
}
|
||||||
|
@ -800,7 +800,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
||||||
new_pl->yscale = pl->yscale;
|
new_pl->yscale = pl->yscale;
|
||||||
new_pl->angle = pl->angle;
|
new_pl->angle = pl->angle;
|
||||||
new_pl->colormap = pl->colormap;
|
new_pl->colormap = pl->colormap;
|
||||||
new_pl->skybox = pl->skybox;
|
new_pl->portal = pl->portal;
|
||||||
new_pl->extralight = pl->extralight;
|
new_pl->extralight = pl->extralight;
|
||||||
new_pl->visibility = pl->visibility;
|
new_pl->visibility = pl->visibility;
|
||||||
new_pl->viewx = pl->viewx;
|
new_pl->viewx = pl->viewx;
|
||||||
|
@ -1160,7 +1160,7 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// R_DrawSkyBoxes
|
// R_DrawPortals
|
||||||
//
|
//
|
||||||
// Draws any recorded sky boxes and then frees them.
|
// Draws any recorded sky boxes and then frees them.
|
||||||
//
|
//
|
||||||
|
@ -1181,7 +1181,7 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
||||||
CVAR (Bool, r_skyboxes, true, 0)
|
CVAR (Bool, r_skyboxes, true, 0)
|
||||||
static int numskyboxes;
|
static int numskyboxes;
|
||||||
|
|
||||||
void R_DrawSkyBoxes ()
|
void R_DrawPortals ()
|
||||||
{
|
{
|
||||||
static TArray<size_t> interestingStack;
|
static TArray<size_t> interestingStack;
|
||||||
static TArray<ptrdiff_t> drawsegStack;
|
static TArray<ptrdiff_t> drawsegStack;
|
||||||
|
@ -1221,7 +1221,7 @@ void R_DrawSkyBoxes ()
|
||||||
visplanes[MAXVISPLANES] = pl->next;
|
visplanes[MAXVISPLANES] = pl->next;
|
||||||
pl->next = NULL;
|
pl->next = NULL;
|
||||||
|
|
||||||
if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES)
|
if (pl->right < pl->left || !r_skyboxes || numskyboxes == MAX_SKYBOX_PLANES || pl->portal == NULL)
|
||||||
{
|
{
|
||||||
R_DrawSinglePlane (pl, OPAQUE, false, false);
|
R_DrawSinglePlane (pl, OPAQUE, false, false);
|
||||||
*freehead = pl;
|
*freehead = pl;
|
||||||
|
@ -1231,14 +1231,15 @@ void R_DrawSkyBoxes ()
|
||||||
|
|
||||||
numskyboxes++;
|
numskyboxes++;
|
||||||
|
|
||||||
ASkyViewpoint *sky = pl->skybox;
|
FSectorPortal *port = pl->portal;
|
||||||
ASkyViewpoint *mate = sky->Mate;
|
switch (port->mType)
|
||||||
|
{
|
||||||
if (mate == NULL)
|
case PORTS_SKYVIEWPOINT:
|
||||||
{
|
{
|
||||||
// Don't let gun flashes brighten the sky box
|
// Don't let gun flashes brighten the sky box
|
||||||
|
ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox);
|
||||||
extralight = 0;
|
extralight = 0;
|
||||||
R_SetVisibility (sky->args[0] * 0.25f);
|
R_SetVisibility(sky->args[0] * 0.25f);
|
||||||
|
|
||||||
DVector3 viewpos = sky->InterpolatedPosition(r_TicFracF);
|
DVector3 viewpos = sky->InterpolatedPosition(r_TicFracF);
|
||||||
viewx = FLOAT2FIXED(viewpos.X);
|
viewx = FLOAT2FIXED(viewpos.X);
|
||||||
|
@ -1247,23 +1248,40 @@ void R_DrawSkyBoxes ()
|
||||||
viewangle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF).BAMs();
|
viewangle = savedangle + (sky->PrevAngles.Yaw + deltaangle(sky->PrevAngles.Yaw, sky->Angles.Yaw) * r_TicFracF).BAMs();
|
||||||
|
|
||||||
R_CopyStackedViewParameters();
|
R_CopyStackedViewParameters();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
case PORTS_STACKEDSECTORTHING:
|
||||||
|
case PORTS_PORTAL:
|
||||||
|
case PORTS_LINKEDPORTAL:
|
||||||
extralight = pl->extralight;
|
extralight = pl->extralight;
|
||||||
R_SetVisibility (pl->visibility);
|
R_SetVisibility (pl->visibility);
|
||||||
viewx = pl->viewx + FLOAT2FIXED(-sky->Mate->X() + sky->X());
|
viewx = pl->viewx + FLOAT2FIXED(port->mDisplacement.X);
|
||||||
viewy = pl->viewy + FLOAT2FIXED(-sky->Mate->Y() + sky->Y());
|
viewy = pl->viewy + FLOAT2FIXED(port->mDisplacement.Y);
|
||||||
viewz = pl->viewz;
|
viewz = pl->viewz;
|
||||||
viewangle = pl->viewangle;
|
viewangle = pl->viewangle;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PORTS_HORIZON:
|
||||||
|
case PORTS_PLANE:
|
||||||
|
// not implemented yet
|
||||||
|
|
||||||
|
default:
|
||||||
|
R_DrawSinglePlane(pl, OPAQUE, false, false);
|
||||||
|
*freehead = pl;
|
||||||
|
freehead = &pl->next;
|
||||||
|
numskyboxes--;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewAngle = AngleToFloat(viewangle);
|
ViewAngle = AngleToFloat(viewangle);
|
||||||
ViewPos = { FIXED2DBL(viewx), FIXED2DBL(viewy), FIXED2DBL(viewz) };
|
ViewPos = { FIXED2DBL(viewx), FIXED2DBL(viewy), FIXED2DBL(viewz) };
|
||||||
|
|
||||||
sky->bInSkybox = true;
|
port->mFlags |= PORTSF_INSKYBOX;
|
||||||
if (mate != NULL) mate->bInSkybox = true;
|
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX;
|
||||||
camera = sky;
|
camera = NULL;
|
||||||
viewsector = sky->Sector;
|
viewsector = port->mDestination;
|
||||||
|
assert(viewsector != NULL);
|
||||||
R_SetViewAngle ();
|
R_SetViewAngle ();
|
||||||
validcount++; // Make sure we see all sprites
|
validcount++; // Make sure we see all sprites
|
||||||
|
|
||||||
|
@ -1324,8 +1342,8 @@ void R_DrawSkyBoxes ()
|
||||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||||
R_DrawPlanes ();
|
R_DrawPlanes ();
|
||||||
|
|
||||||
sky->bInSkybox = false;
|
port->mFlags &= ~PORTSF_INSKYBOX;
|
||||||
if (mate != NULL) mate->bInSkybox = false;
|
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw all the masked textures in a second pass, in the reverse order they
|
// Draw all the masked textures in a second pass, in the reverse order they
|
||||||
|
|
|
@ -43,7 +43,7 @@ struct visplane_s
|
||||||
fixed_t xscale, yscale; // [RH] Support flat scaling
|
fixed_t xscale, yscale; // [RH] Support flat scaling
|
||||||
angle_t angle; // [RH] Support flat rotation
|
angle_t angle; // [RH] Support flat rotation
|
||||||
int sky;
|
int sky;
|
||||||
ASkyViewpoint *skybox; // [RH] Support sky boxes
|
FSectorPortal *portal; // [RH] Support sky boxes
|
||||||
|
|
||||||
// [RH] This set of variables copies information from the time when the
|
// [RH] This set of variables copies information from the time when the
|
||||||
// visplane is created. They are only used by stacks so that you can
|
// visplane is created. They are only used by stacks so that you can
|
||||||
|
@ -88,7 +88,7 @@ void R_DeinitPlanes ();
|
||||||
void R_ClearPlanes (bool fullclear);
|
void R_ClearPlanes (bool fullclear);
|
||||||
|
|
||||||
int R_DrawPlanes ();
|
int R_DrawPlanes ();
|
||||||
void R_DrawSkyBoxes ();
|
void R_DrawPortals ();
|
||||||
void R_DrawSkyPlane (visplane_t *pl);
|
void R_DrawSkyPlane (visplane_t *pl);
|
||||||
void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
||||||
void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool masked);
|
||||||
|
@ -106,7 +106,7 @@ visplane_t *R_FindPlane
|
||||||
fixed_t yscale,
|
fixed_t yscale,
|
||||||
angle_t angle,
|
angle_t angle,
|
||||||
int sky,
|
int sky,
|
||||||
ASkyViewpoint *skybox);
|
FSectorPortal *portal);
|
||||||
|
|
||||||
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop);
|
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop);
|
||||||
|
|
||||||
|
|
|
@ -1536,6 +1536,7 @@ void R_DrawPlayerSprites ()
|
||||||
F3DFloor *rover;
|
F3DFloor *rover;
|
||||||
|
|
||||||
if (!r_drawplayersprites ||
|
if (!r_drawplayersprites ||
|
||||||
|
!camera ||
|
||||||
!camera->player ||
|
!camera->player ||
|
||||||
(players[consoleplayer].cheats & CF_CHASECAM) ||
|
(players[consoleplayer].cheats & CF_CHASECAM) ||
|
||||||
(r_deathcamera && camera->health <= 0))
|
(r_deathcamera && camera->health <= 0))
|
||||||
|
|
|
@ -72,11 +72,11 @@ const char *GetVersionString();
|
||||||
// SAVESIG should match SAVEVER.
|
// SAVESIG should match SAVEVER.
|
||||||
|
|
||||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||||
#define MINSAVEVER 4536
|
#define MINSAVEVER 4539
|
||||||
|
|
||||||
// Use 4500 as the base git save version, since it's higher than the
|
// Use 4500 as the base git save version, since it's higher than the
|
||||||
// SVN revision ever got.
|
// SVN revision ever got.
|
||||||
#define SAVEVER 4538
|
#define SAVEVER 4539
|
||||||
|
|
||||||
#define SAVEVERSTRINGIFY2(x) #x
|
#define SAVEVERSTRINGIFY2(x) #x
|
||||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||||
|
|
|
@ -39,13 +39,13 @@ enum
|
||||||
282 = 0, Sector_Attach3DMidtex(tag, 0, 1) // "3DMidTex_MoveWithCeiling"
|
282 = 0, Sector_Attach3DMidtex(tag, 0, 1) // "3DMidTex_MoveWithCeiling"
|
||||||
|
|
||||||
// Plane portals are not supported in ZDoom, though they probably wouldn't be too hard to implement.
|
// Plane portals are not supported in ZDoom, though they probably wouldn't be too hard to implement.
|
||||||
283 = 0, Unsupported() // "Portal_PlaneCeiling"
|
283 = 0, Sector_SetPortal(tag,3, 1, 0, 0) // "Portal_PlaneCeiling"
|
||||||
284 = 0, Unsupported() // "Portal_PlaneFloor"
|
284 = 0, Sector_SetPortal(tag,3, 0, 0, 0) // "Portal_PlaneFloor"
|
||||||
285 = 0, Unsupported() // "Portal_PlaneFloorCeiling"
|
285 = 0, Sector_SetPortal(tag,3, 2, 0, 0) // "Portal_PlaneFloorCeiling"
|
||||||
286 = 0, Unsupported() // "Portal_HorizonCeiling"
|
286 = 0, Sector_SetPortal(tag,4, 1, 0, 0) // "Portal_HorizonCeiling"
|
||||||
287 = 0, Unsupported() // "Portal_HorizonFloor"
|
287 = 0, Sector_SetPortal(tag,4, 0, 0, 0) // "Portal_HorizonFloor"
|
||||||
288 = 0, Unsupported() // "Portal_HorizonFloorCeiling"
|
288 = 0, Sector_SetPortal(tag,4, 2, 0, 0) // "Portal_HorizonFloorCeiling"
|
||||||
289 = 0, Unsupported() // "Portal_LineTransfer"
|
289 = 0, Sector_SetPortal(0, 5, 0, tag) // "Portal_LineTransfer"
|
||||||
|
|
||||||
// Skybox portals
|
// Skybox portals
|
||||||
290 = 0, Sector_SetPortal(tag, 2, 1, 1, 0) // "Portal_SkyboxCeiling"
|
290 = 0, Sector_SetPortal(tag, 2, 1, 1, 0) // "Portal_SkyboxCeiling"
|
||||||
|
|
Loading…
Reference in a new issue