mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-24 04:51:41 +00:00
Merge branch 'master' of https://github.com/rheit/zdoom
# Conflicts: # src/p_spec.cpp # src/r_bsp.cpp # src/r_defs.h
This commit is contained in:
commit
9c6e7753d8
29 changed files with 435 additions and 316 deletions
|
@ -576,7 +576,6 @@ public:
|
|||
~AActor ();
|
||||
|
||||
void Serialize (FArchive &arc);
|
||||
void PostSerialize();
|
||||
|
||||
static AActor *StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing = false);
|
||||
|
||||
|
|
|
@ -384,6 +384,15 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *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.
|
||||
if (sectors != NULL)
|
||||
{
|
||||
|
@ -392,8 +401,6 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld)
|
|||
#define SECTOR_CHECK(f,t) \
|
||||
if (sectors[i].f.p == static_cast<t *>(old)) { sectors[i].f = static_cast<t *>(notOld); changed++; }
|
||||
SECTOR_CHECK( SoundTarget, AActor );
|
||||
SECTOR_CHECK( SkyBoxes[sector_t::ceiling], ASkyViewpoint );
|
||||
SECTOR_CHECK( SkyBoxes[sector_t::floor], ASkyViewpoint );
|
||||
SECTOR_CHECK( SecActTarget, ASectorAction );
|
||||
SECTOR_CHECK( floordata, DSectorEffect );
|
||||
SECTOR_CHECK( ceilingdata, DSectorEffect );
|
||||
|
|
|
@ -327,7 +327,10 @@ static void MarkRoot()
|
|||
DThinker::MarkRoots();
|
||||
FCanvasTextureInfo::Mark();
|
||||
Mark(DACSThinker::ActiveThinker);
|
||||
Mark(level.DefaultSkybox);
|
||||
for (auto &s : sectorPortals)
|
||||
{
|
||||
Mark(s.mSkybox);
|
||||
}
|
||||
// Mark dead bodies.
|
||||
for (i = 0; i < BODYQUESIZE; ++i)
|
||||
{
|
||||
|
@ -680,8 +683,6 @@ size_t DSectorMarker::PropagateMark()
|
|||
{
|
||||
sector_t *sec = §ors[SecNum + i];
|
||||
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->floordata);
|
||||
GC::Mark(sec->ceilingdata);
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
virtual ~DThinker ();
|
||||
virtual void Tick ();
|
||||
virtual void PostBeginPlay (); // Called just before the first tick
|
||||
virtual void PostSerialize() {}
|
||||
size_t PropagateMark();
|
||||
|
||||
void ChangeStatNum (int statnum);
|
||||
|
|
|
@ -298,6 +298,7 @@ template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node);
|
|||
template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw);
|
||||
template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da);
|
||||
FArchive &operator<< (FArchive &arc, FLinePortal &da);
|
||||
FArchive &operator<< (FArchive &arc, FSectorPortal &da);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1386,7 +1386,6 @@ void G_InitLevelLocals ()
|
|||
NormalLight.ChangeFade (level.fadeto);
|
||||
|
||||
level.DefaultEnvironment = info->DefaultEnvironment;
|
||||
level.DefaultSkybox = NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -1534,13 +1533,14 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
|
|||
|
||||
FBehavior::StaticSerializeModuleStates (arc);
|
||||
if (arc.IsLoading()) interpolator.ClearInterpolations();
|
||||
P_SerializeWorld(arc);
|
||||
P_SerializeThinkers (arc, hubLoad);
|
||||
P_SerializeWorld (arc);
|
||||
P_SerializeWorldActors(arc); // serializing actor pointers in the world data must be done after SerializeWorld has restored the entire sector state, otherwise LinkToWorld may fail.
|
||||
P_SerializePolyobjs (arc);
|
||||
P_SerializeSubsectors(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?
|
||||
FRemapTable *trans;
|
||||
|
@ -1582,13 +1582,6 @@ void G_SerializeLevel (FArchive &arc, bool hubLoad)
|
|||
P_SerializeSounds (arc);
|
||||
if (arc.IsLoading())
|
||||
{
|
||||
FThinkerIterator it(RUNTIME_CLASS(DThinker));
|
||||
DThinker *th;
|
||||
while ((th = it.Next()))
|
||||
{
|
||||
th->PostSerialize();
|
||||
}
|
||||
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
P_Recalculate3DFloors(§ors[i]);
|
||||
|
|
|
@ -435,8 +435,6 @@ struct FLevelLocals
|
|||
int airsupply;
|
||||
int DefaultEnvironment; // Default sound environment.
|
||||
|
||||
TObjPtr<class ASkyViewpoint> DefaultSkybox;
|
||||
|
||||
FSectorScrollValues *Scrolls; // NULL if no DScrollers in this level
|
||||
|
||||
SBYTE WallVertLight; // Light diffs for vert/horiz walls
|
||||
|
|
|
@ -91,14 +91,9 @@ public:
|
|||
class ASkyViewpoint : public AActor
|
||||
{
|
||||
DECLARE_CLASS (ASkyViewpoint, AActor)
|
||||
HAS_OBJECT_POINTERS
|
||||
public:
|
||||
void Serialize (FArchive &arc);
|
||||
void BeginPlay ();
|
||||
void Destroy ();
|
||||
bool bInSkybox;
|
||||
bool bAlways;
|
||||
TObjPtr<ASkyViewpoint> Mate;
|
||||
};
|
||||
|
||||
// For an EE compatible linedef based definition.
|
||||
|
|
|
@ -38,49 +38,42 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "farchive.h"
|
||||
#include "r_sky.h"
|
||||
#include "portal.h"
|
||||
|
||||
// arg0 = Visibility*4 for this skybox
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (ASkyViewpoint)
|
||||
DECLARE_POINTER(Mate)
|
||||
END_POINTERS
|
||||
IMPLEMENT_CLASS (ASkyViewpoint)
|
||||
|
||||
// If this actor has no TID, make it the default sky box
|
||||
void ASkyViewpoint::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 ()
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
sectors[i].SkyBoxes[sector_t::floor] = NULL;
|
||||
}
|
||||
if (sectors[i].SkyBoxes[sector_t::ceiling] == this)
|
||||
{
|
||||
sectors[i].SkyBoxes[sector_t::ceiling] = NULL;
|
||||
}
|
||||
if (sectors[i].GetPortal(sector_t::floor)->mSkybox == this)
|
||||
sectors[i].ClearPortal(sector_t::floor);
|
||||
if (sectors[i].GetPortal(sector_t::ceiling)->mSkybox == this)
|
||||
sectors[i].ClearPortal(sector_t::ceiling);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -90,10 +83,8 @@ void ASkyCamCompat::BeginPlay()
|
|||
{
|
||||
// Do not call the SkyViewpoint's super method because it would trash our setup
|
||||
AActor::BeginPlay();
|
||||
special1 = SKYBOX_SKYVIEWPOINT;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// arg0 = tid of matching SkyViewpoint
|
||||
|
@ -130,20 +121,18 @@ void ASkyPicker::PostBeginPlay ()
|
|||
|
||||
if (box == NULL && args[0] != 0)
|
||||
{
|
||||
Printf ("Can't find SkyViewpoint %d for sector %td\n",
|
||||
args[0], Sector - sectors);
|
||||
Printf ("Can't find SkyViewpoint %d for sector %td\n", args[0], Sector - sectors);
|
||||
}
|
||||
else
|
||||
{
|
||||
int boxindex = P_GetSkyboxPortal(box);
|
||||
if (0 == (args[1] & 2))
|
||||
{
|
||||
Sector->SkyBoxes[sector_t::ceiling] = box;
|
||||
if (box == NULL) Sector->MoreFlags |= SECF_NOCEILINGSKYBOX; // sector should ignore the level's default skybox
|
||||
Sector->Portals[sector_t::ceiling] = boxindex;
|
||||
}
|
||||
if (0 == (args[1] & 1))
|
||||
{
|
||||
Sector->SkyBoxes[sector_t::floor] = box;
|
||||
if (box == NULL) Sector->MoreFlags |= SECF_NOFLOORSKYBOX; // sector should ignore the level's default skybox
|
||||
Sector->Portals[sector_t::floor] = boxindex;
|
||||
}
|
||||
}
|
||||
Destroy ();
|
||||
|
@ -160,9 +149,6 @@ void AStackPoint::BeginPlay ()
|
|||
{
|
||||
// Skip SkyViewpoint's initialization
|
||||
AActor::BeginPlay ();
|
||||
|
||||
bAlways = true;
|
||||
special1 = SKYBOX_STACKEDSECTORTHING;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -358,7 +358,7 @@ void P_PlayerOnSpecial3DFloor(player_t* player)
|
|||
// Checks whether the player's feet touch a solid 3D floor in the sector
|
||||
//
|
||||
//==========================================================================
|
||||
bool P_CheckFor3DFloorHit(AActor * mo)
|
||||
bool P_CheckFor3DFloorHit(AActor * mo, double z)
|
||||
{
|
||||
if ((mo->player && (mo->player->cheats & CF_PREDICTING))) return false;
|
||||
|
||||
|
@ -368,7 +368,7 @@ bool P_CheckFor3DFloorHit(AActor * mo)
|
|||
|
||||
if(rover->flags & FF_SOLID && rover->model->SecActTarget)
|
||||
{
|
||||
if(mo->Z() == rover->top.plane->ZatPoint(mo))
|
||||
if (fabs(z - rover->top.plane->ZatPoint(mo)) < EQUAL_EPSILON)
|
||||
{
|
||||
rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor);
|
||||
return true;
|
||||
|
@ -384,7 +384,7 @@ bool P_CheckFor3DFloorHit(AActor * mo)
|
|||
// Checks whether the player's head touches a solid 3D floor in the sector
|
||||
//
|
||||
//==========================================================================
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo)
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo, double z)
|
||||
{
|
||||
if ((mo->player && (mo->player->cheats & CF_PREDICTING))) return false;
|
||||
|
||||
|
@ -394,7 +394,7 @@ bool P_CheckFor3DCeilingHit(AActor * mo)
|
|||
|
||||
if(rover->flags & FF_SOLID && rover->model->SecActTarget)
|
||||
{
|
||||
if(mo->Top() == rover->bottom.plane->ZatPoint(mo))
|
||||
if(fabs(z - rover->bottom.plane->ZatPoint(mo)) < EQUAL_EPSILON)
|
||||
{
|
||||
rover->model->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling);
|
||||
return true;
|
||||
|
|
|
@ -122,8 +122,8 @@ struct lightlist_t
|
|||
class player_s;
|
||||
void P_PlayerOnSpecial3DFloor(player_t* player);
|
||||
|
||||
bool P_CheckFor3DFloorHit(AActor * mo);
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo);
|
||||
bool P_CheckFor3DFloorHit(AActor * mo, double z);
|
||||
bool P_CheckFor3DCeilingHit(AActor * mo, double z);
|
||||
void P_Recalculate3DFloors(sector_t *);
|
||||
void P_RecalculateAttached3DFloors(sector_t * sec);
|
||||
void P_RecalculateLights(sector_t *sector);
|
||||
|
|
|
@ -587,7 +587,7 @@ bool P_Move (AActor *actor)
|
|||
{
|
||||
actor->floorsector->SecActTarget->TriggerAction(actor, SECSPAC_HitFloor);
|
||||
}
|
||||
P_CheckFor3DFloorHit(actor);
|
||||
P_CheckFor3DFloorHit(actor, actor->Z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1629,10 +1629,10 @@ int FPathTraverse::PortalRelocate(intercept_t *in, int flags, DVector3 *optpos)
|
|||
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 hity = trace.y + portalthing->Scale.Y;
|
||||
double hitx = trace.x + displacement.X;
|
||||
double hity = trace.y + displacement.Y;
|
||||
double endx = hitx + trace.dx;
|
||||
double endy = hity + trace.dy;
|
||||
intercepts.Resize(intercept_index);
|
||||
|
|
|
@ -373,7 +373,7 @@ public:
|
|||
}
|
||||
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);
|
||||
void PortalRelocate(AActor *portalthing, int flags, double hitfrac);
|
||||
void PortalRelocate(const DVector2 &disp, int flags, double hitfrac);
|
||||
virtual ~FPathTraverse();
|
||||
const divline_t &Trace() const { return trace; }
|
||||
|
||||
|
|
|
@ -397,6 +397,9 @@ void AActor::Serialize(FArchive &arc)
|
|||
|
||||
if (arc.IsLoading ())
|
||||
{
|
||||
touching_sectorlist = NULL;
|
||||
LinkToWorld(false, Sector);
|
||||
|
||||
AddToHash ();
|
||||
SetShade (fillcolor);
|
||||
if (player)
|
||||
|
@ -413,17 +416,11 @@ void AActor::Serialize(FArchive &arc)
|
|||
Speed = GetDefault()->Speed;
|
||||
}
|
||||
}
|
||||
ClearInterpolation();
|
||||
UpdateWaterLevel(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AActor::PostSerialize()
|
||||
{
|
||||
touching_sectorlist = NULL;
|
||||
LinkToWorld(false, Sector);
|
||||
ClearInterpolation();
|
||||
UpdateWaterLevel(false);
|
||||
}
|
||||
|
||||
AActor::AActor () throw()
|
||||
{
|
||||
}
|
||||
|
@ -2399,7 +2396,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
{ // [RH] Let the sector do something to the actor
|
||||
mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitFloor);
|
||||
}
|
||||
P_CheckFor3DFloorHit(mo);
|
||||
P_CheckFor3DFloorHit(mo, mo->floorz);
|
||||
// [RH] Need to recheck this because the sector action might have
|
||||
// teleported the actor so it is no longer below the floor.
|
||||
if (mo->Z() <= mo->floorz)
|
||||
|
@ -2499,7 +2496,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
{ // [RH] Let the sector do something to the actor
|
||||
mo->Sector->SecActTarget->TriggerAction (mo, SECSPAC_HitCeiling);
|
||||
}
|
||||
P_CheckFor3DCeilingHit(mo);
|
||||
P_CheckFor3DCeilingHit(mo, mo->ceilingz);
|
||||
// [RH] Need to recheck this because the sector action might have
|
||||
// teleported the actor so it is no longer above the ceiling.
|
||||
if (mo->Top() > mo->ceilingz)
|
||||
|
@ -3861,11 +3858,11 @@ void AActor::CheckSectorTransition(sector_t *oldsec)
|
|||
}
|
||||
if (Z() == floorz)
|
||||
{
|
||||
P_CheckFor3DFloorHit(this);
|
||||
P_CheckFor3DFloorHit(this, Z());
|
||||
}
|
||||
if (Top() == ceilingz)
|
||||
{
|
||||
P_CheckFor3DCeilingHit(this);
|
||||
P_CheckFor3DCeilingHit(this, Top());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -363,13 +363,11 @@ void P_SerializeWorld (FArchive &arc)
|
|||
arc << sec->damageamount;
|
||||
arc << sec->damageinterval
|
||||
<< sec->leakydamage
|
||||
<< sec->damagetype;
|
||||
arc << sec->SoundTarget
|
||||
<< sec->SecActTarget
|
||||
<< sec->damagetype
|
||||
<< sec->sky
|
||||
<< sec->MoreFlags
|
||||
<< sec->Flags
|
||||
<< sec->SkyBoxes[sector_t::floor] << sec->SkyBoxes[sector_t::ceiling]
|
||||
<< sec->Portals[sector_t::floor] << sec->Portals[sector_t::ceiling]
|
||||
<< sec->ZoneNumber;
|
||||
arc << sec->interpolations[0]
|
||||
<< sec->interpolations[1]
|
||||
|
@ -454,10 +452,26 @@ void P_SerializeWorld (FArchive &arc)
|
|||
arc << zn->Environment;
|
||||
}
|
||||
|
||||
arc << linePortals;
|
||||
arc << linePortals << sectorPortals;
|
||||
P_CollectLinkedPortals();
|
||||
}
|
||||
|
||||
void P_SerializeWorldActors(FArchive &arc)
|
||||
{
|
||||
int i, j;
|
||||
sector_t *sec;
|
||||
|
||||
for (i = 0, sec = sectors; i < numsectors; i++, sec++)
|
||||
{
|
||||
arc << sec->SoundTarget
|
||||
<< sec->SecActTarget;
|
||||
}
|
||||
for (auto &s : sectorPortals)
|
||||
{
|
||||
arc << s.mSkybox;
|
||||
}
|
||||
}
|
||||
|
||||
void extsector_t::Serialize(FArchive &arc)
|
||||
{
|
||||
arc << FakeFloor.Sectors
|
||||
|
@ -570,22 +584,8 @@ void P_SerializePolyobjs (FArchive &arc)
|
|||
I_Error ("UnarchivePolyobjs: Invalid polyobj tag");
|
||||
}
|
||||
arc << angle << delta << po->interpolation;
|
||||
if (SaveVersion >= 4537)
|
||||
{
|
||||
arc << po->bBlocked;
|
||||
}
|
||||
else
|
||||
{
|
||||
po->bBlocked = false;
|
||||
}
|
||||
if (SaveVersion >= 4538)
|
||||
{
|
||||
arc << po->bHasPortals;
|
||||
}
|
||||
else
|
||||
{
|
||||
po->bHasPortals = 0;
|
||||
}
|
||||
arc << po->bBlocked;
|
||||
arc << po->bHasPortals;
|
||||
|
||||
po->RotatePolyobj (angle, true);
|
||||
delta -= po->StartSpot.pos;
|
||||
|
|
|
@ -41,6 +41,7 @@ struct PNGHandle;
|
|||
// These are the load / save game routines.
|
||||
// Also see farchive.(h|cpp)
|
||||
void P_SerializePlayers (FArchive &arc, bool fakeload);
|
||||
void P_SerializeWorldActors(FArchive &arc);
|
||||
void P_SerializeWorld (FArchive &arc);
|
||||
void P_SerializeThinkers (FArchive &arc, bool);
|
||||
void P_SerializePolyobjs (FArchive &arc);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "r_utility.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "p_local.h"
|
||||
#include "r_sky.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]);
|
||||
if (MoreFlags & (SECF_NOFLOORSKYBOX << which)) return NULL;
|
||||
return level.DefaultSkybox;
|
||||
FSectorPortal *port = GetPortal(which);
|
||||
if (port->mType == PORTS_SKYVIEWPOINT && port->mSkybox == nullptr) return nullptr; // A skybox without a viewpoint is just a regular sky.
|
||||
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)
|
||||
{
|
||||
AActor *portal = SkyBoxes[plane];
|
||||
if (!portal || portal->special1 != SKYBOX_LINKEDPORTAL) return;
|
||||
|
||||
double planeh = GetPlaneTexZF(plane);
|
||||
int obstructed = PLANEF_OBSTRUCTED * (plane == sector_t::floor ?
|
||||
planeh > portal->specialf1 : planeh < portal->specialf1);
|
||||
planes[plane].Flags = (planes[plane].Flags & ~PLANEF_OBSTRUCTED) | obstructed;
|
||||
if (GetPortalType(plane) == PORTS_LINKEDPORTAL)
|
||||
{
|
||||
double portalh = GetPortalPlaneZ(plane);
|
||||
double planeh = GetPlaneTexZF(plane);
|
||||
int obstructed = PLANEF_OBSTRUCTED * (plane == sector_t::floor ? planeh > portalh : planeh < portalh);
|
||||
planes[plane].Flags = (planes[plane].Flags & ~PLANEF_OBSTRUCTED) | obstructed;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
107
src/p_spec.cpp
107
src/p_spec.cpp
|
@ -838,12 +838,13 @@ static void SetupFloorPortal (AStackPoint *point)
|
|||
NActorIterator it (NAME_LowerStackLookOnly, point->tid);
|
||||
sector_t *Sector = point->Sector;
|
||||
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
||||
Sector->SkyBoxes[sector_t::floor] = skyv;
|
||||
if (skyv != NULL && skyv->bAlways)
|
||||
if (skyv != NULL)
|
||||
{
|
||||
skyv->Mate = point;
|
||||
skyv->target = point;
|
||||
if (Sector->GetAlphaF(sector_t::floor) == 1.)
|
||||
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);
|
||||
sector_t *Sector = point->Sector;
|
||||
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
|
||||
Sector->SkyBoxes[sector_t::ceiling] = skyv;
|
||||
if (skyv != NULL && skyv->bAlways)
|
||||
if (skyv != NULL)
|
||||
{
|
||||
skyv->Mate = point;
|
||||
skyv->target = point;
|
||||
if (Sector->GetAlphaF(sector_t::ceiling) == 1.)
|
||||
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;
|
||||
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
|
||||
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.)
|
||||
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 (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.)
|
||||
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;
|
||||
FSectorTagIterator itr(sectortag);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
SetPortal(§ors[s], plane, origin, alpha);
|
||||
SetPortal(§ors[s], plane, pnum, alpha);
|
||||
}
|
||||
|
||||
for (int j=0;j<numlines;j++)
|
||||
|
@ -930,14 +958,14 @@ static void CopyPortal(int sectortag, int plane, ASkyViewpoint *origin, double a
|
|||
{
|
||||
if (lines[j].args[0] == 0)
|
||||
{
|
||||
SetPortal(lines[j].frontsector, plane, origin, alpha);
|
||||
SetPortal(lines[j].frontsector, plane, pnum, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
FSectorTagIterator itr(lines[j].args[0]);
|
||||
while ((s = itr.Next()) >= 0)
|
||||
{
|
||||
SetPortal(§ors[s], plane, origin, alpha);
|
||||
SetPortal(§ors[s], plane, pnum, alpha);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -961,6 +989,7 @@ static void CopyPortal(int sectortag, int plane, ASkyViewpoint *origin, double a
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void P_SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int linked)
|
||||
{
|
||||
if (plane < 0 || plane > 2 || (linked && plane == 2)) return;
|
||||
|
@ -975,36 +1004,10 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int li
|
|||
lines[i].args[3] == 1)
|
||||
{
|
||||
// beware of overflows.
|
||||
DVector3 pos1((line->v1->fX() + line->v2->fX()) / 2, (line->v1->fY() + line->v2->fY()) / 2, 0);
|
||||
DVector3 pos2((lines[i].v1->fX() + lines[i].v2->fX()) / 2, (lines[i].v1->fY() + lines[i].v2->fY()) / 2, 0);
|
||||
double z = linked ? line->frontsector->GetPlaneTexZF(plane) : 0; // the map's sector height defines the portal plane for linked portals
|
||||
|
||||
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);
|
||||
DVector2 pos1 = line->v1->fPos() + line->Delta() / 2;
|
||||
DVector2 pos2 = lines[i].v1->fPos() + lines[i].Delta() / 2;
|
||||
unsigned pnum = P_GetPortal(linked ? PORTS_LINKEDPORTAL : PORTS_PORTAL, plane, line->frontsector, lines[i].frontsector, pos2 - pos1);
|
||||
CopyPortal(sectortag, plane, pnum, bytealpha / 255., false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1029,7 +1032,8 @@ void P_SpawnSkybox(ASkyViewpoint *origin)
|
|||
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.
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1355,11 +1359,8 @@ void P_SpawnSpecials (void)
|
|||
else if (lines[i].args[1] == 3 || lines[i].args[1] == 4)
|
||||
{
|
||||
line_t *line = &lines[i];
|
||||
ASkyViewpoint *origin = Spawn<ASkyViewpoint>();
|
||||
origin->Sector = line->frontsector;
|
||||
origin->special1 = line->args[1] == 3? SKYBOX_PLANE:SKYBOX_HORIZON;
|
||||
|
||||
CopyPortal(line->args[0], line->args[2], origin, 0, true);
|
||||
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;
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ void FTraceInfo::EnterSectorPortal(FPathTraverse &pt, int position, double frac,
|
|||
inshootthrough = true;
|
||||
startfrac = frac;
|
||||
EnterDist = enterdist;
|
||||
pt.PortalRelocate(entersec->SkyBoxes[position], ptflags, frac);
|
||||
pt.PortalRelocate(entersec->GetPortal(position)->mDisplacement, ptflags, frac);
|
||||
|
||||
if ((TraceFlags & TRACE_ReportPortals) && TraceCallback != NULL)
|
||||
{
|
||||
|
@ -321,7 +321,7 @@ void FTraceInfo::Setup3DFloors()
|
|||
{
|
||||
CurSector->floorplane = *rover->top.plane;
|
||||
CurSector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||
CurSector->SkyBoxes[sector_t::floor] = nullptr;
|
||||
CurSector->ClearPortal(sector_t::floor);
|
||||
bf = ff_top;
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ void FTraceInfo::Setup3DFloors()
|
|||
CurSector->ceilingplane = *rover->bottom.plane;
|
||||
CurSector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||
bc = ff_bottom;
|
||||
CurSector->SkyBoxes[sector_t::ceiling] = nullptr;
|
||||
CurSector->ClearPortal(sector_t::ceiling);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -343,7 +343,7 @@ void FTraceInfo::Setup3DFloors()
|
|||
{
|
||||
CurSector->floorplane = *rover->bottom.plane;
|
||||
CurSector->SetTexture(sector_t::floor, *rover->bottom.texture, false);
|
||||
CurSector->SkyBoxes[sector_t::floor] = nullptr;
|
||||
CurSector->ClearPortal(sector_t::floor);
|
||||
bf = ff_bottom;
|
||||
}
|
||||
|
||||
|
@ -351,7 +351,7 @@ void FTraceInfo::Setup3DFloors()
|
|||
{
|
||||
CurSector->ceilingplane = *rover->top.plane;
|
||||
CurSector->SetTexture(sector_t::ceiling, *rover->top.texture, false);
|
||||
CurSector->SkyBoxes[sector_t::ceiling] = nullptr;
|
||||
CurSector->ClearPortal(sector_t::ceiling);
|
||||
bc = ff_top;
|
||||
}
|
||||
inshootthrough = false;
|
||||
|
@ -499,7 +499,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
|||
{
|
||||
entersector->floorplane = *rover->top.plane;
|
||||
entersector->SetTexture(sector_t::floor, *rover->top.texture, false);
|
||||
entersector->SkyBoxes[sector_t::floor] = NULL;
|
||||
entersector->ClearPortal(sector_t::floor);
|
||||
bf = ff_top;
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ bool FTraceInfo::LineCheck(intercept_t *in, double dist, DVector3 hit)
|
|||
{
|
||||
entersector->ceilingplane = *rover->bottom.plane;
|
||||
entersector->SetTexture(sector_t::ceiling, *rover->bottom.texture, false);
|
||||
entersector->SkyBoxes[sector_t::ceiling] = NULL;
|
||||
entersector->ClearPortal(sector_t::ceiling);
|
||||
bc = ff_bottom;
|
||||
}
|
||||
}
|
||||
|
|
191
src/portal.cpp
191
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,25 @@ 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;
|
||||
return arc;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -487,7 +508,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 +517,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 +666,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 +853,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 +992,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 +1045,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 +1137,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
57
src/portal.h
57
src/portal.h
|
@ -6,6 +6,7 @@
|
|||
#include "m_bbox.h"
|
||||
|
||||
struct FPortalGroupArray;
|
||||
class ASkyViewpoint;
|
||||
//============================================================================
|
||||
//
|
||||
// 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)
|
||||
// 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;
|
||||
double mSinRot;
|
||||
double mCosRot;
|
||||
void *mRenderData;
|
||||
};
|
||||
|
||||
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_SpawnLinePortal(line_t* line);
|
||||
void P_FinalizePortals();
|
||||
|
@ -205,6 +255,9 @@ inline int P_NumPortalGroups()
|
|||
{
|
||||
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 */
|
||||
|
|
|
@ -515,18 +515,18 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec,
|
|||
|
||||
bool R_SkyboxCompare(sector_t *frontsector, sector_t *backsector)
|
||||
{
|
||||
AActor *frontc = frontsector->SkyBoxes[sector_t::ceiling];
|
||||
AActor *frontf = frontsector->SkyBoxes[sector_t::floor];
|
||||
AActor *backc = backsector->SkyBoxes[sector_t::ceiling];
|
||||
AActor *backf = backsector->SkyBoxes[sector_t::floor];
|
||||
FSectorPortal *frontc = frontsector->GetPortal(sector_t::ceiling);
|
||||
FSectorPortal *frontf = frontsector->GetPortal(sector_t::floor);
|
||||
FSectorPortal *backc = backsector->GetPortal(sector_t::ceiling);
|
||||
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.
|
||||
// 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.)
|
||||
if (frontc != NULL && (frontc->special1 == SKYBOX_PORTAL || frontc->special1 == SKYBOX_LINKEDPORTAL)) return (frontc != backc);
|
||||
if (frontf != NULL && (frontf->special1 == SKYBOX_PORTAL || frontf->special1 == SKYBOX_LINKEDPORTAL)) return (frontf != backf);
|
||||
if (backc != NULL && (backc->special1 == SKYBOX_PORTAL || backc->special1 == SKYBOX_LINKEDPORTAL)) return true;
|
||||
if (backf != NULL && (backf->special1 == SKYBOX_PORTAL || backf->special1 == SKYBOX_LINKEDPORTAL)) return true;
|
||||
if (!frontc->MergeAllowed()) return (frontc != backc);
|
||||
if (!frontf->MergeAllowed()) return (frontf != backf);
|
||||
if (!backc->MergeAllowed()) return true;
|
||||
if (!backf->MergeAllowed()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1046,7 +1046,7 @@ void R_Subsector (subsector_t *sub)
|
|||
int ceilinglightlevel; // killough 4/11/98
|
||||
bool outersubsector;
|
||||
int fll, cll, position;
|
||||
ASkyViewpoint *skybox;
|
||||
FSectorPortal *portal;
|
||||
|
||||
// kg3D - fake floor stuff
|
||||
visplane_t *backupfp;
|
||||
|
@ -1114,12 +1114,11 @@ void R_Subsector (subsector_t *sub)
|
|||
basecolormap = frontsector->ColorMap;
|
||||
}
|
||||
|
||||
skybox = frontsector->GetSkyBox(sector_t::ceiling);
|
||||
if (skybox != NULL && skybox->special1 >= SKYBOX_PLANE) skybox = NULL; // skip unsupported portal types
|
||||
portal = frontsector->ValidatePortal(sector_t::ceiling);
|
||||
|
||||
ceilingplane = frontsector->ceilingplane.PointOnSide(viewx, viewy, viewz) > 0 ||
|
||||
frontsector->GetTexture(sector_t::ceiling) == skyflatnum ||
|
||||
(skybox != NULL && skybox->bAlways) ||
|
||||
portal != NULL ||
|
||||
(frontsector->heightsec &&
|
||||
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||
frontsector->heightsec->GetTexture(sector_t::floor) == skyflatnum) ?
|
||||
|
@ -1134,7 +1133,7 @@ void R_Subsector (subsector_t *sub)
|
|||
frontsector->GetYScale(sector_t::ceiling),
|
||||
frontsector->GetAngle(sector_t::ceiling),
|
||||
frontsector->sky,
|
||||
skybox
|
||||
portal
|
||||
) : NULL;
|
||||
|
||||
if (fixedlightlev < 0 && frontsector->e && frontsector->e->XFloor.lightlist.Size())
|
||||
|
@ -1156,13 +1155,11 @@ void R_Subsector (subsector_t *sub)
|
|||
// killough 3/7/98: Add (x,y) offsets to flats, add deep water check
|
||||
// killough 3/16/98: add floorlightlevel
|
||||
// killough 10/98: add support for skies transferred from sidedefs
|
||||
|
||||
skybox = frontsector->GetSkyBox(sector_t::floor);
|
||||
if (skybox != NULL && skybox->special1 >= SKYBOX_PLANE) skybox = NULL; // skip unsupported portal types
|
||||
portal = frontsector->ValidatePortal(sector_t::floor);
|
||||
|
||||
floorplane = frontsector->floorplane.PointOnSide(viewx, viewy, viewz) > 0 || // killough 3/7/98
|
||||
frontsector->GetTexture(sector_t::floor) == skyflatnum ||
|
||||
(skybox != NULL && skybox->bAlways) ||
|
||||
portal != NULL ||
|
||||
(frontsector->heightsec &&
|
||||
!(frontsector->heightsec->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||
frontsector->heightsec->GetTexture(sector_t::ceiling) == skyflatnum) ?
|
||||
|
@ -1177,7 +1174,7 @@ void R_Subsector (subsector_t *sub)
|
|||
frontsector->GetYScale(sector_t::floor),
|
||||
frontsector->GetAngle(sector_t::floor),
|
||||
frontsector->sky,
|
||||
skybox
|
||||
portal
|
||||
) : NULL;
|
||||
|
||||
// kg3D - fake planes rendering
|
||||
|
|
46
src/r_defs.h
46
src/r_defs.h
|
@ -62,19 +62,6 @@ enum
|
|||
extern size_t MaxDrawSegs;
|
||||
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
|
||||
// used by play and refresh
|
||||
|
@ -529,8 +516,6 @@ enum
|
|||
SECF_UNDERWATERMASK = 32+64,
|
||||
SECF_DRAWN = 128, // sector has been drawn at least once
|
||||
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
|
||||
|
@ -700,7 +685,7 @@ public:
|
|||
|
||||
DInterpolation *SetInterpolation(int position, bool attach);
|
||||
|
||||
ASkyViewpoint *GetSkyBox(int which);
|
||||
FSectorPortal *ValidatePortal(int which);
|
||||
void CheckPortalPlane(int plane);
|
||||
|
||||
enum
|
||||
|
@ -963,8 +948,7 @@ public:
|
|||
|
||||
bool PortalBlocksView(int plane)
|
||||
{
|
||||
if (SkyBoxes[plane] == NULL) return true;
|
||||
if (GetPortalType(plane) != SKYBOX_LINKEDPORTAL) return false;
|
||||
if (GetPortalType(plane) != PORTS_LINKEDPORTAL) return false;
|
||||
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
|
||||
}
|
||||
|
||||
|
@ -985,28 +969,37 @@ public:
|
|||
|
||||
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)
|
||||
{
|
||||
return SkyBoxes[plane]->specialf1;
|
||||
return sectorPortals[Portals[plane]].mPlaneZ;
|
||||
}
|
||||
|
||||
DVector2 GetPortalDisplacement(int plane)
|
||||
{
|
||||
return SkyBoxes[plane]->Scale;
|
||||
return sectorPortals[Portals[plane]].mDisplacement;
|
||||
}
|
||||
|
||||
int GetPortalType(int plane)
|
||||
{
|
||||
return SkyBoxes[plane] == nullptr? -1 : SkyBoxes[plane]->special1;
|
||||
return sectorPortals[Portals[plane]].mType;
|
||||
}
|
||||
|
||||
int GetOppositePortalGroup(int plane)
|
||||
{
|
||||
return SkyBoxes[plane]->Sector->PortalGroup;
|
||||
return sectorPortals[Portals[plane]].mDestination->PortalGroup;
|
||||
}
|
||||
|
||||
void SetVerticesDirty()
|
||||
|
@ -1128,9 +1121,8 @@ public:
|
|||
// occurs, SecActTarget's TriggerAction method is called.
|
||||
TObjPtr<ASectorAction> SecActTarget;
|
||||
|
||||
// [RH] The sky box to render for this sector. NULL means use a
|
||||
// regular sky.
|
||||
TObjPtr<AActor> SkyBoxes[2];
|
||||
// [RH] The portal or skybox to render for this sector.
|
||||
unsigned Portals[2];
|
||||
int PortalGroup;
|
||||
|
||||
int sectornum; // for comparing sector copies
|
||||
|
|
|
@ -693,7 +693,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
|||
fixed_t starty = viewy;
|
||||
fixed_t startz = viewz;
|
||||
DVector3 savedpath[2] = { ViewPath[0], ViewPath[1] };
|
||||
int savedvisibility = camera->renderflags & RF_INVISIBLE;
|
||||
int savedvisibility = camera? camera->renderflags & RF_INVISIBLE : 0;
|
||||
|
||||
CurrentPortalUniq++;
|
||||
|
||||
|
@ -746,7 +746,7 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
|||
viewz = FLOAT2FIXED(view.Z);
|
||||
viewangle = va.BAMs();
|
||||
|
||||
if (!r_showviewer)
|
||||
if (!r_showviewer && camera)
|
||||
{
|
||||
double distp = (ViewPath[0] - ViewPath[1]).Length();
|
||||
if (distp > EQUAL_EPSILON)
|
||||
|
@ -802,11 +802,11 @@ void R_EnterPortal (PortalDrawseg* pds, int depth)
|
|||
InSubsector = NULL;
|
||||
R_RenderBSPNode (nodes + numnodes - 1);
|
||||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||
if (!savedvisibility) camera->renderflags &= ~RF_INVISIBLE;
|
||||
if (!savedvisibility && camera) camera->renderflags &= ~RF_INVISIBLE;
|
||||
|
||||
PlaneCycles.Clock();
|
||||
R_DrawPlanes ();
|
||||
R_DrawSkyBoxes ();
|
||||
R_DrawPortals ();
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
fixed_t vzp = viewz;
|
||||
|
@ -961,7 +961,7 @@ void R_RenderActorView (AActor *actor, bool dontmaplines)
|
|||
{
|
||||
PlaneCycles.Clock();
|
||||
R_DrawPlanes ();
|
||||
R_DrawSkyBoxes ();
|
||||
R_DrawPortals ();
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
// [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,
|
||||
fixed_t xoffs, fixed_t yoffs,
|
||||
fixed_t xscale, fixed_t yscale, angle_t angle,
|
||||
int sky, ASkyViewpoint *skybox)
|
||||
int sky, FSectorPortal *portal)
|
||||
{
|
||||
secplane_t plane;
|
||||
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 visplane, then only the floor sky will be drawn.
|
||||
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;
|
||||
isskybox = true;
|
||||
|
@ -622,7 +622,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
// and ->alpha is for stacked sectors
|
||||
if (fake3D & (FAKE3D_FAKEFLOOR|FAKE3D_FAKECEILING)) sky = 0x80000000 | fakeAlpha;
|
||||
else sky = 0; // not skyflatnum so it can't be a sky
|
||||
skybox = NULL;
|
||||
portal = NULL;
|
||||
alpha = OPAQUE;
|
||||
}
|
||||
|
||||
|
@ -633,9 +633,9 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
{
|
||||
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
|
||||
// check even more.
|
||||
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 &&
|
||||
(
|
||||
// headache inducing logic... :(
|
||||
(!(skybox->flags & MF_JUSTATTACKED)) ||
|
||||
(portal->mType != PORTS_STACKEDSECTORTHING) ||
|
||||
(
|
||||
check->Alpha == alpha &&
|
||||
check->Additive == additive &&
|
||||
|
@ -710,7 +710,7 @@ visplane_t *R_FindPlane (const secplane_t &height, FTextureID picnum, int lightl
|
|||
check->angle = angle;
|
||||
check->colormap = basecolormap; // [RH] Save colormap
|
||||
check->sky = sky;
|
||||
check->skybox = skybox;
|
||||
check->portal = portal;
|
||||
check->left = viewwidth; // Was SCREENWIDTH -- killough 11/98
|
||||
check->right = 0;
|
||||
check->extralight = stacked_extralight;
|
||||
|
@ -781,7 +781,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
|||
// make a new visplane
|
||||
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;
|
||||
}
|
||||
|
@ -800,7 +800,7 @@ visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop)
|
|||
new_pl->yscale = pl->yscale;
|
||||
new_pl->angle = pl->angle;
|
||||
new_pl->colormap = pl->colormap;
|
||||
new_pl->skybox = pl->skybox;
|
||||
new_pl->portal = pl->portal;
|
||||
new_pl->extralight = pl->extralight;
|
||||
new_pl->visibility = pl->visibility;
|
||||
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.
|
||||
//
|
||||
|
@ -1181,7 +1181,7 @@ void R_DrawSinglePlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
|
|||
CVAR (Bool, r_skyboxes, true, 0)
|
||||
static int numskyboxes;
|
||||
|
||||
void R_DrawSkyBoxes ()
|
||||
void R_DrawPortals ()
|
||||
{
|
||||
static TArray<size_t> interestingStack;
|
||||
static TArray<ptrdiff_t> drawsegStack;
|
||||
|
@ -1221,7 +1221,7 @@ void R_DrawSkyBoxes ()
|
|||
visplanes[MAXVISPLANES] = pl->next;
|
||||
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);
|
||||
*freehead = pl;
|
||||
|
@ -1231,14 +1231,15 @@ void R_DrawSkyBoxes ()
|
|||
|
||||
numskyboxes++;
|
||||
|
||||
ASkyViewpoint *sky = pl->skybox;
|
||||
ASkyViewpoint *mate = sky->Mate;
|
||||
|
||||
if (mate == NULL)
|
||||
FSectorPortal *port = pl->portal;
|
||||
switch (port->mType)
|
||||
{
|
||||
case PORTS_SKYVIEWPOINT:
|
||||
{
|
||||
// Don't let gun flashes brighten the sky box
|
||||
ASkyViewpoint *sky = barrier_cast<ASkyViewpoint*>(port->mSkybox);
|
||||
extralight = 0;
|
||||
R_SetVisibility (sky->args[0] * 0.25f);
|
||||
R_SetVisibility(sky->args[0] * 0.25f);
|
||||
|
||||
DVector3 viewpos = sky->InterpolatedPosition(r_TicFracF);
|
||||
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();
|
||||
|
||||
R_CopyStackedViewParameters();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
case PORTS_STACKEDSECTORTHING:
|
||||
case PORTS_PORTAL:
|
||||
case PORTS_LINKEDPORTAL:
|
||||
extralight = pl->extralight;
|
||||
R_SetVisibility (pl->visibility);
|
||||
viewx = pl->viewx + FLOAT2FIXED(-sky->Mate->X() + sky->X());
|
||||
viewy = pl->viewy + FLOAT2FIXED(-sky->Mate->Y() + sky->Y());
|
||||
viewx = pl->viewx + FLOAT2FIXED(port->mDisplacement.X);
|
||||
viewy = pl->viewy + FLOAT2FIXED(port->mDisplacement.Y);
|
||||
viewz = pl->viewz;
|
||||
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);
|
||||
ViewPos = { FIXED2DBL(viewx), FIXED2DBL(viewy), FIXED2DBL(viewz) };
|
||||
|
||||
sky->bInSkybox = true;
|
||||
if (mate != NULL) mate->bInSkybox = true;
|
||||
camera = sky;
|
||||
viewsector = sky->Sector;
|
||||
port->mFlags |= PORTSF_INSKYBOX;
|
||||
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags |= PORTSF_INSKYBOX;
|
||||
camera = NULL;
|
||||
viewsector = port->mDestination;
|
||||
assert(viewsector != NULL);
|
||||
R_SetViewAngle ();
|
||||
validcount++; // Make sure we see all sprites
|
||||
|
||||
|
@ -1324,8 +1342,8 @@ void R_DrawSkyBoxes ()
|
|||
R_3D_ResetClip(); // reset clips (floor/ceiling)
|
||||
R_DrawPlanes ();
|
||||
|
||||
sky->bInSkybox = false;
|
||||
if (mate != NULL) mate->bInSkybox = false;
|
||||
port->mFlags &= ~PORTSF_INSKYBOX;
|
||||
if (port->mPartner > 0) sectorPortals[port->mPartner].mFlags &= ~PORTSF_INSKYBOX;
|
||||
}
|
||||
|
||||
// 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
|
||||
angle_t angle; // [RH] Support flat rotation
|
||||
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
|
||||
// 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);
|
||||
|
||||
int R_DrawPlanes ();
|
||||
void R_DrawSkyBoxes ();
|
||||
void R_DrawPortals ();
|
||||
void R_DrawSkyPlane (visplane_t *pl);
|
||||
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);
|
||||
|
@ -106,7 +106,7 @@ visplane_t *R_FindPlane
|
|||
fixed_t yscale,
|
||||
angle_t angle,
|
||||
int sky,
|
||||
ASkyViewpoint *skybox);
|
||||
FSectorPortal *portal);
|
||||
|
||||
visplane_t *R_CheckPlane (visplane_t *pl, int start, int stop);
|
||||
|
||||
|
|
|
@ -1536,6 +1536,7 @@ void R_DrawPlayerSprites ()
|
|||
F3DFloor *rover;
|
||||
|
||||
if (!r_drawplayersprites ||
|
||||
!camera ||
|
||||
!camera->player ||
|
||||
(players[consoleplayer].cheats & CF_CHASECAM) ||
|
||||
(r_deathcamera && camera->health <= 0))
|
||||
|
|
|
@ -72,11 +72,11 @@ const char *GetVersionString();
|
|||
// SAVESIG should match SAVEVER.
|
||||
|
||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||
#define MINSAVEVER 4536
|
||||
#define MINSAVEVER 4540
|
||||
|
||||
// Use 4500 as the base git save version, since it's higher than the
|
||||
// SVN revision ever got.
|
||||
#define SAVEVER 4538
|
||||
#define SAVEVER 4540
|
||||
|
||||
#define SAVEVERSTRINGIFY2(x) #x
|
||||
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)
|
||||
|
|
Loading…
Reference in a new issue