- portal.cpp is almost free of access to the global level variable.

This commit is contained in:
Christoph Oelckers 2019-01-06 17:06:40 +01:00
parent 9b1870f71f
commit 7f3caaf0ff
18 changed files with 238 additions and 213 deletions

View file

@ -910,7 +910,7 @@ public:
}
else
{
return P_GetOffsetPosition(X(), Y(), dx, dy);
return P_GetOffsetPosition(__GetLevel(), X(), Y(), dx, dy);
}
}
@ -923,7 +923,7 @@ public:
}
else
{
DVector2 v = P_GetOffsetPosition(X(), Y(), dx, dy);
DVector2 v = P_GetOffsetPosition(__GetLevel(), X(), Y(), dx, dy);
return DVector3(v, atz);
}
}
@ -936,7 +936,7 @@ public:
}
else
{
return P_GetOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin());
return P_GetOffsetPosition(__GetLevel(), X(), Y(), length*angle.Cos(), length*angle.Sin());
}
}
@ -948,7 +948,7 @@ public:
}
else
{
DVector2 v = P_GetOffsetPosition(X(), Y(), dx, dy);
DVector2 v = P_GetOffsetPosition(__GetLevel(), X(), Y(), dx, dy);
return DVector3(v, Z() + dz);
}
}
@ -966,7 +966,7 @@ public:
}
else
{
DVector2 v = P_GetOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin());
DVector2 v = P_GetOffsetPosition(__GetLevel(), X(), Y(), length*angle.Cos(), length*angle.Sin());
return DVector3(v, Z() + dz);
}
}

View file

@ -64,6 +64,7 @@
#include "events.h"
#include "i_time.h"
#include "vm.h"
#include "actorinlines.h"
EXTERN_CVAR (Int, disableautosave)
EXTERN_CVAR (Int, autosavecount)

View file

@ -2048,7 +2048,7 @@ void FLevelLocals::SetMusicVolume(float f)
//==========================================================================
int IsPointInMap(double x, double y, double z)
int IsPointInMap(FLevelLocals *Level, double x, double y, double z)
{
subsector_t *subsector = R_PointInSubsector(FLOAT2FIXED(x), FLOAT2FIXED(y));
if (!subsector) return false;
@ -2076,15 +2076,15 @@ int IsPointInMap(double x, double y, double z)
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, IsPointInMap, IsPointInMap)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
ACTION_RETURN_BOOL(IsPointInMap(x, y, z));
ACTION_RETURN_BOOL(IsPointInMap(self, x, y, z));
}
template <typename T>
inline T VecDiff(const T& v1, const T& v2)
inline T VecDiff(FLevelLocals *Level, const T& v1, const T& v2)
{
T result = v2 - v1;
@ -2095,7 +2095,7 @@ inline T VecDiff(const T& v1, const T& v2)
if (nullptr != sec1 && nullptr != sec2)
{
result += level.Displacements.getOffset(sec2->PortalGroup, sec1->PortalGroup);
result += Level->Displacements.getOffset(sec2->PortalGroup, sec1->PortalGroup);
}
}
@ -2104,29 +2104,29 @@ inline T VecDiff(const T& v1, const T& v2)
DEFINE_ACTION_FUNCTION(FLevelLocals, Vec2Diff)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x1);
PARAM_FLOAT(y1);
PARAM_FLOAT(x2);
PARAM_FLOAT(y2);
ACTION_RETURN_VEC2(VecDiff(DVector2(x1, y1), DVector2(x2, y2)));
ACTION_RETURN_VEC2(VecDiff(self, DVector2(x1, y1), DVector2(x2, y2)));
}
DEFINE_ACTION_FUNCTION(FLevelLocals, Vec3Diff)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x1);
PARAM_FLOAT(y1);
PARAM_FLOAT(z1);
PARAM_FLOAT(x2);
PARAM_FLOAT(y2);
PARAM_FLOAT(z2);
ACTION_RETURN_VEC3(VecDiff(DVector3(x1, y1, z1), DVector3(x2, y2, z2)));
ACTION_RETURN_VEC3(VecDiff(self, DVector3(x1, y1, z1), DVector3(x2, y2, z2)));
}
DEFINE_ACTION_FUNCTION(FLevelLocals, SphericalCoords)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(viewpointX);
PARAM_FLOAT(viewpointY);
PARAM_FLOAT(viewpointZ);
@ -2139,7 +2139,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, SphericalCoords)
DVector3 viewpoint(viewpointX, viewpointY, viewpointZ);
DVector3 target(targetX, targetY, targetZ);
auto vecTo = absolute ? target - viewpoint : VecDiff(viewpoint, target);
auto vecTo = absolute ? target - viewpoint : VecDiff(self, viewpoint, target);
ACTION_RETURN_VEC3(DVector3(
deltaangle(vecTo.Angle(), viewYaw).Degrees,

View file

@ -3235,5 +3235,5 @@ void MapLoader::LoadLevel(MapData *map, const char *lumpname, int position)
if (reloop) LoopSidedefs(false);
PO_Init(); // Initialize the polyobjs
if (!Level->IsReentering())
P_FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
P_FinalizePortals(Level); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them.
}

View file

@ -3702,7 +3702,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RadiusGive)
{
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
double mid = self->Center();
FMultiBlockThingsIterator it(check, self->X(), self->Y(), mid-distance, mid+distance, distance, false, self->Sector);
FMultiBlockThingsIterator it(check, self->__GetLevel(), self->X(), self->Y(), mid-distance, mid+distance, distance, false, self->Sector);
FMultiBlockThingsIterator::CheckResult cres;
while ((it.Next(&cres)) && ((unlimited) || (given < limit)))

View file

@ -46,6 +46,7 @@
#include "d_player.h"
#include "r_utility.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
CVAR (Int, cl_rockettrails, 1, CVAR_ARCHIVE);
@ -264,7 +265,7 @@ void P_ThinkParticles ()
}
// Handle crossing a line portal
DVector2 newxy = P_GetOffsetPosition(particle->Pos.X, particle->Pos.Y, particle->Vel.X, particle->Vel.Y);
DVector2 newxy = P_GetOffsetPosition(&level, particle->Pos.X, particle->Pos.Y, particle->Vel.X, particle->Vel.Y);
particle->Pos.X = newxy.X;
particle->Pos.Y = newxy.Y;
particle->Pos.Z += particle->Vel.Z;

View file

