Merge remote-tracking branch 'remotes/origin/portal'

This commit is contained in:
Christoph Oelckers 2016-02-22 15:54:07 +01:00
commit 49bfe717ce
36 changed files with 1298 additions and 696 deletions

View file

@ -40,6 +40,7 @@
#include "memarena.h"
#include "g_level.h"
#include "tflags.h"
#include "portal.h"
struct subsector_t;
class PClassAmmo;
@ -1182,24 +1183,13 @@ public:
}
fixedvec3 Pos() const
{
fixedvec3 ret = { X(), Y(), Z() };
return ret;
}
fixedvec3 PosRelative(AActor *other) const
{
fixedvec3 ret = { X(), Y(), Z() };
return ret;
}
fixedvec3 PosRelative(sector_t *sec) const
{
fixedvec3 ret = { X(), Y(), Z() };
return ret;
}
fixedvec3 PosRelative(line_t *line) const
{
fixedvec3 ret = { X(), Y(), Z() };
return ret;
return __pos;
}
fixedvec3 PosRelative(AActor *other) const;
fixedvec3 PosRelative(sector_t *sec) const;
fixedvec3 PosRelative(line_t *line) const;
fixed_t SoundX() const
{
return X();
@ -1377,11 +1367,6 @@ inline fixedvec2 Vec2Angle(fixed_t length, angle_t angle)
return ret;
}
inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refsec = NULL)
{
return pos;
}
void PrintMiscActorInfo(AActor * query);
AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch, ActorFlags actorMask, DWORD wallMask);

View file

@ -83,10 +83,12 @@ bool DBot::Move (ticcmd_t *cmd)
player->mo->movedir = DI_NODIR;
good = 0;
spechit_t spechit1;
line_t *ld;
while (spechit.Pop (ld))
while (spechit.Pop (spechit1))
{
ld = spechit1.line;
bool tryit = true;
if (ld->special == Door_LockedRaise && !P_CheckKeys (player->mo, ld->args[3], false))

View file

@ -81,16 +81,62 @@ union QWORD_UNION
typedef SDWORD fixed_t;
typedef DWORD dsfixed_t; // fixedpt used by span drawer
struct fixedvec3
{
fixed_t x, y, z;
};
struct fixedvec2
{
fixed_t x, y;
fixedvec2 &operator +=(const fixedvec2 &other)
{
x += other.x;
y += other.y;
return *this;
}
};
struct fixedvec3
{
fixed_t x, y, z;
fixedvec3 &operator +=(const fixedvec3 &other)
{
x += other.x;
y += other.y;
z += other.z;
return *this;
}
fixedvec3 &operator +=(const fixedvec2 &other)
{
x += other.x;
y += other.y;
return *this;
}
operator fixedvec2()
{
fixedvec2 ret = { x, y };
return ret;
}
};
inline fixedvec2 operator +(const fixedvec2 &v1, const fixedvec2 &v2)
{
fixedvec2 v = { v1.x + v2.x, v1.y + v2.y };
return v;
}
inline fixedvec3 operator +(const fixedvec3 &v1, const fixedvec3 &v2)
{
fixedvec3 v = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z };
return v;
}
inline fixedvec3 operator +(const fixedvec3 &v1, const fixedvec2 &v2)
{
fixedvec3 v = { v1.x + v2.x, v1.y + v2.y, v1.z };
return v;
}
#define FIXED_MAX (signed)(0x7fffffff)
#define FIXED_MIN (signed)(0x80000000)

View file

@ -111,7 +111,7 @@ void A_PainShootSkull (AActor *self, angle_t angle, PClassActor *spawntype, int
if (!inportal) break;
// recalculate position and redo the check on the other side of the portal
pos = self->Vec3Offset(dist.x, dist.y, 8 * FRACUNIT, false);
pos = self->Vec3Offset(dist.x, dist.y, 8 * FRACUNIT);
src.x = pos.x - dist.x;
src.y = pos.y - dist.y;
@ -122,9 +122,9 @@ void A_PainShootSkull (AActor *self, angle_t angle, PClassActor *spawntype, int
// Check to see if the new Lost Soul's z value is above the
// ceiling of its new sector, or below the floor. If so, kill it.
if ((other->Z() >
(other->Sector->HighestCeiling(other) - other->height)) ||
(other->Z() < other->Sector->LowestFloor(other)))
if ((other->Top() >
(other->Sector->HighestCeilingAt(other))) ||
(other->Z() < other->Sector->LowestFloorAt(other)))
{
// kill it immediately
P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);// ^

View file

@ -82,7 +82,7 @@ void AFastProjectile::Tick ()
if (tm.ceilingline &&
tm.ceilingline->backsector &&
tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint (this))
Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(PosRelative(tm.ceilingline)))
{
// Hack to prevent missiles exploding against the sky.
// Does not handle sky floors.

View file

@ -414,7 +414,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition)
// Move item back to its original location
fixed_t _x, _y;
sector_t *sec;
_x = self->SpawnPoint[0];
_y = self->SpawnPoint[1];
@ -422,12 +421,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition)
self->UnlinkFromWorld();
self->SetXY(_x, _y);
self->LinkToWorld(true);
sec = self->Sector;
self->dropoffz =
self->floorz = sec->floorplane.ZatPoint(_x, _y);
self->ceilingz = sec->ceilingplane.ZatPoint(_x, _y);
self->SetZ(self->floorz);
P_FindFloorCeiling(self, FFCF_ONLYSPAWNPOS);
self->SetZ(self->Sector->floorplane.ZatPoint(_x, _y));
P_FindFloorCeiling(self, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector.
if (self->flags & MF_SPAWNCEILING)
{
@ -450,7 +445,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RestoreSpecialPosition)
{
self->SetZ(self->SpawnPoint[2] + self->floorz);
}
// Redo floor/ceiling check, in case of 3D floors
// Redo floor/ceiling check, in case of 3D floors and portals
P_FindFloorCeiling(self, FFCF_SAMESECTOR | FFCF_ONLY3DFLOORS | FFCF_3DRESTRICT);
if (self->Z() < self->floorz)
{ // Do not reappear under the floor, even if that's where we were for the

View file

@ -659,7 +659,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
sector_t *sec = self->Sector;
if (self->Z() == sec->floorplane.ZatPoint(self))
if (self->Z() == sec->floorplane.ZatPoint(self) && sec->PortalBlocksMovement(sector_t::floor))
{
if (sec->special == Damage_InstantDeath)
{

View file

@ -34,7 +34,7 @@
//
//==========================================================================
FBoundingBox::FBoundingBox(fixed_t x, fixed_t y, fixed_t radius)
void FBoundingBox::setBox(fixed_t x, fixed_t y, fixed_t radius)
{
m_Box[BOXTOP] = (fixed_t)MIN<SQWORD>((SQWORD)y + radius, FIXED_MAX);
m_Box[BOXLEFT] = (fixed_t)MAX<SQWORD>((SQWORD)x - radius, FIXED_MIN);

View file

@ -43,7 +43,12 @@ public:
m_Box[BOXBOTTOM] = bottom;
}
FBoundingBox(fixed_t x, fixed_t y, fixed_t radius);
FBoundingBox(fixed_t x, fixed_t y, fixed_t radius)
{
setBox(x, y, radius);
}
void setBox(fixed_t x, fixed_t y, fixed_t radius);
void ClearBox ()
{

View file

@ -775,6 +775,8 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
FTextureID highestfloorpic;
int highestfloorterrain = -1;
FTextureID lowestceilingpic;
sector_t *lowestceilingsec = NULL, *highestfloorsec = NULL;
secplane_t *highestfloorplanes[2] = { NULL, NULL };
highestfloorpic.SetInvalid();
lowestceilingpic.SetInvalid();
@ -798,6 +800,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
{
lowestceiling = ff_bottom;
lowestceilingpic = *rover->bottom.texture;
lowestceilingsec = j == 0 ? linedef->frontsector : linedef->backsector;
}
if(ff_top > highestfloor && delta1 < delta2 && (!restrict || thing->Z() >= ff_top))
@ -805,6 +808,8 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
highestfloor = ff_top;
highestfloorpic = *rover->top.texture;
highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling);
highestfloorsec = j == 0 ? linedef->frontsector : linedef->backsector;
highestfloorplanes[j] = rover->top.plane;
}
if(ff_top > lowestfloor[j] && ff_top <= thing->Z() + thing->MaxStepHeight) lowestfloor[j] = ff_top;
}
@ -815,12 +820,24 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li
open.bottom = highestfloor;
open.floorpic = highestfloorpic;
open.floorterrain = highestfloorterrain;
open.bottomsec = highestfloorsec;
if (highestfloorplanes[0])
{
open.frontfloorplane = *highestfloorplanes[0];
if (open.frontfloorplane.c < 0) open.frontfloorplane.FlipVert();
}
if (highestfloorplanes[1])
{
open.backfloorplane = *highestfloorplanes[1];
if (open.backfloorplane.c < 0) open.backfloorplane.FlipVert();
}
}
if(lowestceiling < open.top)
{
open.top = lowestceiling;
open.ceilingpic = lowestceilingpic;
open.topsec = lowestceilingsec;
}
open.lowfloor = MIN(lowestfloor[0], lowestfloor[1]);

View file

@ -294,6 +294,8 @@ bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, FLineOpening &
open.abovemidtex = true;
open.floorpic = linedef->sidedef[0]->GetTexture(side_t::mid);
open.floorterrain = TerrainTypes[open.floorpic];
open.frontfloorplane.SetAtHeight(tt, sector_t::floor);
open.backfloorplane.SetAtHeight(tt, sector_t::floor);
}
// returns true if it touches the midtexture

