mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-23 04:22:34 +00:00
Merge remote-tracking branch 'remotes/origin/portal'
This commit is contained in:
commit
49bfe717ce
36 changed files with 1298 additions and 696 deletions
29
src/actor.h
29
src/actor.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);// ^
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ()
|
||||
{
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "g_level.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "gi.h"
|
||||
#include "portal.h"
|
||||
#include "p_spec.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
725
src/p_map.cpp
725
src/p_map.cpp
File diff suppressed because it is too large
Load diff
312
src/p_maputl.cpp
312
src/p_maputl.cpp
|
@ -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
|
||||
|
|
159
src/p_maputl.h
159
src/p_maputl.h
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include "r_data/colormaps.h"
|
||||
#include "w_wad.h"
|
||||
#include "p_tags.h"
|
||||
#include "portal.h"
|
||||
#include "p_terrain.h"
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
67
src/portal.h
67
src/portal.h
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
145
src/r_defs.h
145
src/r_defs.h
|
@ -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
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
#include "v_font.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "farchive.h"
|
||||
#include "portal.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "r_3dfloors.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "portal.h"
|
||||
|
||||
#define WALLYREPEAT 8
|
||||
|
||||
|
|
|
@ -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 ----------------------------------------------
|
||||
|
|
Loading…
Reference in a new issue