@ -2627,7 +2627,7 @@ bool P_CheckForResurrection(AActor *self, bool usevilestates)
FPortalGroupArray check(FPortalGroupArray::PGA_Full3d);
FMultiBlockThingsIterator it(check, viletry.X, viletry.Y, self->Z() - 64, self->Top() + 64, 32., false, NULL);
FMultiBlockThingsIterator it(check, self->__GetLevel(), viletry.X, viletry.Y, self->Z() - 64, self->Top() + 64, 32., false, NULL);
FMultiBlockThingsIterator::CheckResult cres;
while (it.Next(&cres))
{

View file

@ -421,7 +421,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi
sector_t *sector = P_PointInSector(pos);
FPortalGroupArray grouplist;
FMultiBlockLinesIterator mit(grouplist, pos.X, pos.Y, pos.Z, thing->Height, thing->radius, sector);
FMultiBlockLinesIterator mit(grouplist, thing->__GetLevel(), pos.X, pos.Y, pos.Z, thing->Height, thing->radius, sector);
FMultiBlockLinesIterator::CheckResult cres;
while (mit.Next(&cres))
@ -432,7 +432,7 @@ bool P_TeleportMove(AActor* thing, const DVector3 &pos, bool telefrag, bool modi
if (tmf.touchmidtex) tmf.dropoffz = tmf.floorz;
FMultiBlockThingsIterator mit2(grouplist, pos.X, pos.Y, pos.Z, thing->Height, thing->radius, false, sector);
FMultiBlockThingsIterator mit2(grouplist, thing->__GetLevel(), pos.X, pos.Y, pos.Z, thing->Height, thing->radius, false, sector);
FMultiBlockThingsIterator::CheckResult cres2;
while (mit2.Next(&cres2))
@ -1750,7 +1750,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
FBoundingBox box(pos.X, pos.Y, thing->radius);
FPortalGroupArray pcheck;
FMultiBlockThingsIterator it2(pcheck, pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, false, newsec);
FMultiBlockThingsIterator it2(pcheck, thing->__GetLevel(), pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, false, newsec);
FMultiBlockThingsIterator::CheckResult tcres;
while ((it2.Next(&tcres)))
@ -1822,7 +1822,7 @@ bool P_CheckPosition(AActor *thing, const DVector2 &pos, FCheckPosition &tm, boo
return (thing->BlockingMobj = thingblocker) == NULL;
FMultiBlockLinesIterator it(pcheck, pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, newsec);
FMultiBlockLinesIterator it(pcheck, thing->__GetLevel(), pos.X, pos.Y, thing->Z(), thing->Height, thing->radius, newsec);
FMultiBlockLinesIterator::CheckResult lcres;
double thingdropoffz = tm.floorz;
@ -4539,7 +4539,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
// position a bit closer for puffs
if (nointeract || trace.HitType != TRACE_HitWall || ((trace.Line->special != Line_Horizon) || spawnSky))
{
DVector2 pos = P_GetOffsetPosition(trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4);
DVector2 pos = P_GetOffsetPosition(t1->__GetLevel(), trace.HitPos.X, trace.HitPos.Y, -trace.HitVector.X * 4, -trace.HitVector.Y * 4);
puff = P_SpawnPuff(t1, pufftype, DVector3(pos, trace.HitPos.Z - trace.HitVector.Z * 4), trace.SrcAngleFromTarget,
trace.SrcAngleFromTarget - 90, 0, puffFlags);
puff->radius = 1/65536.;
@ -4590,7 +4590,7 @@ AActor *P_LineAttack(AActor *t1, DAngle angle, double distance,
// position a bit closer for puffs/blood if using compatibility mode.
if (i_compatflags & COMPATF_HITSCAN)
{
DVector2 ofs = P_GetOffsetPosition(bleedpos.X, bleedpos.Y, -10 * trace.HitVector.X, -10 * trace.HitVector.Y);
DVector2 ofs = P_GetOffsetPosition(t1->__GetLevel(), bleedpos.X, bleedpos.Y, -10 * trace.HitVector.X, -10 * trace.HitVector.Y);
bleedpos.X = ofs.X;
bleedpos.Y = ofs.Y;
bleedpos.Z -= -10 * trace.HitVector.Z;
@ -5101,7 +5101,7 @@ static ETraceStatus ProcessRailHit(FTraceResults &res, void *userdata)
newhit.HitAngle = res.SrcAngleFromTarget;
if (i_compatflags & COMPATF_HITSCAN)
{
DVector2 ofs = P_GetOffsetPosition(newhit.HitPos.X, newhit.HitPos.Y, -10 * res.HitVector.X, -10 * res.HitVector.Y);
DVector2 ofs = P_GetOffsetPosition(res.Actor->__GetLevel(), newhit.HitPos.X, newhit.HitPos.Y, -10 * res.HitVector.X, -10 * res.HitVector.Y);
newhit.HitPos.X = ofs.X;
newhit.HitPos.Y = ofs.Y;
newhit.HitPos.Z -= -10 * res.HitVector.Z;
@ -5836,7 +5836,7 @@ int P_RadiusAttack(AActor *bombspot, AActor *bombsource, int bombdamage, int bom
fulldamagedistance = clamp<int>(fulldamagedistance, 0, bombdistance - 1);
FPortalGroupArray grouplist(FPortalGroupArray::PGA_Full3d);
FMultiBlockThingsIterator it(grouplist, bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistance, bombspot->Height + bombdistance*2, bombdistance, false, bombspot->Sector);
FMultiBlockThingsIterator it(grouplist, bombspot->__GetLevel(), bombspot->X(), bombspot->Y(), bombspot->Z() - bombdistance, bombspot->Height + bombdistance*2, bombdistance, false, bombspot->Sector);
FMultiBlockThingsIterator::CheckResult cres;
if (flags & RADF_SOURCEISSPOT)

View file

@ -504,7 +504,7 @@ void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sec
{
FPortalGroupArray check;
P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check);
P_CollectConnectedGroups(__GetLevel(), Sector->PortalGroup, Pos(), Top(), radius, check);
BlockNode = NULL;
FBlockNode **alink = &this->BlockNode;
@ -714,21 +714,21 @@ FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, AAc
: checklist(check)
{
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
if (!check.inited) P_CollectConnectedGroups(origin->__GetLevel(), origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.Z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
startsector = origin->Sector;
Reset();
}
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, sector_t *newsec)
FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, FLevelLocals *Level, double checkx, double checky, double checkz, double checkh, double checkradius, sector_t *newsec)
: checklist(check)
{
checkpoint = { checkx, checky, checkz };
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
startsector = newsec;
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
if (!check.inited) P_CollectConnectedGroups(Level, basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.Z = checkradius;
Reset();
}
@ -1056,13 +1056,13 @@ FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, A
: checklist(check)
{
checkpoint = origin->Pos();
if (!check.inited) P_CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
if (!check.inited) P_CollectConnectedGroups(origin->__GetLevel(), origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist);
checkpoint.Z = checkradius == -1? origin->radius : checkradius;
basegroup = origin->Sector->PortalGroup;
Reset();
}
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, FLevelLocals *Level, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
: checklist(check)
{
checkpoint.X = checkx;
@ -1070,7 +1070,7 @@ FMultiBlockThingsIterator::FMultiBlockThingsIterator(FPortalGroupArray &check, d
checkpoint.Z = checkz;
if (newsec == NULL) newsec = P_PointInSector(checkx, checky);
basegroup = newsec->PortalGroup;
if (!check.inited) P_CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist);
if (!check.inited) P_CollectConnectedGroups(Level, basegroup, checkpoint, checkz + checkh, checkradius, checklist);
checkpoint.Z = checkradius;
Reset();
}

View file

@ -254,7 +254,7 @@ public:
};
FMultiBlockLinesIterator(FPortalGroupArray &check, AActor *origin, double checkradius = -1);
FMultiBlockLinesIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, sector_t *newsec);
FMultiBlockLinesIterator(FPortalGroupArray &check, FLevelLocals *Level, double checkx, double checky, double checkz, double checkh, double checkradius, sector_t *newsec);
bool Next(CheckResult *item);
void Reset();
@ -342,7 +342,7 @@ public:
};
FMultiBlockThingsIterator(FPortalGroupArray &check, AActor *origin, double checkradius = -1, bool ignorerestricted = false);
FMultiBlockThingsIterator(FPortalGroupArray &check, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec);
FMultiBlockThingsIterator(FPortalGroupArray &check, FLevelLocals *Level, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec);
bool Next(CheckResult *item);
void Reset();
const FBoundingBox &Box() const

View file

@ -1001,7 +1001,7 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
arc("zones", level.Zones);
arc("lineportals", level.linePortals);
arc("sectorportals", level.sectorPortals);
if (arc.isReading()) P_FinalizePortals();
if (arc.isReading()) P_FinalizePortals(&level);
// [ZZ] serialize health groups
P_SerializeHealthGroups(arc);

View file

@ -42,6 +42,7 @@
#include "r_utility.h"
#include "p_spec.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
#define FUDGEFACTOR 10
@ -186,7 +187,7 @@ bool P_Teleport (AActor *thing, DVector3 pos, DAngle angle, int flags)
if (!predicting)
{
DVector2 vector = angle.ToVector(20);
DVector2 fogpos = P_GetOffsetPosition(pos.X, pos.Y, vector.X, vector.Y);
DVector2 fogpos = P_GetOffsetPosition(thing->__GetLevel(), pos.X, pos.Y, vector.X, vector.Y);
P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true);
}

View file

@ -49,6 +49,7 @@
#include "p_maputl.h"
#include "p_spec.h"
#include "g_levellocals.h"
#include "actorinlines.h"
#include "vm.h"
// simulation recurions maximum
@ -102,34 +103,34 @@ struct FPortalBits
//
//============================================================================
static void BuildBlockmap()
static void BuildBlockmap(FLevelLocals *Level)
{
auto bmapwidth = level.blockmap.bmapwidth;
auto bmapheight = level.blockmap.bmapheight;
auto bmapwidth = Level->blockmap.bmapwidth;
auto bmapheight = Level->blockmap.bmapheight;
level.PortalBlockmap.Clear();
level.PortalBlockmap.Create(bmapwidth, bmapheight);
Level->PortalBlockmap.Clear();
Level->PortalBlockmap.Create(bmapwidth, bmapheight);
for (int y = 0; y < bmapheight; y++)
{
for (int x = 0; x < bmapwidth; x++)
{
int *list = level.blockmap.GetLines(x, y);
FPortalBlock &block = level.PortalBlockmap(x, y);
int *list = Level->blockmap.GetLines(x, y);
FPortalBlock &block = Level->PortalBlockmap(x, y);
while (*list != -1)
{
line_t *ld = &level.lines[*list++];
line_t *ld = &Level->lines[*list++];
FLinePortal *port = ld->getPortal();
if (port && port->mType != PORTT_VISUAL)
{
level.PortalBlockmap.containsLines = true;
Level->PortalBlockmap.containsLines = true;
block.portallines.Push(ld);
block.neighborContainsLines = true;
if (ld->getPortal()->mType == PORTT_LINKED) block.containsLinkedPortals = true;
if (x > 0) level.PortalBlockmap(x - 1, y).neighborContainsLines = true;
if (y > 0) level.PortalBlockmap(x, y - 1).neighborContainsLines = true;
if (x < level.PortalBlockmap.dx - 1) level.PortalBlockmap(x + 1, y).neighborContainsLines = true;
if (y < level.PortalBlockmap.dy - 1) level.PortalBlockmap(x, y + 1).neighborContainsLines = true;
if (x > 0) Level->PortalBlockmap(x - 1, y).neighborContainsLines = true;
if (y > 0) Level->PortalBlockmap(x, y - 1).neighborContainsLines = true;
if (x < Level->PortalBlockmap.dx - 1) Level->PortalBlockmap(x + 1, y).neighborContainsLines = true;
if (y < Level->PortalBlockmap.dy - 1) Level->PortalBlockmap(x, y + 1).neighborContainsLines = true;
}
else
{
@ -140,7 +141,7 @@ static void BuildBlockmap()
yes |= ld->backsector->PortalIsLinked(sector_t::ceiling) || ld->backsector->PortalIsLinked(sector_t::floor);
}
block.containsLinkedPortals |= yes;
level.PortalBlockmap.hasLinkedSectorPortals |= yes;
Level->PortalBlockmap.hasLinkedSectorPortals |= yes;
}
}
@ -158,9 +159,10 @@ static void BuildBlockmap()
void FLinePortalTraverse::AddLineIntercepts(int bx, int by)
{
if (by < 0 || by >= level.PortalBlockmap.dy || bx < 0 || bx >= level.PortalBlockmap.dx) return;
auto Level = &level;
if (by < 0 || by >= Level->PortalBlockmap.dy || bx < 0 || bx >= Level->PortalBlockmap.dx) return;
FPortalBlock &block = level.PortalBlockmap(bx, by);
FPortalBlock &block = Level->PortalBlockmap(bx, by);
for (unsigned i = 0; i<block.portallines.Size(); i++)
{
@ -208,13 +210,14 @@ static line_t *FindDestination(line_t *src, int tag)
if (tag)
{
int lineno = -1;
auto Level = src->frontsector->Level;
FLineIdIterator it(tag);
while ((lineno = it.Next()) >= 0)
{
if (&level.lines[lineno] != src)
if (&Level->lines[lineno] != src)
{
return &level.lines[lineno];
return &Level->lines[lineno];
}
}
}
@ -267,6 +270,8 @@ static void SetRotation(FLinePortal *port)
void P_SpawnLinePortal(line_t* line)
{
auto Level = line->frontsector->Level;
// portal destination is special argument #0
line_t* dst = nullptr;
@ -274,8 +279,8 @@ void P_SpawnLinePortal(line_t* line)
{
dst = FindDestination(line, line->args[0]);
line->portalindex = level.linePortals.Reserve(1);
FLinePortal *port = &level.linePortals.Last();
line->portalindex = Level->linePortals.Reserve(1);
FLinePortal *port = &Level->linePortals.Last();
memset(port, 0, sizeof(FLinePortal));
port->mOrigin = line;
@ -307,12 +312,12 @@ void P_SpawnLinePortal(line_t* line)
int mytag = tagManager.GetFirstLineID(line);
for (auto &ln : level.lines)
for (auto &ln : Level->lines)
{
if (tagManager.GetFirstLineID(&ln) == mytag && ln.args[0] == 1 && ln.special == Line_SetPortal)
{
line->portalindex = level.linePortals.Reserve(1);
FLinePortal *port = &level.linePortals.Last();
line->portalindex = Level->linePortals.Reserve(1);
FLinePortal *port = &Level->linePortals.Last();
memset(port, 0, sizeof(FLinePortal));
port->mOrigin = line;
@ -322,8 +327,8 @@ void P_SpawnLinePortal(line_t* line)
port->mDefFlags = PORTF_TYPEINTERACTIVE;
// we need to create the backlink here, too.
ln.portalindex = level.linePortals.Reserve(1);
port = &level.linePortals.Last();
ln.portalindex = Level->linePortals.Reserve(1);
port = &Level->linePortals.Last();
memset(port, 0, sizeof(FLinePortal));
port->mOrigin = &ln;
@ -349,6 +354,7 @@ void P_SpawnLinePortal(line_t* line)
void P_UpdatePortal(FLinePortal *port)
{
auto Level = port->mOrigin->frontsector->Level;
if (port->mType != PORTT_VISUAL && port->mOrigin->backsector == nullptr && !(port->mOrigin->sidedef[0]->Flags & WALLF_POLYOBJ))
{
Printf(TEXTCOLOR_RED "Warning: Traversable portals must have a back-sector and empty space behind them (or be on a polyobject)! Changing line %d to visual-portal!\n", port->mOrigin->Index());
@ -378,7 +384,7 @@ void P_UpdatePortal(FLinePortal *port)
port->mFlags = port->mDefFlags;
if (port->mType == PORTT_LINKED)
{
if (level.linePortals[port->mDestination->portalindex].mType != PORTT_LINKED)
if (Level->linePortals[port->mDestination->portalindex].mType != PORTT_LINKED)
{
port->mType = PORTT_INTERACTIVE; // linked portals must be two-way.
}
@ -400,15 +406,15 @@ void P_UpdatePortal(FLinePortal *port)
//
//============================================================================
void P_CollectLinkedPortals()
void P_CollectLinkedPortals(FLevelLocals *Level)
{
level.linkedPortals.Clear();
for (unsigned i = 0; i < level.linePortals.Size(); i++)
Level->linkedPortals.Clear();
for (unsigned i = 0; i < Level->linePortals.Size(); i++)
{
FLinePortal * port = &level.linePortals[i];
FLinePortal * port = &Level->linePortals[i];
if (port->mType == PORTT_LINKED)
{
level.linkedPortals.Push(port);
Level->linkedPortals.Push(port);
}
}
}
@ -419,16 +425,16 @@ void P_CollectLinkedPortals()
//
//============================================================================
void P_FinalizePortals()
void P_FinalizePortals(FLevelLocals *Level)
{
for (unsigned i = 0; i < level.linePortals.Size(); i++)
for (unsigned i = 0; i < Level->linePortals.Size(); i++)
{
FLinePortal * port = &level.linePortals[i];
FLinePortal * port = &Level->linePortals[i];
P_UpdatePortal(port);
}
P_CollectLinkedPortals();
BuildBlockmap();
P_CreateLinkedPortals();
P_CollectLinkedPortals(Level);
BuildBlockmap(Level);
P_CreateLinkedPortals(Level);
}
//============================================================================
@ -439,8 +445,9 @@ void P_FinalizePortals()
static bool ChangePortalLine(line_t *line, int destid)
{
if (line->portalindex >= level.linePortals.Size()) return false;
FLinePortal *port = &level.linePortals[line->portalindex];
auto Level = line->frontsector->Level;
if (line->portalindex >= Level->linePortals.Size()) return false;
FLinePortal *port = &Level->linePortals[line->portalindex];
if (port->mType == PORTT_LINKED) return false; // linked portals cannot be changed.
if (destid == 0) port->mDestination = nullptr;
port->mDestination = FindDestination(line, destid);
@ -450,7 +457,7 @@ static bool ChangePortalLine(line_t *line, int destid)
}
else if (port->mType == PORTT_INTERACTIVE)
{
FLinePortal *portd = port->mDestination->portalindex < level.linePortals.Size()? &level.linePortals[port->mDestination->portalindex] : nullptr;
FLinePortal *portd = port->mDestination->portalindex < Level->linePortals.Size()? &Level->linePortals[port->mDestination->portalindex] : nullptr;
if (portd != nullptr && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line)
{
// this is a 2-way interactive portal
@ -482,12 +489,13 @@ bool P_ChangePortal(line_t *ln, int thisid, int destid)
{
int lineno;
auto Level = ln->frontsector->Level;
if (thisid == 0) return ChangePortalLine(ln, destid);
FLineIdIterator it(thisid);
bool res = false;
while ((lineno = it.Next()) >= 0)
{
res |= ChangePortalLine(&level.lines[lineno], destid);
res |= ChangePortalLine(&Level->lines[lineno], destid);
}
return res;
}
@ -645,16 +653,17 @@ void P_TranslatePortalZ(line_t* src, double& z)
unsigned P_GetSkyboxPortal(AActor *actor)
{
if (actor == nullptr) return 1; // this means a regular sky.
for (unsigned i = 0;i<level.sectorPortals.Size();i++)
auto Level = actor->__GetLevel();
for (unsigned i = 0;i<Level->sectorPortals.Size();i++)
{
if (level.sectorPortals[i].mSkybox == actor) return i;
if (Level->sectorPortals[i].mSkybox == actor) return i;
}
unsigned i = level.sectorPortals.Reserve(1);
memset(&level.sectorPortals[i], 0, sizeof(level.sectorPortals[i]));
level.sectorPortals[i].mType = PORTS_SKYVIEWPOINT;
level.sectorPortals[i].mFlags = actor->GetClass()->IsDescendantOf("SkyCamCompat") ? 0 : PORTSF_SKYFLATONLY;
level.sectorPortals[i].mSkybox = actor;
level.sectorPortals[i].mDestination = actor->Sector;
unsigned i = Level->sectorPortals.Reserve(1);
memset(&Level->sectorPortals[i], 0, sizeof(Level->sectorPortals[i]));
Level->sectorPortals[i].mType = PORTS_SKYVIEWPOINT;
Level->sectorPortals[i].mFlags = actor->GetClass()->IsDescendantOf("SkyCamCompat") ? 0 : PORTSF_SKYFLATONLY;
Level->sectorPortals[i].mSkybox = actor;
Level->sectorPortals[i].mDestination = actor->Sector;
return i;
}
@ -674,14 +683,15 @@ DEFINE_ACTION_FUNCTION(FSectorPortal, GetSkyboxPortal)
unsigned P_GetPortal(int type, int plane, sector_t *from, sector_t *to, const DVector2 &displacement)
{
unsigned i = level.sectorPortals.Reserve(1);
memset(&level.sectorPortals[i], 0, sizeof(level.sectorPortals[i]));
level.sectorPortals[i].mType = type;
level.sectorPortals[i].mPlane = plane;
level.sectorPortals[i].mOrigin = from;
level.sectorPortals[i].mDestination = to;
level.sectorPortals[i].mDisplacement = displacement;
level.sectorPortals[i].mPlaneZ = type == PORTS_LINKEDPORTAL? from->GetPlaneTexZ(plane) : FLT_MAX;
auto Level = from->Level;
unsigned i = Level->sectorPortals.Reserve(1);
memset(&Level->sectorPortals[i], 0, sizeof(Level->sectorPortals[i]));
Level->sectorPortals[i].mType = type;
Level->sectorPortals[i].mPlane = plane;
Level->sectorPortals[i].mOrigin = from;
Level->sectorPortals[i].mDestination = to;
Level->sectorPortals[i].mDisplacement = displacement;
Level->sectorPortals[i].mPlaneZ = type == PORTS_LINKEDPORTAL? from->GetPlaneTexZ(plane) : FLT_MAX;
return i;
}
@ -695,14 +705,15 @@ unsigned P_GetPortal(int type, int plane, sector_t *from, sector_t *to, const DV
unsigned P_GetStackPortal(AActor *point, int plane)
{
unsigned i = level.sectorPortals.Reserve(1);
memset(&level.sectorPortals[i], 0, sizeof(level.sectorPortals[i]));
level.sectorPortals[i].mType = PORTS_STACKEDSECTORTHING;
level.sectorPortals[i].mPlane = plane;
level.sectorPortals[i].mOrigin = point->target->Sector;
level.sectorPortals[i].mDestination = point->Sector;
level.sectorPortals[i].mPlaneZ = FLT_MAX;
level.sectorPortals[i].mSkybox = point;
auto Level = point->__GetLevel();
unsigned i = Level->sectorPortals.Reserve(1);
memset(&Level->sectorPortals[i], 0, sizeof(Level->sectorPortals[i]));
Level->sectorPortals[i].mType = PORTS_STACKEDSECTORTHING;
Level->sectorPortals[i].mPlane = plane;
Level->sectorPortals[i].mOrigin = point->target->Sector;
Level->sectorPortals[i].mDestination = point->Sector;
Level->sectorPortals[i].mPlaneZ = FLT_MAX;
Level->sectorPortals[i].mSkybox = point;
return i;
}
@ -716,18 +727,18 @@ unsigned P_GetStackPortal(AActor *point, int plane)
//
//============================================================================
DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy)
DVector2 P_GetOffsetPosition(FLevelLocals *Level, double x, double y, double dx, double dy)
{
DVector2 dest(x + dx, y + dy);
if (level.PortalBlockmap.containsLines)
if (Level->PortalBlockmap.containsLines)
{
double actx = x, acty = y;
// Try some easily discoverable early-out first. If we know that the trace cannot possibly find a portal, this saves us from calling the traverser completely for vast parts of the map.
if (dx < 128 && dy < 128)
{
int blockx = level.blockmap.GetBlockX(actx);
int blocky = level.blockmap.GetBlockY(acty);
if (blockx < 0 || blocky < 0 || blockx >= level.PortalBlockmap.dx || blocky >= level.PortalBlockmap.dy || !level.PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
int blockx = Level->blockmap.GetBlockX(actx);
int blocky = Level->blockmap.GetBlockY(acty);
if (blockx < 0 || blocky < 0 || blockx >= Level->PortalBlockmap.dx || blocky >= Level->PortalBlockmap.dy || !Level->PortalBlockmap(blockx, blocky).neighborContainsLines) return dest;
}
bool repeat;
@ -777,11 +788,6 @@ DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy)
return dest;
}
static void GetOffsetPosition(double x, double y, double dx, double dy, DVector2 *result)
{
*result = P_GetOffsetPosition(x, y, dx, dy);
}
//============================================================================
//
// CollectSectors
@ -829,7 +835,7 @@ static bool CollectSectors(int groupid, sector_t *origin)
//
//============================================================================
static void AddDisplacementForPortal(FSectorPortal *portal)
static void AddDisplacementForPortal(FLevelLocals *Level, FSectorPortal *portal)
{
int thisgroup = portal->mOrigin->PortalGroup;
int othergroup = portal->mDestination->PortalGroup;
@ -839,14 +845,14 @@ static void AddDisplacementForPortal(FSectorPortal *portal)
portal->mType = PORTS_PORTAL;
return;
}
if (thisgroup <= 0 || thisgroup >= level.Displacements.size || othergroup <= 0 || othergroup >= level.Displacements.size)
if (thisgroup <= 0 || thisgroup >= Level->Displacements.size || othergroup <= 0 || othergroup >= Level->Displacements.size)
{
Printf("Portal between sectors %d and %d has invalid group and will be disabled\n", portal->mOrigin->sectornum, portal->mDestination->sectornum);
portal->mType = PORTS_PORTAL;
return;
}
FDisplacement & disp = level.Displacements(thisgroup, othergroup);
FDisplacement & disp = Level->Displacements(thisgroup, othergroup);
if (!disp.isSet)
{
disp.pos = portal->mDisplacement;
@ -864,24 +870,24 @@ static void AddDisplacementForPortal(FSectorPortal *portal)
}
static void AddDisplacementForPortal(FLinePortal *portal)
static void AddDisplacementForPortal(FLevelLocals *Level, FLinePortal *portal)
{
int thisgroup = portal->mOrigin->frontsector->PortalGroup;
int othergroup = portal->mDestination->frontsector->PortalGroup;
if (thisgroup == othergroup)
{
Printf("Portal between lines %d and %d has both sides in same group\n", portal->mOrigin->Index(), portal->mDestination->Index());
portal->mType = level.linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
portal->mType = Level->linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
return;
}
if (thisgroup <= 0 || thisgroup >= level.Displacements.size || othergroup <= 0 || othergroup >= level.Displacements.size)
if (thisgroup <= 0 || thisgroup >= Level->Displacements.size || othergroup <= 0 || othergroup >= Level->Displacements.size)
{
Printf("Portal between lines %d and %d has invalid group\n", portal->mOrigin->Index(), portal->mDestination->Index());
portal->mType = level.linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
portal->mType = Level->linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
return;
}
FDisplacement & disp = level.Displacements(thisgroup, othergroup);
FDisplacement & disp = Level->Displacements(thisgroup, othergroup);
if (!disp.isSet)
{
disp.pos = portal->mDisplacement;
@ -892,7 +898,7 @@ static void AddDisplacementForPortal(FLinePortal *portal)
if (disp.pos != portal->mDisplacement)
{
Printf("Portal between lines %d and %d has displacement mismatch\n", portal->mOrigin->Index(), portal->mDestination->Index());
portal->mType = level.linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
portal->mType = Level->linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT;
return;
}
}
@ -906,7 +912,7 @@ static void AddDisplacementForPortal(FLinePortal *portal)
//
//============================================================================
static bool ConnectGroups()
static bool ConnectGroups(FLevelLocals *Level)
{
// Now
uint8_t indirect = 1;
@ -915,19 +921,19 @@ static bool ConnectGroups()
do
{
changed = false;
for (int x = 1; x < level.Displacements.size; x++)
for (int x = 1; x < Level->Displacements.size; x++)
{
for (int y = 1; y < level.Displacements.size; y++)
for (int y = 1; y < Level->Displacements.size; y++)
{
FDisplacement &dispxy = level.Displacements(x, y);
FDisplacement &dispxy = Level->Displacements(x, y);
if (dispxy.isSet)
{
for (int z = 1; z < level.Displacements.size; z++)
for (int z = 1; z < Level->Displacements.size; z++)
{
FDisplacement &dispyz = level.Displacements(y, z);
FDisplacement &dispyz = Level->Displacements(y, z);
if (dispyz.isSet)
{
FDisplacement &dispxz = level.Displacements(x, z);
FDisplacement &dispxz = Level->Displacements(x, z);
if (dispxz.isSet)
{
if (dispxy.pos.X + dispyz.pos.X != dispxz.pos.X || dispxy.pos.Y + dispyz.pos.Y != dispxz.pos.Y)
@ -966,13 +972,13 @@ static bool ConnectGroups()
//
//============================================================================
void P_CreateLinkedPortals()
void P_CreateLinkedPortals(FLevelLocals *Level)
{
TArray<FSectorPortal *> orgs;
int id = 1;
bool bogus = false;
for(auto &s : level.sectorPortals)
for(auto &s : Level->sectorPortals)
{
if (s.mType == PORTS_LINKEDPORTAL)
{
@ -982,7 +988,7 @@ void P_CreateLinkedPortals()
id = 1;
if (orgs.Size() != 0)
{
for (auto &sec : level.sectors)
for (auto &sec : Level->sectors)
{
for (int j = 0; j < 2; j++)
{
@ -1006,27 +1012,27 @@ void P_CreateLinkedPortals()
if (CollectSectors(id, orgs[i]->mDestination)) id++;
}
}
for (unsigned i = 0; i < level.linePortals.Size(); i++)
for (unsigned i = 0; i < Level->linePortals.Size(); i++)
{
if (level.linePortals[i].mType == PORTT_LINKED)
if (Level->linePortals[i].mType == PORTT_LINKED)
{
if (level.linePortals[i].mDestination == nullptr)
if (Level->linePortals[i].mDestination == nullptr)
{
Printf("Linked portal on line %d is unconnected and will be disabled\n", level.linePortals[i].mOrigin->Index());
level.linePortals[i].mOrigin->portalindex = UINT_MAX;
level.linePortals[i].mType = PORTT_VISUAL;
Printf("Linked portal on line %d is unconnected and will be disabled\n", Level->linePortals[i].mOrigin->Index());
Level->linePortals[i].mOrigin->portalindex = UINT_MAX;
Level->linePortals[i].mType = PORTT_VISUAL;
}
else
{
if (CollectSectors(id, level.linePortals[i].mOrigin->frontsector)) id++;
if (CollectSectors(id, level.linePortals[i].mDestination->frontsector)) id++;
if (CollectSectors(id, Level->linePortals[i].mOrigin->frontsector)) id++;
if (CollectSectors(id, Level->linePortals[i].mDestination->frontsector)) id++;
}
}
}
level.Displacements.Create(id);
Level->Displacements.Create(id);
// Check for leftover sectors that connect to a portal
for (auto &sec : level.sectors)
for (auto &sec : Level->sectors)
{
for (int j = 0; j < 2; j++)
{
@ -1039,36 +1045,36 @@ void P_CreateLinkedPortals()
}
for (unsigned i = 0; i < orgs.Size(); i++)
{
AddDisplacementForPortal(orgs[i]);
AddDisplacementForPortal(Level, orgs[i]);
}
for (unsigned i = 0; i < level.linePortals.Size(); i++)
for (unsigned i = 0; i < Level->linePortals.Size(); i++)
{
if (level.linePortals[i].mType == PORTT_LINKED)
if (Level->linePortals[i].mType == PORTT_LINKED)
{
AddDisplacementForPortal(&level.linePortals[i]);
AddDisplacementForPortal(Level, &Level->linePortals[i]);
}
}
for (int x = 1; x < level.Displacements.size; x++)
for (int x = 1; x < Level->Displacements.size; x++)
{
for (int y = x + 1; y < level.Displacements.size; y++)
for (int y = x + 1; y < Level->Displacements.size; y++)
{
FDisplacement &dispxy = level.Displacements(x, y);
FDisplacement &dispyx = level.Displacements(y, x);
FDisplacement &dispxy = Level->Displacements(x, y);
FDisplacement &dispyx = Level->Displacements(y, x);
if (dispxy.isSet && dispyx.isSet &&
(dispxy.pos.X != -dispyx.pos.X || dispxy.pos.Y != -dispyx.pos.Y))
{
int sec1 = -1, sec2 = -1;
for (unsigned i = 0; i < level.sectors.Size() && (sec1 == -1 || sec2 == -1); i++)
for (unsigned i = 0; i < Level->sectors.Size() && (sec1 == -1 || sec2 == -1); i++)
{
if (sec1 == -1 && level.sectors[i].PortalGroup == x) sec1 = i;
if (sec2 == -1 && level.sectors[i].PortalGroup == y) sec2 = i;
if (sec1 == -1 && Level->sectors[i].PortalGroup == x) sec1 = i;
if (sec2 == -1 && Level->sectors[i].PortalGroup == y) sec2 = i;
}
Printf("Link offset mismatch between sectors %d and %d\n", sec1, sec2);
bogus = true;
}
// mark everything that connects to a one-sided line
for (auto &line : level.lines)
for (auto &line : Level->lines)
{
if (line.backsector == nullptr && line.frontsector->PortalGroup == 0)
{
@ -1076,7 +1082,7 @@ void P_CreateLinkedPortals()
}
}
// and now print a message for everything that still wasn't processed.
for (auto &sec : level.sectors)
for (auto &sec : Level->sectors)
{
if (sec.PortalGroup == 0)
{
@ -1086,19 +1092,19 @@ void P_CreateLinkedPortals()
}
}
}
bogus |= ConnectGroups();
bogus |= ConnectGroups(Level);
if (bogus)
{
// todo: disable all portals whose offsets do not match the associated groups
}
// reject would just get in the way when checking sight through portals.
if (level.Displacements.size > 1)
if (Level->Displacements.size > 1)
{
level.rejectmatrix.Reset();
Level->rejectmatrix.Reset();
}
// finally we must flag all planes which are obstructed by the sector's own ceiling or floor.
for (auto &sec : level.sectors)
for (auto &sec : Level->sectors)
{
sec.CheckPortalPlane(sector_t::floor);
sec.CheckPortalPlane(sector_t::ceiling);
@ -1134,7 +1140,7 @@ void P_CreateLinkedPortals()
if (sec.PortalIsLinked(sector_t::floor)) sec.planes[sector_t::floor].Flags |= PLANEF_LINKED;
if (sec.PortalIsLinked(sector_t::ceiling)) sec.planes[sector_t::ceiling].Flags |= PLANEF_LINKED;
}
if (level.linkedPortals.Size() > 0)
if (Level->linkedPortals.Size() > 0)
{
// We need to relink all actors that may touch a linked line portal
TThinkerIterator<AActor> it;
@ -1144,7 +1150,7 @@ void P_CreateLinkedPortals()
if (!(actor->flags & MF_NOBLOCKMAP))
{
FPortalGroupArray check(FPortalGroupArray::PGA_NoSectorPortals);
P_CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check);
P_CollectConnectedGroups(Level, actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check);
if (check.Size() > 0)
{
FLinkContext ctx;
@ -1164,7 +1170,7 @@ void P_CreateLinkedPortals()
//
//============================================================================
bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out)
bool P_CollectConnectedGroups(FLevelLocals *Level, int startgroup, const DVector3 &position, double upperz, double 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.
@ -1175,14 +1181,14 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
bool retval = false;
out.inited = true;
processMask.setSize(level.Displacements.size);
if (level.Displacements.size == 1)
processMask.setSize(Level->Displacements.size);
if (Level->Displacements.size == 1)
{
processMask.setBit(startgroup);
return false;
}
if (level.linkedPortals.Size() != 0)
if (Level->linkedPortals.Size() != 0)
{
processMask.clear();
foundPortals.Clear();
@ -1191,17 +1197,17 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
processMask.setBit(thisgroup);
//out.Add(thisgroup);
for (unsigned i = 0; i < level.linkedPortals.Size(); i++)
for (unsigned i = 0; i < Level->linkedPortals.Size(); i++)
{
line_t *ld = level.linkedPortals[i]->mOrigin;
line_t *ld = Level->linkedPortals[i]->mOrigin;
int othergroup = ld->frontsector->PortalGroup;
FDisplacement &disp = level.Displacements(thisgroup, othergroup);
FDisplacement &disp = Level->Displacements(thisgroup, othergroup);
if (!disp.isSet) continue; // no connection.
FBoundingBox box(position.X + disp.pos.X, position.Y + disp.pos.Y, checkradius);
if (!box.inRange(ld) || box.BoxOnLineSide(level.linkedPortals[i]->mOrigin) != -1) continue; // not touched
foundPortals.Push(level.linkedPortals[i]);
if (!box.inRange(ld) || box.BoxOnLineSide(Level->linkedPortals[i]->mOrigin) != -1) continue; // not touched
foundPortals.Push(Level->linkedPortals[i]);
}
bool foundone = true;
while (foundone)
@ -1228,7 +1234,7 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
while (!wsec->PortalBlocksMovement(sector_t::ceiling) && upperz > wsec->GetPortalPlaneZ(sector_t::ceiling))
{
int othergroup = wsec->GetOppositePortalGroup(sector_t::ceiling);
DVector2 pos = level.Displacements.getOffset(startgroup, othergroup) + position;
DVector2 pos = Level->Displacements.getOffset(startgroup, othergroup) + position;
if (processMask.getBit(othergroup)) break;
processMask.setBit(othergroup);
out.Add(othergroup | FPortalGroupArray::UPPER);
@ -1239,21 +1245,21 @@ bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double u
while (!wsec->PortalBlocksMovement(sector_t::floor) && position.Z < wsec->GetPortalPlaneZ(sector_t::floor))
{
int othergroup = wsec->GetOppositePortalGroup(sector_t::floor);
DVector2 pos = level.Displacements.getOffset(startgroup, othergroup) + position;
DVector2 pos = Level->Displacements.getOffset(startgroup, othergroup) + position;
if (processMask.getBit(othergroup)) break;
processMask.setBit(othergroup);
out.Add(othergroup | FPortalGroupArray::LOWER);
wsec = P_PointInSector(pos); // get lower sector at the exact spot we want to check and repeat
retval = true;
}
if (out.method == FPortalGroupArray::PGA_Full3d && level.PortalBlockmap.hasLinkedSectorPortals)
if (out.method == FPortalGroupArray::PGA_Full3d && Level->PortalBlockmap.hasLinkedSectorPortals)
{
groupsToCheck.Clear();
groupsToCheck.Push(startgroup);
int thisgroup = startgroup;
for (unsigned i = 0; i < groupsToCheck.Size();i++)
{
DVector2 disp = level.Displacements.getOffset(startgroup, thisgroup & ~FPortalGroupArray::FLAT);
DVector2 disp = Level->Displacements.getOffset(startgroup, thisgroup & ~FPortalGroupArray::FLAT);
FBoundingBox box(position.X + disp.X, position.Y + disp.Y, checkradius);
FBlockLinesIterator it(box);
line_t *ld;

View file

@ -264,11 +264,11 @@ struct FSectorPortalGroup
//============================================================================
void P_SpawnLinePortal(line_t* line);
void P_FinalizePortals();
void P_FinalizePortals(FLevelLocals *Level);
bool P_ChangePortal(line_t *ln, int thisid, int destid);
void P_CreateLinkedPortals();
bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out);
void P_CollectLinkedPortals();
void P_CreateLinkedPortals(FLevelLocals *Level);
bool P_CollectConnectedGroups(FLevelLocals *Level, int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out);
void P_CollectLinkedPortals(FLevelLocals *Level);
unsigned P_GetSkyboxPortal(AActor *actor);
unsigned P_GetPortal(int type, int plane, sector_t *orgsec, sector_t *destsec, const DVector2 &displacement);
unsigned P_GetStackPortal(AActor *point, int plane);
@ -280,7 +280,7 @@ void P_TranslatePortalXY(line_t* src, double& vx, double& vy);
void P_TranslatePortalVXVY(line_t* src, double &velx, double &vely);
void P_TranslatePortalAngle(line_t* src, DAngle& angle);
void P_TranslatePortalZ(line_t* src, double& vz);
DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy);
DVector2 P_GetOffsetPosition(FLevelLocals *Level, double x, double y, double dx, double dy);
struct FLevelLocals;
void InitPortalGroups(FLevelLocals *Level);

View file

@ -108,8 +108,8 @@ public:
cres.portalflags = 0;
}
DBlockLinesIterator(double x, double y, double z, double height, double radius, sector_t *sec)
:FMultiBlockLinesIterator(check, x, y, z, height, radius, sec)
DBlockLinesIterator(FLevelLocals *Level, double x, double y, double z, double height, double radius, sector_t *sec)
:FMultiBlockLinesIterator(check, Level, x, y, z, height, radius, sec)
{
cres.line = nullptr;
cres.Position.Zero();
@ -132,21 +132,22 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBlockLinesIterator, Create, CreateBLI)
ACTION_RETURN_OBJECT(Create<DBlockLinesIterator>(origin, radius));
}
static DBlockLinesIterator *CreateBLIFromPos(double x, double y, double z, double h, double radius, sector_t *sec)
static DBlockLinesIterator *CreateBLIFromPos(FLevelLocals *Level, double x, double y, double z, double h, double radius, sector_t *sec)
{
return Create<DBlockLinesIterator>(x, y, z, h, radius, sec);
return Create<DBlockLinesIterator>(Level, x, y, z, h, radius, sec);
}
DEFINE_ACTION_FUNCTION_NATIVE(DBlockLinesIterator, CreateFromPos, CreateBLIFromPos)
DEFINE_ACTION_FUNCTION_NATIVE(DBlockLinesIterator, CreateFromPosition, CreateBLIFromPos)
{
PARAM_PROLOGUE;
PARAM_POINTER(Level, FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
PARAM_FLOAT(h);
PARAM_FLOAT(radius);
PARAM_POINTER(sec, sector_t);
ACTION_RETURN_OBJECT(Create<DBlockLinesIterator>(x, y, z, h, radius, sec));
ACTION_RETURN_OBJECT(Create<DBlockLinesIterator>(Level, x, y, z, h, radius, sec));
}
static int BLINext(DBlockLinesIterator *self)
@ -182,8 +183,8 @@ public:
cres.portalflags = 0;
}
DBlockThingsIterator(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
: iterator(check, checkx, checky, checkz, checkh, checkradius, ignorerestricted, newsec)
DBlockThingsIterator(FLevelLocals *Level, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted, sector_t *newsec)
: iterator(check, Level, checkx, checky, checkz, checkh, checkradius, ignorerestricted, newsec)
{
cres.thing = nullptr;
cres.Position.Zero();
@ -209,21 +210,22 @@ DEFINE_ACTION_FUNCTION_NATIVE(DBlockThingsIterator, Create, CreateBTI)
ACTION_RETURN_OBJECT(Create<DBlockThingsIterator>(origin, radius, ignore));
}
static DBlockThingsIterator *CreateBTIFromPos(double x, double y, double z, double h, double radius, bool ignore)
static DBlockThingsIterator *CreateBTIFromPos(FLevelLocals *Level, double x, double y, double z, double h, double radius, bool ignore)
{
return Create<DBlockThingsIterator>(x, y, z, h, radius, ignore, nullptr);
return Create<DBlockThingsIterator>(Level, x, y, z, h, radius, ignore, nullptr);
}
DEFINE_ACTION_FUNCTION_NATIVE(DBlockThingsIterator, CreateFromPos, CreateBTIFromPos)
DEFINE_ACTION_FUNCTION_NATIVE(DBlockThingsIterator, CreateFromPosition, CreateBTIFromPos)
{
PARAM_PROLOGUE;
PARAM_POINTER(Level, FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
PARAM_FLOAT(h);
PARAM_FLOAT(radius);
PARAM_BOOL(ignore);
ACTION_RETURN_OBJECT(Create<DBlockThingsIterator>(x, y, z, h, radius, ignore, nullptr));
ACTION_RETURN_OBJECT(Create<DBlockThingsIterator>(Level, x, y, z, h, radius, ignore, nullptr));
}
static int NextBTI(DBlockThingsIterator *bti)

View file

@ -2577,7 +2577,7 @@ DEFINE_ACTION_FUNCTION(FLevelLocals, GetChecksum)
ACTION_RETURN_STRING((const char*)md5string);
}
static void Vec2Offset(double x, double y, double dx, double dy, bool absolute, DVector2 *result)
static void Vec2Offset(FLevelLocals *self, double x, double y, double dx, double dy, bool absolute, DVector2 *result)
{
if (absolute)
{
@ -2585,24 +2585,24 @@ static void Vec2Offset(double x, double y, double dx, double dy, bool absolute,
}
else
{
*result = P_GetOffsetPosition(x, y, dx, dy);
*result = P_GetOffsetPosition(self, x, y, dx, dy);
}
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec2Offset, Vec2Offset)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(dx);
PARAM_FLOAT(dy);
PARAM_BOOL(absolute);
DVector2 result;
Vec2Offset(x, y, dx, dy, absolute, &result);
Vec2Offset(self, x, y, dx, dy, absolute, &result);
ACTION_RETURN_VEC2(result);
}
static void Vec2OffsetZ(double x, double y, double dx, double dy, double atz, bool absolute, DVector3 *result)
static void Vec2OffsetZ(FLevelLocals *Level, double x, double y, double dx, double dy, double atz, bool absolute, DVector3 *result)
{
if (absolute)
{
@ -2610,14 +2610,14 @@ static void Vec2OffsetZ(double x, double y, double dx, double dy, double atz, bo
}
else
{
DVector2 v = P_GetOffsetPosition(x, y, dx, dy);
DVector2 v = P_GetOffsetPosition(Level, x, y, dx, dy);
*result = (DVector3(v, atz));
}
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec2OffsetZ, Vec2OffsetZ)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(dx);
@ -2625,11 +2625,11 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec2OffsetZ, Vec2OffsetZ)
PARAM_FLOAT(atz);
PARAM_BOOL(absolute);
DVector3 result;
Vec2OffsetZ(x, y, dx, dy, atz, absolute, &result);
Vec2OffsetZ(self, x, y, dx, dy, atz, absolute, &result);
ACTION_RETURN_VEC3(result);
}
static void Vec3Offset(double x, double y, double z, double dx, double dy, double dz, bool absolute, DVector3 *result)
static void Vec3Offset(FLevelLocals *Level, double x, double y, double z, double dx, double dy, double dz, bool absolute, DVector3 *result)
{
if (absolute)
{
@ -2637,14 +2637,14 @@ static void Vec3Offset(double x, double y, double z, double dx, double dy, doubl
}
else
{
DVector2 v = P_GetOffsetPosition(x, y, dx, dy);
DVector2 v = P_GetOffsetPosition(Level, x, y, dx, dy);
*result = (DVector3(v, z + dz));
}
}
DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec3Offset, Vec3Offset)
{
PARAM_PROLOGUE;
PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
@ -2653,7 +2653,7 @@ DEFINE_ACTION_FUNCTION_NATIVE(FLevelLocals, Vec3Offset, Vec3Offset)
PARAM_FLOAT(dz);
PARAM_BOOL(absolute);
DVector3 result;
Vec3Offset(x, y, z, dx, dy, dz, absolute, &result);
Vec3Offset(self, x, y, z, dx, dy, dz, absolute, &result);
ACTION_RETURN_VEC3(result);
}
@ -2851,6 +2851,7 @@ DEFINE_FIELD(DBaseStatusBar, fullscreenOffsets);
DEFINE_FIELD(DBaseStatusBar, defaultScale);
DEFINE_FIELD(DBaseStatusBar, artiflashTick);
DEFINE_FIELD(DBaseStatusBar, itemflashFade);
DEFINE_FIELD(DBaseStatusBar, Level);
DEFINE_FIELD(DHUDFont, mFont);

View file

@ -492,7 +492,13 @@ class BlockThingsIterator : Object native
native int portalflags;
native static BlockThingsIterator Create(Actor origin, double checkradius = -1, bool ignorerestricted = false);
native static BlockThingsIterator CreateFromPos(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted);
native static BlockThingsIterator CreateFromPosition(LevelLocals Level, double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted);
// Since this depends on the global level variable it should not be used any longer because this may block compatibility with future features.
deprecated("3.8") static BlockThingsIterator CreateFromPos(double checkx, double checky, double checkz, double checkh, double checkradius, bool ignorerestricted)
{
return CreateFromPosition(level, checkx, checky, checkz, checkh, checkradius, ignorerestricted);
}
native bool Next();
}
@ -503,7 +509,13 @@ class BlockLinesIterator : Object native
native int portalflags;
native static BlockLinesIterator Create(Actor origin, double checkradius = -1);
native static BlockLinesIterator CreateFromPos(Vector3 pos, double checkh, double checkradius, Sector sec = null);
native static BlockLinesIterator CreateFromPosition(LevelLocals Level, Vector3 pos, double checkh, double checkradius, Sector sec = null);
// Since this depends on the global level variable it should not be used any longer because this may block compatibility with future features.
deprecated("3.8") static BlockLinesIterator CreateFromPos(Vector3 pos, double checkh, double checkradius, Sector sec = null)
{
return CreateFromPosition(level, pos, checkh, checkradius, sec);
}
native bool Next();
}
@ -691,15 +703,15 @@ struct LevelLocals native
native void StartIntermission(Name type, int state) const;
native SpotState GetSpotState(bool create = true);
native static clearscope bool IsPointInMap(vector3 p);
native clearscope bool IsPointInMap(vector3 p);
native static clearscope vector2 Vec2Diff(vector2 v1, vector2 v2);
native static clearscope vector3 Vec3Diff(vector3 v1, vector3 v2);
native static clearscope vector3 SphericalCoords(vector3 viewpoint, vector3 targetPos, vector2 viewAngles = (0, 0), bool absolute = false);
native clearscope vector2 Vec2Diff(vector2 v1, vector2 v2);
native clearscope vector3 Vec3Diff(vector3 v1, vector3 v2);
native clearscope vector3 SphericalCoords(vector3 viewpoint, vector3 targetPos, vector2 viewAngles = (0, 0), bool absolute = false);
native static clearscope vector2 Vec2Offset(vector2 pos, vector2 dir, bool absolute = false);
native static clearscope vector3 Vec2OffsetZ(vector2 pos, vector2 dir, double atz, bool absolute = false);
native static clearscope vector3 Vec3Offset(vector3 pos, vector3 dir, bool absolute = false);
native clearscope vector2 Vec2Offset(vector2 pos, vector2 dir, bool absolute = false);
native clearscope vector3 Vec2OffsetZ(vector2 pos, vector2 dir, double atz, bool absolute = false);
native clearscope vector3 Vec3Offset(vector3 pos, vector3 dir, bool absolute = false);
native String GetChecksum() const;

View file

@ -299,6 +299,7 @@ class BaseStatusBar native ui
native Vector2 defaultScale; // factor for fully scaled fullscreen display.
clearscope native int artiflashTick;
clearscope native double itemflashFade;
clearscope native LevelLocals Level;
// These are block properties for the drawers. A child class can set them to have a block of items use the same settings.
native double Alpha;