View file

@ -76,7 +76,6 @@
#include "actorptrselect.h"
#include "farchive.h"
#include "decallib.h"
#include "portal.h"
#include "p_terrain.h"
#include "version.h"
#include "p_effect.h"
@ -4179,49 +4178,19 @@ bool DLevelScript::DoCheckActorTexture(int tid, AActor *activator, int string, b
// they're obviously not the same.
return 0;
}
int i, numff;
FTextureID secpic;
sector_t *sec = actor->Sector;
numff = sec->e->XFloor.ffloors.Size();
sector_t *resultsec;
F3DFloor *resffloor;
if (floor)
{
// Looking through planes from top to bottom
for (i = 0; i < numff; ++i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) &&
actor->Z() >= ff->top.plane->ZatPoint(actor))
{ // This floor is beneath our feet.
secpic = *ff->top.texture;
break;
}
}
if (i == numff)
{ // Use sector's floor
secpic = sec->GetTexture(sector_t::floor);
}
actor->Sector->NextLowestFloorAt(actor, actor->Z(), 0, &resultsec, &resffloor);
secpic = resffloor ? *resffloor->top.texture : resultsec->planes[sector_t::floor].Texture;
}
else
{
fixed_t z = actor->Top();
// Looking through planes from bottom to top
for (i = numff-1; i >= 0; --i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) &&
z <= ff->bottom.plane->ZatPoint(actor))
{ // This floor is above our eyes.
secpic = *ff->bottom.texture;
break;
}
}
if (i < 0)
{ // Use sector's ceiling
secpic = sec->GetTexture(sector_t::ceiling);
}
actor->Sector->NextHighestCeilingAt(actor, actor->Top(), 0, &resultsec, &resffloor);
secpic = resffloor ? *resffloor->bottom.texture : resultsec->planes[sector_t::ceiling].Texture;
}
return tex == TexMan[secpic];
}

View file

@ -17,7 +17,6 @@
#include "g_level.h"
#include "r_data/colormaps.h"
#include "gi.h"
#include "portal.h"
#include "p_spec.h"
// MACROS ------------------------------------------------------------------

View file

@ -2,63 +2,6 @@
#define P_CHECKPOS_H
//============================================================================
//
// This is a dynamic array which holds its first MAX_STATIC entries in normal
// variables to avoid constant allocations which this would otherwise
// require.
//
// When collecting touched portal groups the normal cases are either
// no portals == one group or
// two portals = two groups
//
// Anything with more can happen but far less infrequently, so this
// organization helps avoiding the overhead from heap allocations
// in the vast majority of situations.
//
//============================================================================
struct FPortalGroupArray
{
enum
{
MAX_STATIC = 2
};
FPortalGroupArray()
{
varused = 0;
}
void Clear()
{
data.Clear();
varused = 0;
}
void Add(DWORD num)
{
if (varused < MAX_STATIC) entry[varused++] = num;
else data.Push(num);
}
unsigned Size()
{
return varused + data.Size();
}
DWORD operator[](unsigned index)
{
return index < MAX_STATIC ? entry[index] : data[index - MAX_STATIC];
}
private:
DWORD entry[MAX_STATIC];
unsigned varused;
TArray<DWORD> data;
};
//============================================================================
//
// Used by P_CheckPosition and P_TryMove in place of the original
@ -95,7 +38,6 @@ struct FCheckPosition
bool DoRipping;
TMap<AActor*, bool> LastRipped;
FPortalGroupArray Groups;
int PushTime;
FCheckPosition(bool rip=false)

View file

@ -558,7 +558,7 @@ bool P_Move (AActor *actor)
else
{ // The monster just hit the floor, so trigger any actions.
if (actor->floorsector->SecActTarget != NULL &&
actor->floorz == actor->floorsector->floorplane.ZatPoint(actor))
actor->floorz == actor->floorsector->floorplane.ZatPoint(actor->PosRelative(actor->floorsector)))
{
actor->floorsector->SecActTarget->TriggerAction(actor, SECSPAC_HitFloor);
}
@ -612,18 +612,18 @@ bool P_Move (AActor *actor)
// Do NOT simply return false 1/4th of the time (causes monsters to
// back out when they shouldn't, and creates secondary stickiness).
line_t *ld;
spechit_t spec;
int good = 0;
if (!(actor->flags6 & MF6_NOTRIGGER))
{
while (spechit.Pop (ld))
while (spechit.Pop (spec))
{
// [RH] let monsters push lines, as well as use them
if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (ld, actor, 0, SPAC_Use)) ||
((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (ld, actor, 0, SPAC_Push)))
if (((actor->flags4 & MF4_CANUSEWALLS) && P_ActivateLine (spec.line, actor, 0, SPAC_Use)) ||
((actor->flags2 & MF2_PUSHWALL) && P_ActivateLine (spec.line, actor, 0, SPAC_Push)))
{
good |= ld == actor->BlockingLine ? 1 : 2;
good |= spec.line == actor->BlockingLine ? 1 : 2;
}
}
}
@ -868,8 +868,8 @@ void P_NewChaseDir(AActor * actor)
box.Bottom() < line->bbox[BOXTOP] &&
box.BoxOnLineSide(line) == -1)
{
fixed_t front = line->frontsector->floorplane.ZatPoint(actor);
fixed_t back = line->backsector->floorplane.ZatPoint(actor);
fixed_t front = line->frontsector->floorplane.ZatPoint(actor->PosRelative(line));
fixed_t back = line->backsector->floorplane.ZatPoint(actor->PosRelative(line));
angle_t angle;
// The monster must contact one of the two floors,

View file

@ -57,7 +57,6 @@
#include "d_net.h"
#include "d_event.h"
#include "gstrings.h"
#include "portal.h"
#include "po_man.h"
#include "d_player.h"
#include "r_utility.h"

View file

@ -240,7 +240,14 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false)
// if within "tmfloorz - tmceilingz".
extern msecnode_t *sector_list; // phares 3/16/98
extern TArray<line_t *> spechit;
struct spechit_t
{
line_t *line;
fixedvec2 refpos;
};
extern TArray<spechit_t> spechit;
extern TArray<spechit_t> portalhit;
bool P_TestMobjLocation (AActor *mobj);
@ -287,6 +294,10 @@ enum
FFCF_SAMESECTOR = 2,
FFCF_ONLY3DFLOORS = 4, // includes 3D midtexes
FFCF_3DRESTRICT = 8, // ignore 3D midtexes and floors whose floorz are above thing's z
FFCF_NOPORTALS = 16, // ignore portals (considers them impassable.)
FFCF_NOFLOOR = 32,
FFCF_NOCEILING = 64,
FFCF_RESTRICTEDPORTAL = 128, // current values in the iterator's return are through a restricted portal type (i.e. some features are blocked.)
};
void P_FindFloorCeiling (AActor *actor, int flags=0);

File diff suppressed because it is too large Load diff

View file

@ -162,10 +162,28 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
front = linedef->frontsector;
back = linedef->backsector;
fc = front->ceilingplane.ZatPoint (x, y);
ff = front->floorplane.ZatPoint (x, y);
bc = back->ceilingplane.ZatPoint (x, y);
bf = back->floorplane.ZatPoint (x, y);
if (!(flags & FFCF_NOPORTALS) && !linedef->frontsector->PortalBlocksMovement(sector_t::ceiling) &&
linedef->backsector->SkyBoxes[sector_t::ceiling] &&
linedef->frontsector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup == linedef->backsector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup)
{
fc = bc = FIXED_MAX;
}
else
{
fc = front->ceilingplane.ZatPoint(x, y);
bc = back->ceilingplane.ZatPoint(x, y);
}
if (!(flags & FFCF_NOPORTALS) && !linedef->frontsector->PortalBlocksMovement(sector_t::floor) &&
linedef->backsector->SkyBoxes[sector_t::floor] &&
linedef->frontsector->SkyBoxes[sector_t::floor]->Sector->PortalGroup == linedef->backsector->SkyBoxes[sector_t::floor]->Sector->PortalGroup)
{
ff = bf = FIXED_MIN;
}
else
{
ff = front->floorplane.ZatPoint(x, y);
bf = back->floorplane.ZatPoint(x, y);
}
/*Printf ("]]]]]] %d %d\n", ff, bf);*/
@ -211,6 +229,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
open.floorterrain = back->GetTerrain(sector_t::floor);
open.lowfloor = ff;
}
open.frontfloorplane = front->floorplane;
open.backfloorplane = back->floorplane;
}
else
{ // Dummy stuff to have some sort of opening for the 3D checks to modify
@ -222,6 +242,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
open.floorterrain = -1;
open.bottom = FIXED_MIN;
open.lowfloor = FIXED_MAX;
open.frontfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
open.backfloorplane.SetAtHeight(FIXED_MIN, sector_t::floor);
}
// Check 3D floors
@ -513,11 +535,15 @@ void AActor::SetOrigin (fixed_t ix, fixed_t iy, fixed_t iz, bool moving)
SetXYZ(ix, iy, iz);
if (moving) SetMovement(ix - X(), iy - Y(), iz - Z());
LinkToWorld ();
floorz = Sector->floorplane.ZatPoint (ix, iy);
ceilingz = Sector->ceilingplane.ZatPoint (ix, iy);
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS);
}
//===========================================================================
//
// FBlockNode - allows to link actors into multiple blocks in the blockmap
//
//===========================================================================
FBlockNode *FBlockNode::FreeBlocks = NULL;
FBlockNode *FBlockNode::Create (AActor *who, int x, int y, int group)
@ -574,7 +600,7 @@ FBlockLinesIterator::FBlockLinesIterator(int _minx, int _miny, int _maxx, int _m
Reset();
}
FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
void FBlockLinesIterator::init(const FBoundingBox &box)
{
validcount++;
maxy = GetSafeBlockY(box.Top() - bmaporgy);
@ -584,6 +610,10 @@ FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
Reset();
}
FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
{
init(box);
}
//===========================================================================
//
@ -683,6 +713,169 @@ line_t *FBlockLinesIterator::Next()
}
}
//===========================================================================
//
// FMultiBlockLinesIterator :: FMultiBlockLinesIterator
//
// An iterator that can check multiple portal groups.
//
//===========================================================================
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius)
: checklist(check)
{
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
Reset();
}
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
Reset();
}
//===========================================================================
//
// Go up a ceiling portal
//
//===========================================================================
bool FMultiBlockLinesIterator::GoUp(fixed_t x, fixed_t y)
{
if (continueup)
{
sector_t *sector = P_PointInSector(x, y);
if (!sector->PortalBlocksMovement(sector_t::ceiling))
{
startIteratorForGroup(sector->SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
portalflags = FFCF_NOFLOOR;
return true;
}
else continueup = false;
}
return false;
}
//===========================================================================
//
// Go down a floor portal
//
//===========================================================================
bool FMultiBlockLinesIterator::GoDown(fixed_t x, fixed_t y)
{
if (continuedown)
{
sector_t *sector = P_PointInSector(x, y);
if (!sector->PortalBlocksMovement(sector_t::floor))
{
startIteratorForGroup(sector->SkyBoxes[sector_t::floor]->Sector->PortalGroup);
portalflags = FFCF_NOCEILING;
return true;
}
else continuedown = false;
}
return false;
}
//===========================================================================
//
// Gets the next line - also manages switching between portal groups
//
//===========================================================================
bool FMultiBlockLinesIterator::Next(FMultiBlockLinesIterator::CheckResult *item)
{
line_t *line = blockIterator.Next();
if (line != NULL)
{
item->line = line;
item->position.x = offset.x;
item->position.y = offset.y;
item->portalflags = portalflags;
return true;
}
bool onlast = unsigned(index + 1) >= checklist.Size();
int nextflags = onlast ? 0 : checklist[index + 1] & FPortalGroupArray::FLAT;
if (portalflags == FFCF_NOFLOOR && nextflags != FPortalGroupArray::UPPER)
{
// if this is the last upper portal in the list, check if we need to go further up to find the real ceiling.
if (GoUp(offset.x, offset.y)) return Next(item);
}
else if (portalflags == FFCF_NOCEILING && nextflags != FPortalGroupArray::LOWER)
{
// if this is the last lower portal in the list, check if we need to go further down to find the real floor.
if (GoDown(offset.x, offset.y)) return Next(item);
}
if (onlast)
{
// We reached the end of the list. Check if we still need to check up- and downwards.
if (GoUp(checkpoint.x, checkpoint.y) ||
GoDown(checkpoint.x, checkpoint.y))
{
return Next(item);
}
return false;
}
index++;
startIteratorForGroup(checklist[index] & ~FPortalGroupArray::FLAT);
switch (nextflags)
{
case FPortalGroupArray::UPPER:
portalflags = FFCF_NOFLOOR;
break;
case FPortalGroupArray::LOWER:
portalflags = FFCF_NOCEILING;
break;
default:
portalflags = 0;
}
return Next(item);
}
//===========================================================================
//
// start iterating a new group
//
//===========================================================================
void FMultiBlockLinesIterator::startIteratorForGroup(int group)
{
offset = Displacements(basegroup, group);
offset.x += checkpoint.x;
offset.y += checkpoint.y;
bbox.setBox(offset.x, offset.y, checkpoint.z);
blockIterator.init(bbox);
}
//===========================================================================
//
// Resets the iterator
//
//===========================================================================
void FMultiBlockLinesIterator::Reset()
{
continueup = continueup = true;
index = -1;
portalflags = 0;
startIteratorForGroup(basegroup);
}
//===========================================================================
//
// FBlockThingsIterator :: FBlockThingsIterator
@ -709,8 +902,7 @@ FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int
Reset();
}
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
: DynHash(0)
void FBlockThingsIterator::init(const FBoundingBox &box)
{
maxy = GetSafeBlockY(box.Top() - bmaporgy);
miny = GetSafeBlockY(box.Bottom() - bmaporgy);
@ -852,6 +1044,108 @@ AActor *FBlockThingsIterator::Next(bool centeronly)
}
//===========================================================================
//
// FMultiBlockThingsIterator :: FMultiBlockThingsIterator
//
// An iterator that can check multiple portal groups.
//
//===========================================================================
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius, bool ignorerestricted)
: checklist(check)
{
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
Reset();
}
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted)
: checklist(check)
{
checkpoint.x = checkx;
checkpoint.y = checky;
checkpoint.z = checkz;
basegroup = P_PointInSector(checkx, checky)->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.z = checkradius;
Reset();
}
//===========================================================================
//
// Gets the next line - also manages switching between portal groups
//
//===========================================================================
bool FMultiBlockThingsIterator::Next(FMultiBlockThingsIterator::CheckResult *item)
{
AActor *thing = blockIterator.Next();
if (thing != NULL)
{
item->thing = thing;
item->position = checkpoint + Displacements(basegroup, thing->Sector->PortalGroup);
item->portalflags = portalflags;
return true;
}
bool onlast = unsigned(index + 1) >= checklist.Size();
int nextflags = onlast ? 0 : checklist[index + 1] & FPortalGroupArray::FLAT;
if (onlast)
{
return false;
}
index++;
startIteratorForGroup(checklist[index] & ~FPortalGroupArray::FLAT);
switch (nextflags)
{
case FPortalGroupArray::UPPER:
portalflags = FFCF_NOFLOOR;
break;
case FPortalGroupArray::LOWER:
portalflags = FFCF_NOCEILING;
break;
default:
portalflags = 0;
}
return Next(item);
}
//===========================================================================
//
// start iterating a new group
//
//===========================================================================
void FMultiBlockThingsIterator::startIteratorForGroup(int group)
{
fixedvec2 offset = Displacements(basegroup, group);
offset.x += checkpoint.x;
offset.y += checkpoint.y;
bbox.setBox(offset.x, offset.y, checkpoint.z);
blockIterator.init(bbox);
}
//===========================================================================
//
// Resets the iterator
//
//===========================================================================
void FMultiBlockThingsIterator::Reset()
{
index = -1;
portalflags = 0;
startIteratorForGroup(basegroup);
}
//===========================================================================
//
// FPathTraverse :: Intercepts

View file

@ -3,6 +3,7 @@
#include "r_defs.h"
#include "doomstat.h"
#include "m_bbox.h"
extern int validcount;
@ -98,6 +99,8 @@ struct FLineOpening
sector_t *topsec;
FTextureID ceilingpic;
FTextureID floorpic;
secplane_t frontfloorplane;
secplane_t backfloorplane;
int floorterrain;
bool touchmidtex;
bool abovemidtex;
@ -108,8 +111,76 @@ void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fi
class FBoundingBox;
struct polyblock_t;
//============================================================================
//
// This is a dynamic array which holds its first MAX_STATIC entries in normal
// variables to avoid constant allocations which this would otherwise
// require.
//
// When collecting touched portal groups the normal cases are either
// no portals == one group or
// two portals = two groups
//
// Anything with more can happen but far less infrequently, so this
// organization helps avoiding the overhead from heap allocations
// in the vast majority of situations.
//
//============================================================================
struct FPortalGroupArray
{
enum
{
LOWER = 0x4000,
UPPER = 0x8000,
FLAT = 0xc000,
};
enum
{
MAX_STATIC = 4
};
FPortalGroupArray()
{
varused = 0;
inited = false;
}
void Clear()
{
data.Clear();
varused = 0;
inited = false;
}
void Add(DWORD num)
{
if (varused < MAX_STATIC) entry[varused++] = (WORD)num;
else data.Push((WORD)num);
}
unsigned Size()
{
return varused + data.Size();
}
DWORD operator[](unsigned index)
{
return index < MAX_STATIC ? entry[index] : data[index - MAX_STATIC];
}
bool inited;
private:
WORD entry[MAX_STATIC];
BYTE varused;
TArray<WORD> data;
};
class FBlockLinesIterator
{
friend class FMultiBlockLinesIterator;
int minx, maxx;
int miny, maxy;
@ -120,6 +191,8 @@ class FBlockLinesIterator
void StartBlock(int x, int y);
FBlockLinesIterator() {}
void init(const FBoundingBox &box);
public:
FBlockLinesIterator(int minx, int miny, int maxx, int maxy, bool keepvalidcount = false);
FBlockLinesIterator(const FBoundingBox &box);
@ -127,6 +200,52 @@ public:
void Reset() { StartBlock(minx, miny); }
};
class FMultiBlockLinesIterator
{
FPortalGroupArray &checklist;
fixedvec3 checkpoint;
fixedvec2 offset;
short basegroup;
short portalflags;
short index;
bool continueup;
bool continuedown;
FBlockLinesIterator blockIterator;
FBoundingBox bbox;
bool GoUp(fixed_t x, fixed_t y);
bool GoDown(fixed_t x, fixed_t y);
void startIteratorForGroup(int group);
public:
struct CheckResult
{
line_t *line;
fixedvec3 position;
int portalflags;
};
FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1);
FMultiBlockLinesIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius);
bool Next(CheckResult *item);
void Reset();
// for stopping group traversal through portals. Only the calling code can decide whether this is needed so this needs to be set from the outside.
void StopUp()
{
continueup = false;
}
void StopDown()
{
continuedown = false;
}
const FBoundingBox &Box() const
{
return bbox;
}
};
class FBlockThingsIterator
{
int minx, maxx;
@ -158,14 +277,52 @@ class FBlockThingsIterator
FBlockThingsIterator();
friend class FPathTraverse;
friend class FMultiBlockThingsIterator;
public:
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
FBlockThingsIterator(const FBoundingBox &box);
FBlockThingsIterator(const FBoundingBox &box)
{
init(box);
}
void init(const FBoundingBox &box);
AActor *Next(bool centeronly = false);
void Reset() { StartBlock(minx, miny); }
};
class FMultiBlockThingsIterator
{
FPortalGroupArray &checklist;
fixedvec3 checkpoint;
short basegroup;
short portalflags;
short index;
FBlockThingsIterator blockIterator;
FBoundingBox bbox;
void startIteratorForGroup(int group);
public:
struct CheckResult
{
AActor *thing;
fixedvec3 position;
int portalflags;
};
FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, fixed_t checkradius = -1, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, fixed_t checkx, fixed_t checky, fixed_t checkz, fixed_t checkh, fixed_t checkradius, bool ignorerestricted = false);
bool Next(CheckResult *item);
void Reset();
const FBoundingBox &Box() const
{
return bbox;
}
};
class FPathTraverse
{
static TArray<intercept_t> intercepts;

View file

@ -2187,7 +2187,7 @@ explode:
if (tm.ceilingline &&
tm.ceilingline->backsector &&
tm.ceilingline->backsector->GetTexture(sector_t::ceiling) == skyflatnum &&
mo->Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(mo))
mo->Z() >= tm.ceilingline->backsector->ceilingplane.ZatPoint(mo->PosRelative(tm.ceilingline)))
{
// Hack to prevent missiles exploding against the sky.
// Does not handle sky floors.
@ -3559,7 +3559,7 @@ void AActor::Tick ()
for (node = touching_sectorlist; node; node = node->m_tnext)
{
const sector_t *sec = node->m_sector;
sector_t *sec = node->m_sector;
fixed_t scrollx, scrolly;
if (level.Scrolls != NULL)
@ -3641,7 +3641,8 @@ void AActor::Tick ()
{
continue;
}
height = sec->floorplane.ZatPoint (this);
fixedvec3 pos = PosRelative(sec);
height = sec->floorplane.ZatPoint (pos);
if (Z() > height)
{
if (heightsec == NULL)
@ -3649,7 +3650,7 @@ void AActor::Tick ()
continue;
}
waterheight = heightsec->floorplane.ZatPoint (this);
waterheight = heightsec->floorplane.ZatPoint (pos);
if (waterheight > height && Z() >= waterheight)
{
continue;
@ -3690,7 +3691,7 @@ void AActor::Tick ()
floorplane = P_FindFloorPlane(floorsector, X(), Y(), floorz);
if (floorplane.c < STEEPSLOPE &&
floorplane.ZatPoint (this) <= floorz)
floorplane.ZatPoint (PosRelative(floorsector)) <= floorz)
{
const msecnode_t *node;
bool dopush = true;
@ -3702,7 +3703,7 @@ void AActor::Tick ()
const sector_t *sec = node->m_sector;
if (sec->floorplane.c >= STEEPSLOPE)
{
if (floorplane.ZatPoint (this) >= Z() - MaxStepHeight)
if (floorplane.ZatPoint (PosRelative(node->m_sector)) >= Z() - MaxStepHeight)
{
dopush = false;
break;
@ -4478,15 +4479,16 @@ void AActor::AdjustFloorClip ()
const msecnode_t *m;
// possibly standing on a 3D-floor
if (Sector->e->XFloor.ffloors.Size() && Z()>Sector->floorplane.ZatPoint(this)) floorclip=0;
if (Sector->e->XFloor.ffloors.Size() && Z() > Sector->floorplane.ZatPoint(this)) floorclip = 0;
// [RH] clip based on shallowest floor player is standing on
// If the sector has a deep water effect, then let that effect
// do the floorclipping instead of the terrain type.
for (m = touching_sectorlist; m; m = m->m_tnext)
{
fixedvec3 pos = PosRelative(m->m_sector);
sector_t *hsec = m->m_sector->GetHeightSec();
if (hsec == NULL && m->m_sector->floorplane.ZatPoint (this) == Z())
if (hsec == NULL && m->m_sector->floorplane.ZatPoint (pos) == Z())
{
fixed_t clip = Terrains[m->m_sector->GetTerrain(sector_t::floor)].FootClip;
if (clip < shallowestclip)
@ -5356,7 +5358,7 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
}
if (bloodtype >= 1)
{
P_DrawSplash2 (40, x, y, z, R_PointToAngle2 (x, y, originator->X(), originator->Y()), 2, bloodcolor);
P_DrawSplash2 (40, x, y, z, 0u - originator->AngleTo(x, y), 2, bloodcolor);
}
}
@ -5396,7 +5398,7 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
}
if (bloodtype >= 1)
{
P_DrawSplash2 (100, x, y, z, R_PointToAngle2 (0, 0, originator->X() - x, originator->Y() - y), 2, bloodcolor);
P_DrawSplash2 (100, x, y, z, 0u - originator->AngleTo(x, y), 2, bloodcolor);
}
}
@ -5524,9 +5526,9 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
fixed_t planez = rover->top.plane->ZatPoint(x, y);
if (z > planez - FRACUNIT / 2 && z < planez + FRACUNIT / 2) // allow minor imprecisions
{
if (rover->flags & (FF_SOLID | FF_SWIMMABLE))
if (rover->flags & (FF_SOLID | FF_SWIMMABLE))
{
terrainnum = rover->model->GetTerrain(rover->top.isceiling);
terrainnum = rover->model->GetTerrain(rover->top.isceiling);
goto foundone;
}
}
@ -5639,9 +5641,11 @@ bool P_HitFloor (AActor *thing)
return false;
// don't splash if landing on the edge above water/lava/etc....
fixedvec3 pos;
for (m = thing->touching_sectorlist; m; m = m->m_tnext)
{
if (thing->Z() == m->m_sector->floorplane.ZatPoint(thing))
pos = thing->PosRelative(m->m_sector);
if (thing->Z() == m->m_sector->floorplane.ZatPoint(pos.x, pos.y))
{
break;
}
@ -5653,9 +5657,9 @@ bool P_HitFloor (AActor *thing)
if (!(rover->flags & FF_EXISTS)) continue;
if (rover->flags & (FF_SOLID|FF_SWIMMABLE))
{
if (rover->top.plane->ZatPoint(thing) == thing->Z())
if (rover->top.plane->ZatPoint(pos.x, pos.y) == thing->Z())
{
return P_HitWater (thing, m->m_sector);
return P_HitWater (thing, m->m_sector, pos.x, pos.y, pos.z);
}
}
}
@ -5665,7 +5669,7 @@ bool P_HitFloor (AActor *thing)
return false;
}
return P_HitWater (thing, m->m_sector);
return P_HitWater (thing, m->m_sector, pos.x, pos.y, pos.z);
}
//---------------------------------------------------------------------------
@ -5678,12 +5682,15 @@ bool P_HitFloor (AActor *thing)
void P_CheckSplash(AActor *self, fixed_t distance)
{
if (self->Z() <= self->floorz + (distance<<FRACBITS) && self->floorsector == self->Sector && self->Sector->GetHeightSec() == NULL)
sector_t *floorsec;
self->Sector->LowestFloorAt(self, &floorsec);
if (self->Z() <= self->floorz + (distance<<FRACBITS) && self->floorsector == floorsec && self->Sector->GetHeightSec() == NULL && floorsec->heightsec == NULL)
{
// Explosion splashes never alert monsters. This is because A_Explode has
// a separate parameter for that so this would get in the way of proper
// behavior.
P_HitWater (self, self->Sector, self->X(), self->Y(), self->floorz, false, false);
fixedvec3 pos = self->PosRelative(floorsec);
P_HitWater (self, floorsec, pos.x, pos.y, self->floorz, false, false);
}
}

View file

@ -55,7 +55,6 @@
#include "p_lnspec.h"
#include "p_acs.h"
#include "p_terrain.h"
#include "portal.h"
static void CopyPlayer (player_t *dst, player_t *src, const char *name);
static void ReadOnePlayer (FArchive &arc, bool skipload);

View file

@ -31,6 +31,7 @@
#include "farchive.h"
#include "r_utility.h"
#include "a_sharedglobal.h"
#include "p_local.h"
#include "r_data/colormaps.h"
@ -805,7 +806,7 @@ int sector_t::GetCeilingLight () const
ASkyViewpoint *sector_t::GetSkyBox(int which)
{
if (SkyBoxes[which] != NULL) return SkyBoxes[which];
if (SkyBoxes[which] != NULL) return barrier_cast<ASkyViewpoint*>(SkyBoxes[which]);
if (MoreFlags & (SECF_NOFLOORSKYBOX << which)) return NULL;
return level.DefaultSkybox;
}
@ -873,7 +874,7 @@ int sector_t::GetTerrain(int pos) const
void sector_t::CheckPortalPlane(int plane)
{
ASkyViewpoint *portal = SkyBoxes[plane];
AActor *portal = SkyBoxes[plane];
if (!portal || portal->special1 != SKYBOX_LINKEDPORTAL) return;
fixed_t planeh = planes[plane].TexZ;
@ -882,7 +883,140 @@ void sector_t::CheckPortalPlane(int plane)
planes[plane].Flags = (planes[plane].Flags & ~PLANEF_OBSTRUCTED) | obstructed;
}
//===========================================================================
//
// Finds the highest ceiling at the given position, all portals considered
//
//===========================================================================
fixed_t sector_t::HighestCeilingAt(fixed_t x, fixed_t y, sector_t **resultsec)
{
sector_t *check = this;
fixed_t planeheight = FIXED_MIN;
// Continue until we find a blocking portal or a portal below where we actually are.
while (!check->PortalBlocksMovement(ceiling) && planeheight < check->SkyBoxes[ceiling]->threshold)
{
FDisplacement &disp = check->CeilingDisplacement();
x += disp.pos.x;
y += disp.pos.y;
planeheight = check->SkyBoxes[ceiling]->threshold;
check = P_PointInSector(x, y);
}
if (resultsec) *resultsec = check;
return check->ceilingplane.ZatPoint(x, y);
}
//===========================================================================
//
// Finds the lowest floor at the given position, all portals considered
//
//===========================================================================
fixed_t sector_t::LowestFloorAt(fixed_t x, fixed_t y, sector_t **resultsec)
{
sector_t *check = this;
fixed_t planeheight = FIXED_MAX;
// Continue until we find a blocking portal or a portal above where we actually are.
while (!check->PortalBlocksMovement(floor) && planeheight > check->SkyBoxes[floor]->threshold)
{
FDisplacement &disp = check->FloorDisplacement();
x += disp.pos.x;
y += disp.pos.y;
planeheight = check->SkyBoxes[floor]->threshold;
check = P_PointInSector(x, y);
}
if (resultsec) *resultsec = check;
return check->floorplane.ZatPoint(x, y);
}
fixed_t sector_t::NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flags, sector_t **resultsec, F3DFloor **resultffloor)
{
sector_t *sec = this;
fixed_t planeheight = FIXED_MIN;
while (true)
{
// Looking through planes from bottom to top
for (int i = sec->e->XFloor.ffloors.Size() - 1; i >= 0; --i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
fixed_t ffz = ff->bottom.plane->ZatPoint(x, y);
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID) && z <= ffz)
{ // This floor is above our eyes.
if (resultsec) *resultsec = sec;
if (resultffloor) *resultffloor = ff;
return ffz;
}
}
if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(ceiling) || planeheight >= sec->SkyBoxes[ceiling]->threshold)
{ // Use sector's floor
if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec;
return sec->ceilingplane.ZatPoint(x, y);
}
else
{
FDisplacement &disp = sec->CeilingDisplacement();
x += disp.pos.x;
y += disp.pos.y;
planeheight = sec->SkyBoxes[ceiling]->threshold;
sec = P_PointInSector(x, y);
}
}
}
fixed_t sector_t::NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags, fixed_t steph, sector_t **resultsec, F3DFloor **resultffloor)
{
sector_t *sec = this;
fixed_t planeheight = FIXED_MAX;
while (true)
{
// Looking through planes from top to bottom
unsigned numff = sec->e->XFloor.ffloors.Size();
for (unsigned i = 0; i < numff; ++i)
{
F3DFloor *ff = sec->e->XFloor.ffloors[i];
fixed_t ffz = ff->top.plane->ZatPoint(x, y);
fixed_t ffb = ff->bottom.plane->ZatPoint(x, y);
// either with feet above the 3D floor or feet with less than 'stepheight' map units inside
if ((ff->flags & (FF_EXISTS | FF_SOLID)) == (FF_EXISTS | FF_SOLID))
{
if (z >= ffz || (!(flags & FFCF_3DRESTRICT) && (ffb < z && ffz < z + steph)))
{ // This floor is beneath our feet.
if (resultsec) *resultsec = sec;
if (resultffloor) *resultffloor = ff;
return ffz;
}
}
}
if ((flags & FFCF_NOPORTALS) || sec->PortalBlocksMovement(sector_t::floor) || planeheight <= sec->SkyBoxes[floor]->threshold)
{ // Use sector's floor
if (resultffloor) *resultffloor = NULL;
if (resultsec) *resultsec = sec;
return sec->floorplane.ZatPoint(x, y);
}
else
{
FDisplacement &disp = sec->FloorDisplacement();
x += disp.pos.x;
y += disp.pos.y;
planeheight = sec->SkyBoxes[floor]->threshold;
sec = P_PointInSector(x, y);
}
}
}
//===========================================================================
//
//
//
//===========================================================================
FArchive &operator<< (FArchive &arc, secspecial_t &p)
{
@ -908,6 +1042,11 @@ FArchive &operator<< (FArchive &arc, secspecial_t &p)
}
//===========================================================================
//
//
//
//===========================================================================
bool secplane_t::CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const
{
@ -1085,4 +1224,3 @@ int side_t::GetLightLevel (bool foggy, int baselight, bool is3dlight, int *pfake
}
return baselight;
}

View file

@ -69,7 +69,6 @@
#include "po_man.h"
#include "r_renderer.h"
#include "r_data/colormaps.h"
#include "portal.h"
#include "p_blockmap.h"
#include "r_utility.h"
#include "p_spec.h"
@ -3393,12 +3392,12 @@ void P_FreeLevelData ()
FPolyObj::ClearAllSubsectorLinks(); // can't be done as part of the polyobj deletion process.
SN_StopAllSequences ();
DThinker::DestroyAllThinkers ();
P_ClearPortals();
tagManager.Clear();
level.total_monsters = level.total_items = level.total_secrets =
level.killed_monsters = level.found_items = level.found_secrets =
wminfo.maxfrags = 0;
linePortals.Clear();
FBehavior::StaticUnloadModules ();
if (vertexes != NULL)
{

View file

@ -67,7 +67,6 @@
#include "c_dispatch.h"
#include "r_sky.h"
#include "d_player.h"
#include "portal.h"
#include "p_maputl.h"
#include "p_blockmap.h"
#ifndef NO_EDATA
@ -440,7 +439,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
{
// Falling, not all the way down yet?
sector = player->mo->Sector;
if (player->mo->Z() != sector->floorplane.ZatPoint(player->mo)
if (player->mo->Z() != sector->LowestFloorAt(player->mo)
&& !player->mo->waterlevel)
{
return;
@ -480,7 +479,7 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
}
if (sector->Flags & SECF_DMGTERRAINFX)
{
P_HitWater(player->mo, sector, INT_MIN, INT_MIN, INT_MIN, false, true, true);
P_HitWater(player->mo, player->mo->Sector, INT_MIN, INT_MIN, INT_MIN, false, true, true);
}
}
}
@ -919,10 +918,11 @@ static void SetupFloorPortal (AStackPoint *point)
{
NActorIterator it (NAME_LowerStackLookOnly, point->tid);
sector_t *Sector = point->Sector;
Sector->SkyBoxes[sector_t::floor] = static_cast<ASkyViewpoint*>(it.Next());
if (Sector->SkyBoxes[sector_t::floor] != NULL && Sector->SkyBoxes[sector_t::floor]->bAlways)
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
Sector->SkyBoxes[sector_t::floor] = skyv;
if (skyv != NULL && skyv->bAlways)
{
Sector->SkyBoxes[sector_t::floor]->Mate = point;
skyv->Mate = point;
if (Sector->GetAlpha(sector_t::floor) == OPAQUE)
Sector->SetAlpha(sector_t::floor, Scale (point->args[0], OPAQUE, 255));
}
@ -932,12 +932,13 @@ static void SetupCeilingPortal (AStackPoint *point)
{
NActorIterator it (NAME_UpperStackLookOnly, point->tid);
sector_t *Sector = point->Sector;
Sector->SkyBoxes[sector_t::ceiling] = static_cast<ASkyViewpoint*>(it.Next());
if (Sector->SkyBoxes[sector_t::ceiling] != NULL && Sector->SkyBoxes[sector_t::ceiling]->bAlways)
ASkyViewpoint *skyv = static_cast<ASkyViewpoint*>(it.Next());
Sector->SkyBoxes[sector_t::ceiling] = skyv;
if (skyv != NULL && skyv->bAlways)
{
Sector->SkyBoxes[sector_t::ceiling]->Mate = point;
skyv->Mate = point;
if (Sector->GetAlpha(sector_t::ceiling) == OPAQUE)
Sector->SetAlpha(sector_t::ceiling, Scale (point->args[0], OPAQUE, 255));
Sector->SetAlpha(sector_t::ceiling, Scale(point->args[0], OPAQUE, 255));
}
}
@ -968,7 +969,7 @@ static void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_
// plane: 0=floor, 1=ceiling, 2=both
if (plane > 0)
{
if (sector->SkyBoxes[sector_t::ceiling] == NULL || !sector->SkyBoxes[sector_t::ceiling]->bAlways)
if (sector->SkyBoxes[sector_t::ceiling] == NULL || !barrier_cast<ASkyViewpoint*>(sector->SkyBoxes[sector_t::ceiling])->bAlways)
{
sector->SkyBoxes[sector_t::ceiling] = portal;
if (sector->GetAlpha(sector_t::ceiling) == OPAQUE)
@ -979,7 +980,7 @@ static void SetPortal(sector_t *sector, int plane, ASkyViewpoint *portal, fixed_
}
if (plane == 2 || plane == 0)
{
if (sector->SkyBoxes[sector_t::floor] == NULL || !sector->SkyBoxes[sector_t::floor]->bAlways)
if (sector->SkyBoxes[sector_t::floor] == NULL || !barrier_cast<ASkyViewpoint*>(sector->SkyBoxes[sector_t::floor])->bAlways)
{
sector->SkyBoxes[sector_t::floor] = portal;
}
@ -2299,6 +2300,7 @@ void DPusher::Tick ()
continue;
sector_t *hsec = sec->GetHeightSec();
fixedvec3 pos = thing->PosRelative(sec);
if (m_Type == p_wind)
{
if (hsec == NULL)
@ -2316,7 +2318,7 @@ void DPusher::Tick ()
}
else // special water sector
{
ht = hsec->floorplane.ZatPoint(thing);
ht = hsec->floorplane.ZatPoint(pos);
if (thing->Z() > ht) // above ground
{
xspeed = m_Xmag; // full force
@ -2345,7 +2347,7 @@ void DPusher::Tick ()
{ // special water sector
floor = &hsec->floorplane;
}
if (thing->Z() > floor->ZatPoint(thing))
if (thing->Z() > floor->ZatPoint(pos))
{ // above ground
xspeed = yspeed = 0; // no force
}

View file

@ -47,7 +47,6 @@
#include "r_data/colormaps.h"
#include "w_wad.h"
#include "p_tags.h"
#include "portal.h"
#include "p_terrain.h"
//===========================================================================

View file

@ -769,10 +769,9 @@ void APlayerPawn::PostBeginPlay()
// Voodoo dolls: restore original floorz/ceilingz logic
if (player == NULL || player->mo != this)
{
dropoffz = floorz = Sector->floorplane.ZatPoint(this);
ceilingz = Sector->ceilingplane.ZatPoint(this);
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS);
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS|FFCF_NOPORTALS);
SetZ(floorz);
P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS);
}
else
{

View file

@ -37,7 +37,6 @@
*/
#include "portal.h"
#include "p_local.h"
#include "p_lnspec.h"
#include "r_bsp.h"
@ -360,6 +359,20 @@ bool P_ChangePortal(line_t *ln, int thisid, int destid)
return res;
}
//============================================================================
//
// clears all portal dat for a new level start
//
//============================================================================
void P_ClearPortals()
{
Displacements.Create(1);
linePortals.Clear();
linkedPortals.Clear();
}
//============================================================================
//
// Calculate the intersection between two lines.
@ -774,13 +787,13 @@ static void AddDisplacementForPortal(AStackPoint *portal)
FDisplacement & disp = Displacements(thisgroup, othergroup);
if (!disp.isSet)
{
disp.x = portal->scaleX;
disp.y = portal->scaleY;
disp.pos.x = portal->scaleX;
disp.pos.y = portal->scaleY;
disp.isSet = true;
}
else
{
if (disp.x != portal->scaleX || disp.y != portal->scaleY)
if (disp.pos.x != portal->scaleX || disp.pos.y != portal->scaleY)
{
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;
@ -810,13 +823,13 @@ static void AddDisplacementForPortal(FLinePortal *portal)
FDisplacement & disp = Displacements(thisgroup, othergroup);
if (!disp.isSet)
{
disp.x = portal->mXDisplacement;
disp.y = portal->mYDisplacement;
disp.pos.x = portal->mXDisplacement;
disp.pos.y = portal->mYDisplacement;
disp.isSet = true;
}
else
{
if (disp.x != portal->mXDisplacement || disp.y != portal->mYDisplacement)
if (disp.pos.x != portal->mXDisplacement || disp.pos.y != portal->mYDisplacement)
{
Printf("Portal between lines %d and %d has displacement mismatch\n", int(portal->mOrigin - lines), int(portal->mDestination - lines));
portal->mType = linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
@ -857,15 +870,14 @@ static bool ConnectGroups()
FDisplacement &dispxz = Displacements(x, z);
if (dispxz.isSet)
{
if (dispxy.x + dispyz.x != dispxz.x || dispxy.y + dispyz.y != dispxz.y)
if (dispxy.pos.x + dispyz.pos.x != dispxz.pos.x || dispxy.pos.y + dispyz.pos.y != dispxz.pos.y)
{
bogus = true;
}
}
else
{
dispxz.x = dispxy.x + dispyz.x;
dispxz.y = dispxy.y + dispyz.y;
dispxz.pos = dispxy.pos + dispyz.pos;
dispxz.isSet = true;
dispxz.indirect = indirect;
changed = true;
@ -920,13 +932,15 @@ void P_CreateLinkedPortals()
}
if (orgs.Size() == 0)
{
// Create the 0->0 translation which is always needed.
Displacements.Create(1);
return;
}
for (int i = 0; i < numsectors; i++)
{
for (int j = 0; j < 2; j++)
{
ASkyViewpoint *box = sectors[i].SkyBoxes[j];
AActor *box = sectors[i].SkyBoxes[j];
if (box != NULL && box->special1 == SKYBOX_LINKEDPORTAL)
{
secplane_t &plane = j == 0 ? sectors[i].floorplane : sectors[i].ceilingplane;
@ -962,7 +976,7 @@ void P_CreateLinkedPortals()
{
for (int j = 0; j < 2; j++)
{
ASkyViewpoint *box = sectors[i].SkyBoxes[j];
ASkyViewpoint *box = barrier_cast<ASkyViewpoint*>(sectors[i].SkyBoxes[j]);
if (box != NULL)
{
if (box->special1 == SKYBOX_LINKEDPORTAL && sectors[i].PortalGroup == 0)
@ -995,7 +1009,7 @@ void P_CreateLinkedPortals()
FDisplacement &dispxy = Displacements(x, y);
FDisplacement &dispyx = Displacements(y, x);
if (dispxy.isSet && dispyx.isSet &&
(dispxy.x != -dispyx.x || dispxy.y != -dispyx.y))
(dispxy.pos.x != -dispyx.pos.x || dispxy.pos.y != -dispyx.pos.y))
{
int sec1 = -1, sec2 = -1;
for (int i = 0; i < numsectors && (sec1 == -1 || sec2 == -1); i++)
@ -1054,7 +1068,7 @@ void P_CreateLinkedPortals()
//
//============================================================================
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupArray &out)
bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t upperz, fixed_t checkradius, FPortalGroupArray &out)
{
// Keep this temporary work stuff static. This function can never be called recursively
// and this would have to be reallocated for each call otherwise.
@ -1062,19 +1076,19 @@ bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortal
static TArray<FLinePortal*> foundPortals;
bool retval = false;
out.inited = true;
if (linkedPortals.Size() == 0)
{
// If there are no portals, all sectors are in group 0.
out.Add(0);
return false;
}
processMask.setSize(linkedPortals.Size());
processMask.clear();
foundPortals.Clear();
int thisgroup = actor->Sector->PortalGroup;
int thisgroup = startgroup;
processMask.setBit(thisgroup);
out.Add(thisgroup);
//out.Add(thisgroup);
for (unsigned i = 0; i < linkedPortals.Size(); i++)
{
@ -1083,7 +1097,7 @@ bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortal
FDisplacement &disp = Displacements(thisgroup, othergroup);
if (!disp.isSet) continue; // no connection.
FBoundingBox box(newx + disp.x, newy + disp.y, actor->radius);
FBoundingBox box(position.x + disp.pos.x, position.y + disp.pos.y, checkradius);
if (box.Right() <= ld->bbox[BOXLEFT]
|| box.Left() >= ld->bbox[BOXRIGHT]
@ -1111,27 +1125,27 @@ bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortal
}
}
}
sector_t *sec = P_PointInSector(newx, newy);
sector_t *sec = P_PointInSector(position.x, position.y);
sector_t *wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && actor->Top() > wsec->SkyBoxes[sector_t::ceiling]->threshold)
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->SkyBoxes[sector_t::ceiling]->threshold)
{
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
fixed_t dx = newx + disp.x;
fixed_t dy = newx + disp.y;
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
fixed_t dx = position.x + disp.pos.x;
fixed_t dy = position.y + disp.pos.y;
processMask.setBit(othersec->PortalGroup);
out.Add(othersec->PortalGroup);
out.Add(othersec->PortalGroup|FPortalGroupArray::UPPER);
wsec = P_PointInSector(dx, dy); // get upper sector at the exact spot we want to check and repeat
retval = true;
}
wsec = sec;
while (!wsec->PortalBlocksMovement(sector_t::floor) && actor->Z() < wsec->SkyBoxes[sector_t::floor]->threshold)
while (!wsec->PortalBlocksMovement(sector_t::floor) && position.z < wsec->SkyBoxes[sector_t::floor]->threshold)
{
sector_t *othersec = wsec->SkyBoxes[sector_t::ceiling]->Sector;
FDisplacement &disp = Displacements(actor->Sector->PortalGroup, othersec->PortalGroup);
fixed_t dx = newx + disp.x;
fixed_t dy = newx + disp.y;
processMask.setBit(othersec->PortalGroup);
sector_t *othersec = wsec->SkyBoxes[sector_t::floor]->Sector;
FDisplacement &disp = Displacements(startgroup, othersec->PortalGroup);
fixed_t dx = position.x + disp.pos.x;
fixed_t dy = position.y + disp.pos.y;
processMask.setBit(othersec->PortalGroup|FPortalGroupArray::LOWER);
out.Add(othersec->PortalGroup);
wsec = P_PointInSector(dx, dy); // get lower sector at the exact spot we want to check and repeat
retval = true;
@ -1153,7 +1167,7 @@ CCMD(dumplinktable)
for (int y = 1; y < Displacements.size; y++)
{
FDisplacement &disp = Displacements(x, y);
Printf("%c%c(%6d, %6d)", TEXTCOLOR_ESCAPE, 'C' + disp.indirect, disp.x >> FRACBITS, disp.y >> FRACBITS);
Printf("%c%c(%6d, %6d)", TEXTCOLOR_ESCAPE, 'C' + disp.indirect, disp.pos.x >> FRACBITS, disp.pos.y >> FRACBITS);
}
Printf("\n");
}

View file

@ -3,11 +3,7 @@
#include "basictypes.h"
#include "v_video.h"
#include "r_defs.h"
#include "actor.h"
#include "p_local.h"
#include "m_bbox.h"
#include "a_sharedglobal.h"
struct FPortalGroupArray;
//============================================================================
@ -30,9 +26,14 @@ struct FPortalGroupArray;
struct FDisplacement
{
fixed_t x, y;
fixedvec2 pos;
bool isSet;
BYTE indirect; // just for illustration.
operator fixedvec2()
{
return pos;
}
};
struct FDisplacementTable
@ -40,6 +41,11 @@ struct FDisplacementTable
TArray<FDisplacement> data;
int size;
FDisplacementTable()
{
Create(1);
}
void Create(int numgroups)
{
data.Resize(numgroups*numgroups);
@ -49,6 +55,7 @@ struct FDisplacementTable
FDisplacement &operator()(int x, int y)
{
if (x == y) return data[0]; // shortcut for the most common case
return data[x + size*y];
}
};
@ -116,11 +123,12 @@ struct FLinePortal
extern TArray<FLinePortal> linePortals;
void P_ClearPortals();
void P_SpawnLinePortal(line_t* line);
void P_FinalizePortals();
bool P_ChangePortal(line_t *ln, int thisid, int destid);
void P_CreateLinkedPortals();
bool P_CollectConnectedGroups(AActor *actor, fixed_t newx, fixed_t newy, FPortalGroupArray &out);
bool P_CollectConnectedGroups(int startgroup, const fixedvec3 &position, fixed_t upperz, fixed_t checkradius, FPortalGroupArray &out);
void P_CollectLinkedPortals();
inline int P_NumPortalGroups()
{
@ -175,51 +183,4 @@ public:
/* new code */
fixed_t P_PointLineDistance(line_t* line, fixed_t x, fixed_t y);
//============================================================================
//
// some wrappers around the portal data.
//
//============================================================================
// returns true if the portal is crossable by actors
inline bool line_t::isLinePortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_PASSABLE);
}
// returns true if the portal needs to be handled by the renderer
inline bool line_t::isVisualPortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_VISIBLE);
}
inline line_t *line_t::getPortalDestination() const
{
return portalindex >= linePortals.Size() ? (line_t*)NULL : linePortals[portalindex].mDestination;
}
inline int line_t::getPortalAlignment() const
{
return portalindex >= linePortals.Size() ? 0 : linePortals[portalindex].mAlign;
}
inline bool sector_t::PortalBlocksView(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool sector_t::PortalBlocksMovement(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
inline bool sector_t::PortalBlocksSound(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
#endif

View file

@ -56,7 +56,6 @@
#include "r_sky.h"
#include "po_man.h"
#include "r_data/colormaps.h"
#include "portal.h"
seg_t* curline;
side_t* sidedef;

View file

@ -25,7 +25,7 @@
#include "tarray.h"
#include <stddef.h>
#include "portal.h"
#include "r_defs.h"
// The 3072 below is just an arbitrary value picked to avoid
// drawing lines the player is too close to that would overflow

View file

@ -55,6 +55,7 @@ enum
};
extern size_t MaxDrawSegs;
struct FDisplacement;
enum
@ -242,6 +243,16 @@ struct secplane_t
return ic < 0 ? d : -d;
}
fixed_t ZatPoint(const fixedvec2 &spot) const
{
return FixedMul(ic, -d - DMulScale16(a, spot.x, b, spot.y));
}
fixed_t ZatPoint(const fixedvec3 &spot) const
{
return FixedMul(ic, -d - DMulScale16(a, spot.x, b, spot.y));
}
// Returns the value of z at (x,y)
fixed_t ZatPoint (fixed_t x, fixed_t y) const
{
@ -334,6 +345,21 @@ struct secplane_t
return -TMulScale16 (a, v->x, b, v->y, z, c);
}
void SetAtHeight(fixed_t height, int ceiling)
{
a = b = 0;
if (ceiling)
{
c = ic = -FRACUNIT;
d = height;
}
else
{
c = ic = FRACUNIT;
d = -height;
}
}
bool CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const;
};
@ -702,17 +728,6 @@ struct sector_t
return pos == floor? floorplane:ceilingplane;
}
fixed_t HighestCeiling(AActor *a) const
{
return ceilingplane.ZatPoint(a);
}
fixed_t LowestFloor(AActor *a) const
{
return floorplane.ZatPoint(a);
}
bool isSecret() const
{
return !!(Flags & SECF_SECRET);
@ -739,9 +754,41 @@ struct sector_t
Flags &= ~SECF_SPECIALFLAGS;
}
bool PortalBlocksView(int plane);
bool PortalBlocksMovement(int plane);
bool PortalBlocksSound(int plane);
bool PortalBlocksView(int plane)
{
if (SkyBoxes[plane] == NULL) return true;
if (SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return false;
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
bool PortalBlocksSight(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NORENDER | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
bool PortalBlocksMovement(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_NOPASS | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
bool PortalBlocksSound(int plane)
{
if (SkyBoxes[plane] == NULL || SkyBoxes[plane]->special1 != SKYBOX_LINKEDPORTAL) return true;
return !!(planes[plane].Flags & (PLANEF_BLOCKSOUND | PLANEF_DISABLED | PLANEF_OBSTRUCTED));
}
// These may only be called if the portal has been validated
FDisplacement &FloorDisplacement()
{
return Displacements(PortalGroup, SkyBoxes[sector_t::floor]->Sector->PortalGroup);
}
FDisplacement &CeilingDisplacement()
{
return Displacements(PortalGroup, SkyBoxes[sector_t::ceiling]->Sector->PortalGroup);
}
int GetTerrain(int pos) const;
@ -750,6 +797,32 @@ struct sector_t
void SetSpecial(const secspecial_t *spec);
bool PlaneMoving(int pos);
// Portal-aware height calculation
fixed_t HighestCeilingAt(fixed_t x, fixed_t y, sector_t **resultsec = NULL);
fixed_t LowestFloorAt(fixed_t x, fixed_t y, sector_t **resultsec = NULL);
fixed_t HighestCeilingAt(AActor *a, sector_t **resultsec = NULL)
{
return HighestCeilingAt(a->X(), a->Y(), resultsec);
}
fixed_t LowestFloorAt(AActor *a, sector_t **resultsec = NULL)
{
return LowestFloorAt(a->X(), a->Y(), resultsec);
}
fixed_t NextHighestCeilingAt(fixed_t x, fixed_t y, fixed_t z, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL);
fixed_t NextLowestFloorAt(fixed_t x, fixed_t y, fixed_t z, int flags = 0, fixed_t steph = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL);
fixed_t NextHighestCeilingAt(AActor *a, fixed_t z, int flags = 0, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL)
{
return NextHighestCeilingAt(a->X(), a->Y(), z, flags, resultsec, resultffloor);
}
fixed_t NextLowestFloorAt(AActor *a, fixed_t z, int flags, sector_t **resultsec = NULL, F3DFloor **resultffloor = NULL)
{
return NextLowestFloorAt(a->X(), a->Y(), z, flags, a->MaxStepHeight, resultsec, resultffloor);
}
// Member variables
fixed_t CenterFloor () const { return floorplane.ZatPoint (soundorg[0], soundorg[1]); }
@ -834,7 +907,7 @@ struct sector_t
// [RH] The sky box to render for this sector. NULL means use a
// regular sky.
TObjPtr<ASkyViewpoint> SkyBoxes[2];
TObjPtr<AActor> SkyBoxes[2];
int PortalGroup;
int sectornum; // for comparing sector copies
@ -1015,11 +1088,26 @@ struct line_t
unsigned portalindex;
// returns true if the portal is crossable by actors
bool isLinePortal() const;
bool isLinePortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_PASSABLE);
}
// returns true if the portal needs to be handled by the renderer
bool isVisualPortal() const;
line_t *getPortalDestination() const;
int getPortalAlignment() const;
bool isVisualPortal() const
{
return portalindex >= linePortals.Size() ? false : !!(linePortals[portalindex].mFlags & PORTF_VISIBLE);
}
line_t *getPortalDestination() const
{
return portalindex >= linePortals.Size() ? (line_t*)NULL : linePortals[portalindex].mDestination;
}
int getPortalAlignment() const
{
return portalindex >= linePortals.Size() ? 0 : linePortals[portalindex].mAlign;
}
};
// phares 3/14/98
@ -1165,5 +1253,24 @@ inline sector_t *P_PointInSector(fixed_t x, fixed_t y)
return P_PointInSubsector(x, y)->sector;
}
inline fixedvec3 AActor::PosRelative(AActor *other) const
{
return __pos + Displacements(Sector->PortalGroup, other->Sector->PortalGroup);
}
inline fixedvec3 AActor::PosRelative(sector_t *sec) const
{
return __pos + Displacements(Sector->PortalGroup, sec->PortalGroup);
}
inline fixedvec3 AActor::PosRelative(line_t *line) const
{
return __pos + Displacements(Sector->PortalGroup, line->frontsector->PortalGroup);
}
inline fixedvec3 PosRelative(const fixedvec3 &pos, line_t *line, sector_t *refsec = NULL)
{
return pos + Displacements(refsec->PortalGroup, line->frontsector->PortalGroup);
}
#endif

View file

@ -58,7 +58,6 @@
#include "v_font.h"
#include "r_data/colormaps.h"
#include "farchive.h"
#include "portal.h"
// MACROS ------------------------------------------------------------------

View file

@ -58,7 +58,6 @@
#include "r_3dfloors.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "portal.h"
#ifdef _MSC_VER
#pragma warning(disable:4244)

View file

@ -52,7 +52,6 @@
#include "r_3dfloors.h"
#include "v_palette.h"
#include "r_data/colormaps.h"
#include "portal.h"
#define WALLYREPEAT 8

View file

@ -34,7 +34,6 @@
#include "doomstat.h"
#include "m_random.h"
#include "m_bbox.h"
#include "portal.h"
#include "r_sky.h"
#include "st_stuff.h"
#include "c_cvars.h"
@ -57,7 +56,7 @@
#include "farchive.h"
#include "r_utility.h"
#include "d_player.h"
#include "portal.h"
#include "p_local.h"
// EXTERNAL DATA DECLARATIONS ----------------------------------------------