From 3cef56249dee03068ced261a00b3ee21f06efc15 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 25 Jan 2019 00:30:55 +0100 Subject: [PATCH] - moved most functions of portals.cpp into FLevelLocals. Much of this is used during level init and needs to be independent of the current level. --- src/actor.h | 74 +---- src/actorinlines.h | 68 ++++ src/b_func.cpp | 2 +- src/g_levellocals.h | 61 ++++ src/maploader/maploader.cpp | 2 +- src/maploader/maploader.h | 1 + src/maploader/specials.cpp | 94 +++++- src/p_effect.cpp | 2 +- src/p_lnspec.cpp | 2 +- src/p_map.cpp | 18 +- src/p_maputl.cpp | 10 +- src/p_maputl.h | 26 +- src/p_saveg.cpp | 2 +- src/p_teleport.cpp | 2 +- src/p_trace.cpp | 2 +- src/portal.cpp | 434 ++++++++++--------------- src/portal.h | 10 - src/scripting/vmthunks.cpp | 6 +- wadsrc/static/zscript/base.txt | 1 + wadsrc/static/zscript/mapdata.txt | 4 +- wadsrc/static/zscript/shared/skies.txt | 2 +- 21 files changed, 420 insertions(+), 403 deletions(-) diff --git a/src/actor.h b/src/actor.h index 7f1b1ea3fe..778ed611ee 100644 --- a/src/actor.h +++ b/src/actor.h @@ -900,74 +900,12 @@ public: return other->PosRelative(this) - Pos(); } - DVector2 Vec2Offset(double dx, double dy, bool absolute = false) - { - if (absolute) - { - return { X() + dx, Y() + dy }; - } - else - { - return P_GetOffsetPosition(X(), Y(), dx, dy); - } - } - - - DVector3 Vec2OffsetZ(double dx, double dy, double atz, bool absolute = false) - { - if (absolute) - { - return{ X() + dx, Y() + dy, atz }; - } - else - { - DVector2 v = P_GetOffsetPosition(X(), Y(), dx, dy); - return DVector3(v, atz); - } - } - - DVector2 Vec2Angle(double length, DAngle angle, bool absolute = false) - { - if (absolute) - { - return{ X() + length * angle.Cos(), Y() + length * angle.Sin() }; - } - else - { - return P_GetOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin()); - } - } - - DVector3 Vec3Offset(double dx, double dy, double dz, bool absolute = false) - { - if (absolute) - { - return { X() + dx, Y() + dy, Z() + dz }; - } - else - { - DVector2 v = P_GetOffsetPosition(X(), Y(), dx, dy); - return DVector3(v, Z() + dz); - } - } - - DVector3 Vec3Offset(const DVector3 &ofs, bool absolute = false) - { - return Vec3Offset(ofs.X, ofs.Y, ofs.Z, absolute); - } - - DVector3 Vec3Angle(double length, DAngle angle, double dz, bool absolute = false) - { - if (absolute) - { - return{ X() + length * angle.Cos(), Y() + length * angle.Sin(), Z() + dz }; - } - else - { - DVector2 v = P_GetOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin()); - return DVector3(v, Z() + dz); - } - } + DVector2 Vec2Offset(double dx, double dy, bool absolute = false); + DVector3 Vec2OffsetZ(double dx, double dy, double atz, bool absolute = false); + DVector2 AActor::Vec2Angle(double length, DAngle angle, bool absolute = false); + DVector3 Vec3Offset(double dx, double dy, double dz, bool absolute = false); + DVector3 Vec3Offset(const DVector3 &ofs, bool absolute = false); + DVector3 Vec3Angle(double length, DAngle angle, double dz, bool absolute = false); void ClearInterpolation(); diff --git a/src/actorinlines.h b/src/actorinlines.h index 408835524d..7346d6d763 100644 --- a/src/actorinlines.h +++ b/src/actorinlines.h @@ -94,3 +94,71 @@ inline double AActor::AttackOffset(double offset) } +inline DVector2 AActor::Vec2Offset(double dx, double dy, bool absolute) +{ + if (absolute) + { + return { X() + dx, Y() + dy }; + } + else + { + return level.GetPortalOffsetPosition(X(), Y(), dx, dy); + } +} + + +inline DVector3 AActor::Vec2OffsetZ(double dx, double dy, double atz, bool absolute) +{ + if (absolute) + { + return{ X() + dx, Y() + dy, atz }; + } + else + { + DVector2 v = level.GetPortalOffsetPosition(X(), Y(), dx, dy); + return DVector3(v, atz); + } +} + +inline DVector2 AActor::Vec2Angle(double length, DAngle angle, bool absolute) +{ + if (absolute) + { + return{ X() + length * angle.Cos(), Y() + length * angle.Sin() }; + } + else + { + return level.GetPortalOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin()); + } +} + +inline DVector3 AActor::Vec3Offset(double dx, double dy, double dz, bool absolute) +{ + if (absolute) + { + return { X() + dx, Y() + dy, Z() + dz }; + } + else + { + DVector2 v = level.GetPortalOffsetPosition(X(), Y(), dx, dy); + return DVector3(v, Z() + dz); + } +} + +inline DVector3 AActor::Vec3Offset(const DVector3 &ofs, bool absolute) +{ + return Vec3Offset(ofs.X, ofs.Y, ofs.Z, absolute); +} + +inline DVector3 AActor::Vec3Angle(double length, DAngle angle, double dz, bool absolute) +{ + if (absolute) + { + return{ X() + length * angle.Cos(), Y() + length * angle.Sin(), Z() + dz }; + } + else + { + DVector2 v = level.GetPortalOffsetPosition(X(), Y(), length*angle.Cos(), length*angle.Sin()); + return DVector3(v, Z() + dz); + } +} diff --git a/src/b_func.cpp b/src/b_func.cpp index 0613cacaec..36bbcf5c2a 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -73,7 +73,7 @@ bool DBot::Reachable (AActor *rtarget) double estimated_dist = player->mo->Distance2D(rtarget); bool reachable = true; - FPathTraverse it(player->mo->X()+player->mo->Vel.X, player->mo->Y()+player->mo->Vel.Y, rtarget->X(), rtarget->Y(), PT_ADDLINES|PT_ADDTHINGS); + FPathTraverse it(&level, player->mo->X()+player->mo->Vel.X, player->mo->Y()+player->mo->Vel.Y, rtarget->X(), rtarget->Y(), PT_ADDLINES|PT_ADDTHINGS); intercept_t *in; while ((in = it.Next())) { diff --git a/src/g_levellocals.h b/src/g_levellocals.h index a88a789be4..521fffa0da 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -50,6 +50,38 @@ #include "r_data/r_sections.h" #include "r_data/r_canvastexture.h" +//============================================================================ +// +// This is used to mark processed portals for some collection functions. +// +//============================================================================ + +struct FPortalBits +{ + TArray data; + + void setSize(int num) + { + data.Resize((num + 31) / 32); + clear(); + } + + void clear() + { + memset(&data[0], 0, data.Size() * sizeof(uint32_t)); + } + + void setBit(int group) + { + data[group >> 5] |= (1 << (group & 31)); + } + + int getBit(int group) + { + return data[group >> 5] & (1 << (group & 31)); + } +}; + class DACSThinker; class DFraggleThinker; class DSpotState; @@ -120,6 +152,8 @@ struct FLevelData struct FLevelLocals : public FLevelData { + friend class MapLoader; + void Tick(); void Mark(); void AddScroller(int secnum); @@ -138,6 +172,33 @@ struct FLevelLocals : public FLevelData void SetConversation(int convid, PClassActor *Class, int dlgindex); int FindNode (const FStrifeDialogueNode *node); +private: + line_t *FindPortalDestination(line_t *src, int tag); + void BuildPortalBlockmap(); + void UpdatePortal(FLinePortal *port); + void CollectLinkedPortals(); + void CreateLinkedPortals(); + bool ChangePortalLine(line_t *line, int destid); + void AddDisplacementForPortal(FSectorPortal *portal); + void AddDisplacementForPortal(FLinePortal *portal); + bool ConnectPortalGroups(); +public: + void FinalizePortals(); + bool ChangePortal(line_t *ln, int thisid, int destid); + unsigned GetSkyboxPortal(AActor *actor); + unsigned GetPortal(int type, int plane, sector_t *orgsec, sector_t *destsec, const DVector2 &displacement); + unsigned GetStackPortal(AActor *point, int plane); + DVector2 GetPortalOffsetPosition(double x, double y, double dx, double dy); + bool CollectConnectedGroups(int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out); + +private: + // Work data for CollectConnectedGroups. + FPortalBits processMask; + TArray foundPortals; + TArray groupsToCheck; + +public: + FSectorTagIterator GetSectorTagIterator(int tag) { return FSectorTagIterator(tagManager, tag); diff --git a/src/maploader/maploader.cpp b/src/maploader/maploader.cpp index 0dd4190917..c3f207927a 100644 --- a/src/maploader/maploader.cpp +++ b/src/maploader/maploader.cpp @@ -3290,5 +3290,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. + Level->FinalizePortals(); // finalize line portals after polyobjects have been initialized. This info is needed for properly flagging them. } diff --git a/src/maploader/maploader.h b/src/maploader/maploader.h index 884a827a4b..ba2f192bdb 100644 --- a/src/maploader/maploader.h +++ b/src/maploader/maploader.h @@ -185,6 +185,7 @@ private: void SpawnPortal(line_t *line, int sectortag, int plane, int bytealpha, int linked); void CopyPortal(int sectortag, int plane, unsigned pnum, double alpha, bool tolines); void SetPortal(sector_t *sector, int plane, unsigned pnum, double alpha); + void SpawnLinePortal(line_t* line); void SetupPortals(); void SpawnSkybox(AActor *origin); void SetupFloorPortal (AActor *point); diff --git a/src/maploader/specials.cpp b/src/maploader/specials.cpp index 38ace4b685..4f42a017f5 100644 --- a/src/maploader/specials.cpp +++ b/src/maploader/specials.cpp @@ -109,7 +109,87 @@ EXTERN_CVAR(Bool, forcewater) // //----------------------------------------------------------------------------- -//--------------------------------------------------------------------------- +//============================================================================ +// +// Spawns a single line portal +// +//============================================================================ + +void MapLoader::SpawnLinePortal(line_t* line) +{ + // portal destination is special argument #0 + line_t* dst = nullptr; + + if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED) + { + dst = Level->FindPortalDestination(line, line->args[0]); + + line->portalindex = Level->linePortals.Reserve(1); + FLinePortal *port = &Level->linePortals.Last(); + + memset(port, 0, sizeof(FLinePortal)); + port->mOrigin = line; + port->mDestination = dst; + port->mType = uint8_t(line->args[2]); // range check is done above. + + if (port->mType == PORTT_LINKED) + { + // Linked portals have no z-offset ever. + port->mAlign = PORG_ABSOLUTE; + } + else + { + port->mAlign = uint8_t(line->args[3] >= PORG_ABSOLUTE && line->args[3] <= PORG_CEILING ? line->args[3] : PORG_ABSOLUTE); + if (port->mType == PORTT_INTERACTIVE && port->mAlign != PORG_ABSOLUTE) + { + // Due to the way z is often handled, these pose a major issue for parts of the code that needs to transparently handle interactive portals. + Printf(TEXTCOLOR_RED "Warning: z-offsetting not allowed for interactive portals. Changing line %d to teleport-portal!\n", line->Index()); + port->mType = PORTT_TELEPORT; + } + } + port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : + port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : + PORTF_TYPEINTERACTIVE; + } + else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0) + { + // EE-style portals require that the first line ID is identical and the first arg of the two linked linedefs are 0 and 1 respectively. + + int mytag = Level->GetFirstLineId(line); + + for (auto &ln : Level->lines) + { + if (Level->GetFirstLineId(&ln) == mytag && ln.args[0] == 1 && ln.special == Line_SetPortal) + { + line->portalindex = Level->linePortals.Reserve(1); + FLinePortal *port = &Level->linePortals.Last(); + + memset(port, 0, sizeof(FLinePortal)); + port->mOrigin = line; + port->mDestination = &ln; + port->mType = PORTT_LINKED; + port->mAlign = PORG_ABSOLUTE; + port->mDefFlags = PORTF_TYPEINTERACTIVE; + + // we need to create the backlink here, too. + ln.portalindex = Level->linePortals.Reserve(1); + port = &Level->linePortals.Last(); + + memset(port, 0, sizeof(FLinePortal)); + port->mOrigin = &ln; + port->mDestination = line; + port->mType = PORTT_LINKED; + port->mAlign = PORG_ABSOLUTE; + port->mDefFlags = PORTF_TYPEINTERACTIVE; + } + } + } + else + { + // undefined type + return; + } +} //----------------------------------------------------------------------------- // @@ -128,7 +208,7 @@ void MapLoader::SetupFloorPortal (AActor *point) if (Sector->GetAlpha(sector_t::floor) == 1.) Sector->SetAlpha(sector_t::floor, clamp(point->args[0], 0, 255) / 255.); - Sector->Portals[sector_t::floor] = P_GetStackPortal(skyv, sector_t::floor); + Sector->Portals[sector_t::floor] = Level->GetStackPortal(skyv, sector_t::floor); } } @@ -149,7 +229,7 @@ void MapLoader::SetupCeilingPortal (AActor *point) if (Sector->GetAlpha(sector_t::ceiling) == 1.) Sector->SetAlpha(sector_t::ceiling, clamp(point->args[0], 0, 255) / 255.); - Sector->Portals[sector_t::ceiling] = P_GetStackPortal(skyv, sector_t::ceiling); + Sector->Portals[sector_t::ceiling] = Level->GetStackPortal(skyv, sector_t::ceiling); } } @@ -319,7 +399,7 @@ void MapLoader::SpawnPortal(line_t *line, int sectortag, int plane, int bytealph // beware of overflows. DVector2 pos1 = line->v1->fPos() + line->Delta() / 2; DVector2 pos2 = oline.v1->fPos() + oline.Delta() / 2; - unsigned pnum = P_GetPortal(linked ? PORTS_LINKEDPORTAL : PORTS_PORTAL, plane, line->frontsector, oline.frontsector, pos2 - pos1); + unsigned pnum = Level->GetPortal(linked ? PORTS_LINKEDPORTAL : PORTS_PORTAL, plane, line->frontsector, oline.frontsector, pos2 - pos1); CopyPortal(sectortag, plane, pnum, bytealpha / 255., false); return; } @@ -348,7 +428,7 @@ void MapLoader::SpawnSkybox(AActor *origin) if (refline->special == Sector_SetPortal && refline->args[1] == 2) { // We found the setup linedef for this skybox, so let's use it for our init. - unsigned pnum = P_GetSkyboxPortal(origin); + unsigned pnum = Level->GetSkyboxPortal(origin); CopyPortal(refline->args[0], refline->args[2], pnum, 0, true); return; } @@ -669,13 +749,13 @@ void MapLoader::SpawnSpecials () } else if (line.args[1] == 3 || line.args[1] == 4) { - unsigned pnum = P_GetPortal(line.args[1] == 3 ? PORTS_PLANE : PORTS_HORIZON, line.args[2], line.frontsector, NULL, { 0,0 }); + unsigned pnum = Level->GetPortal(line.args[1] == 3 ? PORTS_PLANE : PORTS_HORIZON, line.args[2], line.frontsector, NULL, { 0,0 }); CopyPortal(line.args[0], line.args[2], pnum, 0, true); } break; case Line_SetPortal: - P_SpawnLinePortal(&line); + SpawnLinePortal(&line); break; // [RH] ZDoom Static_Init settings diff --git a/src/p_effect.cpp b/src/p_effect.cpp index da43890c5d..93724d9629 100644 --- a/src/p_effect.cpp +++ b/src/p_effect.cpp @@ -264,7 +264,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 = level.GetPortalOffsetPosition(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; diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index b369ffceb5..e67ed311c9 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -3402,7 +3402,7 @@ FUNC(LS_Thing_SetConversation) FUNC(LS_Line_SetPortalTarget) // Line_SetPortalTarget(thisid, destid) { - return P_ChangePortal(ln, arg0, arg1); + return Level->ChangePortal(ln, arg0, arg1); } FUNC(LS_Sector_SetPlaneReflection) diff --git a/src/p_map.cpp b/src/p_map.cpp index 8801b1791f..9b52b897e1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -2928,7 +2928,7 @@ void FSlide::HitSlideLine(line_t* ld) void FSlide::SlideTraverse(const DVector2 &start, const DVector2 &end) { FLineOpening open; - FPathTraverse it(start.X, start.Y, end.X, end.Y, PT_ADDLINES); + FPathTraverse it(&level, start.X, start.Y, end.X, end.Y, PT_ADDLINES); intercept_t *in; while ((in = it.Next())) @@ -3285,7 +3285,7 @@ const secplane_t * P_CheckSlopeWalk(AActor *actor, DVector2 &move) bool FSlide::BounceTraverse(const DVector2 &start, const DVector2 &end) { FLineOpening open; - FPathTraverse it(start.X, start.Y, end.X, end.Y, PT_ADDLINES); + FPathTraverse it(&level, start.X, start.Y, end.X, end.Y, PT_ADDLINES); intercept_t *in; while ((in = it.Next())) @@ -3977,7 +3977,7 @@ struct aim_t if (ceilingportalstate) EnterSectorPortal(sector_t::ceiling, 0, lastsector, toppitch, MIN(0., bottompitch)); if (floorportalstate) EnterSectorPortal(sector_t::floor, 0, lastsector, MAX(0., toppitch), bottompitch); - FPathTraverse it(startpos.X, startpos.Y, aimtrace.X, aimtrace.Y, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE | PT_DELTA, startfrac); + FPathTraverse it(&level, startpos.X, startpos.Y, aimtrace.X, aimtrace.Y, PT_ADDLINES | PT_ADDTHINGS | PT_COMPATIBLE | PT_DELTA, startfrac); intercept_t *in; if (aimdebug) @@ -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 = level.GetPortalOffsetPosition(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 = level.GetPortalOffsetPosition(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 = level.GetPortalOffsetPosition(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; @@ -5376,7 +5376,7 @@ bool P_TalkFacing(AActor *player) bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, bool &foundline) { - FPathTraverse it(start.X, start.Y, end.X, end.Y, PT_ADDLINES | PT_ADDTHINGS); + FPathTraverse it(&level, start.X, start.Y, end.X, end.Y, PT_ADDLINES | PT_ADDTHINGS); intercept_t *in; DVector3 xpos = { start.X, start.Y, usething->Z() }; @@ -5519,7 +5519,7 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end, bool P_NoWayTraverse(AActor *usething, const DVector2 &start, const DVector2 &end) { - FPathTraverse it(start.X, start.Y, end.X, end.Y, PT_ADDLINES); + FPathTraverse it(&level, start.X, start.Y, end.X, end.Y, PT_ADDLINES); intercept_t *in; while ((in = it.Next())) @@ -5596,7 +5596,7 @@ int P_UsePuzzleItem(AActor *PuzzleItemUser, int PuzzleItemType) start = PuzzleItemUser->GetPortalTransition(PuzzleItemUser->Height / 2); end = PuzzleItemUser->Angles.Yaw.ToVector(usedist); - FPathTraverse it(start.X, start.Y, end.X, end.Y, PT_DELTA | PT_ADDLINES | PT_ADDTHINGS); + FPathTraverse it(&level, start.X, start.Y, end.X, end.Y, PT_DELTA | PT_ADDLINES | PT_ADDTHINGS); intercept_t *in; while ((in = it.Next())) diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 678f3fbdd9..cf4b3cf030 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -504,7 +504,7 @@ void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sec { FPortalGroupArray check; - P_CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check); + level.CollectConnectedGroups(Sector->PortalGroup, Pos(), Top(), radius, check); BlockNode = NULL; FBlockNode **alink = &this->BlockNode; @@ -714,7 +714,7 @@ 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) level.CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist); checkpoint.Z = checkradius == -1? origin->radius : checkradius; basegroup = origin->Sector->PortalGroup; startsector = origin->Sector; @@ -728,7 +728,7 @@ FMultiBlockLinesIterator::FMultiBlockLinesIterator(FPortalGroupArray &check, dou 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) level.CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist); checkpoint.Z = checkradius; Reset(); } @@ -1056,7 +1056,7 @@ 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) level.CollectConnectedGroups(origin->Sector->PortalGroup, checkpoint, origin->Top(), checkradius, checklist); checkpoint.Z = checkradius == -1? origin->radius : checkradius; basegroup = origin->Sector->PortalGroup; Reset(); @@ -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) level.CollectConnectedGroups(basegroup, checkpoint, checkz + checkh, checkradius, checklist); checkpoint.Z = checkradius; Reset(); } diff --git a/src/p_maputl.h b/src/p_maputl.h index 23e3f3ed62..c8b5cd9ff2 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -358,6 +358,7 @@ class FPathTraverse protected: static TArray intercepts; + FLevelLocals *Level; divline_t trace; double Startfrac; unsigned int intercept_index; @@ -366,13 +367,17 @@ protected: virtual void AddLineIntercepts(int bx, int by); virtual void AddThingIntercepts(int bx, int by, FBlockThingsIterator &it, bool compatible); - FPathTraverse() {} + FPathTraverse(FLevelLocals *l) + { + Level = l; + } public: intercept_t *Next(); - FPathTraverse(double x1, double y1, double x2, double y2, int flags, double startfrac = 0) + FPathTraverse(FLevelLocals *l, double x1, double y1, double x2, double y2, int flags, double startfrac = 0) { + Level = l; init(x1, y1, x2, y2, flags, startfrac); } void init(double x1, double y1, double x2, double y2, int flags, double startfrac = 0); @@ -392,23 +397,6 @@ public: }; -//============================================================================ -// -// A traverser that uses the portal blockmap -// This should be in portal.h but that'd create circular dependencies. -// -//============================================================================ - -class FLinePortalTraverse : public FPathTraverse -{ - void AddLineIntercepts(int bx, int by); - -public: - FLinePortalTraverse() - { - } -}; - // // P_MAPUTL // diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 3e2e78dcae..c6eb7e9252 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -988,7 +988,7 @@ void G_SerializeLevel(FSerializer &arc, FLevelLocals *Level, bool hubload) arc("zones", Level->Zones); arc("lineportals", Level->linePortals); arc("sectorportals", Level->sectorPortals); - if (arc.isReading()) P_FinalizePortals(); + if (arc.isReading()) Level->FinalizePortals(); // [ZZ] serialize health groups P_SerializeHealthGroups(arc); diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 844d462b03..117245c67b 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -186,7 +186,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 = level.GetPortalOffsetPosition(pos.X, pos.Y, vector.X, vector.Y); P_SpawnTeleportFog(thing, DVector3(fogpos, thing->Z()), false, true); } diff --git a/src/p_trace.cpp b/src/p_trace.cpp index d2f3e71f40..b4a33ade9e 100644 --- a/src/p_trace.cpp +++ b/src/p_trace.cpp @@ -777,7 +777,7 @@ bool FTraceInfo::TraceTraverse (int ptflags) // Do a 3D floor check in the starting sector Setup3DFloors(); - FPathTraverse it(Start.X, Start.Y, Vec.X * MaxDist, Vec.Y * MaxDist, ptflags | PT_DELTA, startfrac); + FPathTraverse it(&level, Start.X, Start.Y, Vec.X * MaxDist, Vec.Y * MaxDist, ptflags | PT_DELTA, startfrac); intercept_t *in; int lastsplashsector = -1; diff --git a/src/portal.cpp b/src/portal.cpp index 434cc73202..fd6eb503c9 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -64,72 +64,40 @@ DEFINE_FIELD(FSectorPortal, mDisplacement); DEFINE_FIELD(FSectorPortal, mPlaneZ); DEFINE_FIELD(FSectorPortal, mSkybox); -//============================================================================ -// -// This is used to mark processed portals for some collection functions. -// -//============================================================================ - -struct FPortalBits -{ - TArray data; - - void setSize(int num) - { - data.Resize((num + 31) / 32); - clear(); - } - - void clear() - { - memset(&data[0], 0, data.Size()*sizeof(uint32_t)); - } - - void setBit(int group) - { - data[group >> 5] |= (1 << (group & 31)); - } - - int getBit(int group) - { - return data[group >> 5] & (1 << (group & 31)); - } -}; - //============================================================================ // // BuildBlockmap // //============================================================================ -static void BuildBlockmap() +void FLevelLocals::BuildPortalBlockmap() { - auto bmapwidth = level.blockmap.bmapwidth; - auto bmapheight = level.blockmap.bmapheight; + auto bmapwidth = blockmap.bmapwidth; + auto bmapheight = blockmap.bmapheight; - level.PortalBlockmap.Clear(); - level.PortalBlockmap.Create(bmapwidth, bmapheight); + PortalBlockmap.Clear(); + 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 = blockmap.GetLines(x, y); + FPortalBlock &block = PortalBlockmap(x, y); while (*list != -1) { - line_t *ld = &level.lines[*list++]; + line_t *ld = &lines[*list++]; FLinePortal *port = ld->getPortal(); if (port && port->mType != PORTT_VISUAL) { - level.PortalBlockmap.containsLines = true; + 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) PortalBlockmap(x - 1, y).neighborContainsLines = true; + if (y > 0) PortalBlockmap(x, y - 1).neighborContainsLines = true; + if (x < PortalBlockmap.dx - 1) PortalBlockmap(x + 1, y).neighborContainsLines = true; + if (y < PortalBlockmap.dy - 1) PortalBlockmap(x, y + 1).neighborContainsLines = true; } else { @@ -140,7 +108,7 @@ static void BuildBlockmap() yes |= ld->backsector->PortalIsLinked(sector_t::ceiling) || ld->backsector->PortalIsLinked(sector_t::floor); } block.containsLinkedPortals |= yes; - level.PortalBlockmap.hasLinkedSectorPortals |= yes; + PortalBlockmap.hasLinkedSectorPortals |= yes; } } @@ -148,6 +116,23 @@ static void BuildBlockmap() } } +//============================================================================ +// +// A traverser that uses the portal blockmap +// +//============================================================================ + +class FLinePortalTraverse : public FPathTraverse +{ + void AddLineIntercepts(int bx, int by); + +public: + FLinePortalTraverse(FLevelLocals *l) : FPathTraverse(l) + { + } +}; + + //=========================================================================== // // FLinePortalTraverse :: AddLineIntercepts. @@ -158,9 +143,9 @@ static void BuildBlockmap() void FLinePortalTraverse::AddLineIntercepts(int bx, int by) { - if (by < 0 || by >= level.PortalBlockmap.dy || bx < 0 || bx >= level.PortalBlockmap.dx) return; + 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= 0) { - if (&level.lines[lineno] != src) + if (&lines[lineno] != src) { - return &level.lines[lineno]; + return &lines[lineno]; } } } @@ -228,7 +213,7 @@ static line_t *FindDestination(line_t *src, int tag) // //============================================================================ -static void SetRotation(FLinePortal *port) +static void SetPortalRotation(FLinePortal *port) { if (port != nullptr && port->mDestination != nullptr) { @@ -259,95 +244,13 @@ static void SetRotation(FLinePortal *port) } } -//============================================================================ -// -// Spawns a single line portal -// -//============================================================================ - -void P_SpawnLinePortal(line_t* line) -{ - // portal destination is special argument #0 - line_t* dst = nullptr; - - if (line->args[2] >= PORTT_VISUAL && line->args[2] <= PORTT_LINKED) - { - dst = FindDestination(line, line->args[0]); - - line->portalindex = level.linePortals.Reserve(1); - FLinePortal *port = &level.linePortals.Last(); - - memset(port, 0, sizeof(FLinePortal)); - port->mOrigin = line; - port->mDestination = dst; - port->mType = uint8_t(line->args[2]); // range check is done above. - - if (port->mType == PORTT_LINKED) - { - // Linked portals have no z-offset ever. - port->mAlign = PORG_ABSOLUTE; - } - else - { - port->mAlign = uint8_t(line->args[3] >= PORG_ABSOLUTE && line->args[3] <= PORG_CEILING ? line->args[3] : PORG_ABSOLUTE); - if (port->mType == PORTT_INTERACTIVE && port->mAlign != PORG_ABSOLUTE) - { - // Due to the way z is often handled, these pose a major issue for parts of the code that needs to transparently handle interactive portals. - Printf(TEXTCOLOR_RED "Warning: z-offsetting not allowed for interactive portals. Changing line %d to teleport-portal!\n", line->Index()); - port->mType = PORTT_TELEPORT; - } - } - port->mDefFlags = port->mType == PORTT_VISUAL ? PORTF_VISIBLE : - port->mType == PORTT_TELEPORT ? PORTF_TYPETELEPORT : - PORTF_TYPEINTERACTIVE; - } - else if (line->args[2] == PORTT_LINKEDEE && line->args[0] == 0) - { - // EE-style portals require that the first line ID is identical and the first arg of the two linked linedefs are 0 and 1 respectively. - - int mytag = level.GetFirstLineId(line); - - for (auto &ln : level.lines) - { - if (level.GetFirstLineId(&ln) == mytag && ln.args[0] == 1 && ln.special == Line_SetPortal) - { - line->portalindex = level.linePortals.Reserve(1); - FLinePortal *port = &level.linePortals.Last(); - - memset(port, 0, sizeof(FLinePortal)); - port->mOrigin = line; - port->mDestination = &ln; - port->mType = PORTT_LINKED; - port->mAlign = PORG_ABSOLUTE; - port->mDefFlags = PORTF_TYPEINTERACTIVE; - - // we need to create the backlink here, too. - ln.portalindex = level.linePortals.Reserve(1); - port = &level.linePortals.Last(); - - memset(port, 0, sizeof(FLinePortal)); - port->mOrigin = &ln; - port->mDestination = line; - port->mType = PORTT_LINKED; - port->mAlign = PORG_ABSOLUTE; - port->mDefFlags = PORTF_TYPEINTERACTIVE; - } - } - } - else - { - // undefined type - return; - } -} - //============================================================================ // // Update a line portal's state after all have been spawned // //============================================================================ -void P_UpdatePortal(FLinePortal *port) +void FLevelLocals::UpdatePortal(FLinePortal *port) { if (port->mType != PORTT_VISUAL && port->mOrigin->backsector == nullptr && !(port->mOrigin->sidedef[0]->Flags & WALLF_POLYOBJ)) { @@ -378,7 +281,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 (linePortals[port->mDestination->portalindex].mType != PORTT_LINKED) { port->mType = PORTT_INTERACTIVE; // linked portals must be two-way. } @@ -390,7 +293,7 @@ void P_UpdatePortal(FLinePortal *port) } // Cache the angle between the two linedefs, for rotating. - SetRotation(port); + SetPortalRotation(port); } //============================================================================ @@ -400,15 +303,15 @@ void P_UpdatePortal(FLinePortal *port) // //============================================================================ -void P_CollectLinkedPortals() +void FLevelLocals::CollectLinkedPortals() { - level.linkedPortals.Clear(); - for (unsigned i = 0; i < level.linePortals.Size(); i++) + linkedPortals.Clear(); + for (unsigned i = 0; i < linePortals.Size(); i++) { - FLinePortal * port = &level.linePortals[i]; + FLinePortal * port = &linePortals[i]; if (port->mType == PORTT_LINKED) { - level.linkedPortals.Push(port); + linkedPortals.Push(port); } } } @@ -419,16 +322,16 @@ void P_CollectLinkedPortals() // //============================================================================ -void P_FinalizePortals() +void FLevelLocals::FinalizePortals() { - for (unsigned i = 0; i < level.linePortals.Size(); i++) + for (unsigned i = 0; i < linePortals.Size(); i++) { - FLinePortal * port = &level.linePortals[i]; - P_UpdatePortal(port); + FLinePortal * port = &linePortals[i]; + UpdatePortal(port); } - P_CollectLinkedPortals(); - BuildBlockmap(); - P_CreateLinkedPortals(); + CollectLinkedPortals(); + BuildPortalBlockmap(); + CreateLinkedPortals(); } //============================================================================ @@ -437,20 +340,20 @@ void P_FinalizePortals() // //============================================================================ -static bool ChangePortalLine(line_t *line, int destid) +bool FLevelLocals::ChangePortalLine(line_t *line, int destid) { - if (line->portalindex >= level.linePortals.Size()) return false; - FLinePortal *port = &level.linePortals[line->portalindex]; + if (line->portalindex >= linePortals.Size()) return false; + FLinePortal *port = &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); + port->mDestination = FindPortalDestination(line, destid); if (port->mDestination == nullptr) { port->mFlags = 0; } 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 < linePortals.Size()? &linePortals[port->mDestination->portalindex] : nullptr; if (portd != nullptr && portd->mType == PORTT_INTERACTIVE && portd->mDestination == line) { // this is a 2-way interactive portal @@ -461,13 +364,13 @@ static bool ChangePortalLine(line_t *line, int destid) { port->mFlags = port->mDefFlags; } - SetRotation(portd); + SetPortalRotation(portd); } else { port->mFlags = port->mDefFlags; } - SetRotation(port); + SetPortalRotation(port); return true; } @@ -478,16 +381,16 @@ static bool ChangePortalLine(line_t *line, int destid) // //============================================================================ -bool P_ChangePortal(line_t *ln, int thisid, int destid) +bool FLevelLocals::ChangePortal(line_t *ln, int thisid, int destid) { int lineno; if (thisid == 0) return ChangePortalLine(ln, destid); - auto it = level.GetLineIdIterator(thisid); + auto it = GetLineIdIterator(thisid); bool res = false; while ((lineno = it.Next()) >= 0) { - res |= ChangePortalLine(&level.lines[lineno], destid); + res |= ChangePortalLine(&lines[lineno], destid); } return res; } @@ -553,7 +456,7 @@ void P_TranslatePortalXY(line_t* src, double& x, double& y) if (!src) return; FLinePortal *port = src->getPortal(); if (!port) return; - if (port->mFlags & PORTF_POLYOBJ) SetRotation(port); // update the angle for polyportals. + if (port->mFlags & PORTF_POLYOBJ) SetPortalRotation(port); // update the angle for polyportals. // offsets from line double nposx = x - src->v1->fX(); @@ -581,7 +484,7 @@ void P_TranslatePortalVXVY(line_t* src, double &velx, double &vely) if (!src) return; FLinePortal *port = src->getPortal(); if (!port) return; - if (port->mFlags & PORTF_POLYOBJ) SetRotation(port); // update the angle for polyportals. + if (port->mFlags & PORTF_POLYOBJ) SetPortalRotation(port); // update the angle for polyportals. double orig_velx = velx; double orig_vely = vely; @@ -600,7 +503,7 @@ void P_TranslatePortalAngle(line_t* src, DAngle& angle) if (!src) return; FLinePortal *port = src->getPortal(); if (!port) return; - if (port->mFlags & PORTF_POLYOBJ) SetRotation(port); // update the angle for polyportals. + if (port->mFlags & PORTF_POLYOBJ) SetPortalRotation(port); // update the angle for polyportals. angle = (angle + port->mAngleDiff).Normalized360(); } @@ -642,27 +545,27 @@ void P_TranslatePortalZ(line_t* src, double& z) // //============================================================================ -unsigned P_GetSkyboxPortal(AActor *actor) +unsigned FLevelLocals::GetSkyboxPortal(AActor *actor) { if (actor == nullptr) return 1; // this means a regular sky. - for (unsigned i = 0;iGetClass()->IsDescendantOf("SkyCamCompat") ? 0 : PORTSF_SKYFLATONLY; - level.sectorPortals[i].mSkybox = actor; - level.sectorPortals[i].mDestination = actor->Sector; + unsigned i = sectorPortals.Reserve(1); + memset(§orPortals[i], 0, sizeof(sectorPortals[i])); + sectorPortals[i].mType = PORTS_SKYVIEWPOINT; + sectorPortals[i].mFlags = actor->GetClass()->IsDescendantOf("SkyCamCompat") ? 0 : PORTSF_SKYFLATONLY; + sectorPortals[i].mSkybox = actor; + sectorPortals[i].mDestination = actor->Sector; return i; } -DEFINE_ACTION_FUNCTION(FSectorPortal, GetSkyboxPortal) +DEFINE_ACTION_FUNCTION(FLevelLocals, GetSkyboxPortal) { - PARAM_PROLOGUE; + PARAM_SELF_STRUCT_PROLOGUE(FLevelLocals); PARAM_OBJECT(actor, AActor); - ACTION_RETURN_INT(P_GetSkyboxPortal(actor)); + ACTION_RETURN_INT(self->GetSkyboxPortal(actor)); } //============================================================================ // @@ -672,16 +575,16 @@ DEFINE_ACTION_FUNCTION(FSectorPortal, GetSkyboxPortal) // //============================================================================ -unsigned P_GetPortal(int type, int plane, sector_t *from, sector_t *to, const DVector2 &displacement) +unsigned FLevelLocals::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; + unsigned i = sectorPortals.Reserve(1); + memset(§orPortals[i], 0, sizeof(sectorPortals[i])); + sectorPortals[i].mType = type; + sectorPortals[i].mPlane = plane; + sectorPortals[i].mOrigin = from; + sectorPortals[i].mDestination = to; + sectorPortals[i].mDisplacement = displacement; + sectorPortals[i].mPlaneZ = type == PORTS_LINKEDPORTAL? from->GetPlaneTexZ(plane) : FLT_MAX; return i; } @@ -693,47 +596,47 @@ unsigned P_GetPortal(int type, int plane, sector_t *from, sector_t *to, const DV // //============================================================================ -unsigned P_GetStackPortal(AActor *point, int plane) +unsigned FLevelLocals::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; + unsigned i = sectorPortals.Reserve(1); + memset(§orPortals[i], 0, sizeof(sectorPortals[i])); + sectorPortals[i].mType = PORTS_STACKEDSECTORTHING; + sectorPortals[i].mPlane = plane; + sectorPortals[i].mOrigin = point->target->Sector; + sectorPortals[i].mDestination = point->Sector; + sectorPortals[i].mPlaneZ = FLT_MAX; + sectorPortals[i].mSkybox = point; return i; } //============================================================================ // -// P_GetOffsetPosition +// level.GetPortalOffsetPosition // // Offsets a given coordinate if the trace from the origin crosses an // interactive line-to-line portal. // //============================================================================ -DVector2 P_GetOffsetPosition(double x, double y, double dx, double dy) +DVector2 FLevelLocals::GetPortalOffsetPosition(double x, double y, double dx, double dy) { DVector2 dest(x + dx, y + dy); - if (level.PortalBlockmap.containsLines) + if (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 = blockmap.GetBlockX(actx); + int blocky = blockmap.GetBlockY(acty); + if (blockx < 0 || blocky < 0 || blockx >= PortalBlockmap.dx || blocky >= PortalBlockmap.dy || !PortalBlockmap(blockx, blocky).neighborContainsLines) return dest; } bool repeat; do { - FLinePortalTraverse it; + FLinePortalTraverse it(this); it.init(actx, acty, dx, dy, PT_ADDLINES|PT_DELTA); intercept_t *in; @@ -777,11 +680,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 +727,7 @@ static bool CollectSectors(int groupid, sector_t *origin) // //============================================================================ -static void AddDisplacementForPortal(FSectorPortal *portal) +void FLevelLocals::AddDisplacementForPortal(FSectorPortal *portal) { int thisgroup = portal->mOrigin->PortalGroup; int othergroup = portal->mDestination->PortalGroup; @@ -839,14 +737,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 >= Displacements.size || othergroup <= 0 || othergroup >= 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 = Displacements(thisgroup, othergroup); if (!disp.isSet) { disp.pos = portal->mDisplacement; @@ -864,24 +762,24 @@ static void AddDisplacementForPortal(FSectorPortal *portal) } -static void AddDisplacementForPortal(FLinePortal *portal) +void FLevelLocals::AddDisplacementForPortal(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 = 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 >= Displacements.size || othergroup <= 0 || othergroup >= 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 = linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT; return; } - FDisplacement & disp = level.Displacements(thisgroup, othergroup); + FDisplacement & disp = Displacements(thisgroup, othergroup); if (!disp.isSet) { disp.pos = portal->mDisplacement; @@ -892,7 +790,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 = linePortals[portal->mDestination->portalindex].mType = PORTT_TELEPORT; return; } } @@ -906,7 +804,7 @@ static void AddDisplacementForPortal(FLinePortal *portal) // //============================================================================ -static bool ConnectGroups() +bool FLevelLocals::ConnectPortalGroups() { // Now uint8_t indirect = 1; @@ -915,19 +813,19 @@ static bool ConnectGroups() do { changed = false; - for (int x = 1; x < level.Displacements.size; x++) + for (int x = 1; x < Displacements.size; x++) { - for (int y = 1; y < level.Displacements.size; y++) + for (int y = 1; y < Displacements.size; y++) { - FDisplacement &dispxy = level.Displacements(x, y); + FDisplacement &dispxy = Displacements(x, y); if (dispxy.isSet) { - for (int z = 1; z < level.Displacements.size; z++) + for (int z = 1; z < Displacements.size; z++) { - FDisplacement &dispyz = level.Displacements(y, z); + FDisplacement &dispyz = Displacements(y, z); if (dispyz.isSet) { - FDisplacement &dispxz = level.Displacements(x, z); + FDisplacement &dispxz = 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 +864,13 @@ static bool ConnectGroups() // //============================================================================ -void P_CreateLinkedPortals() +void FLevelLocals::CreateLinkedPortals() { TArray orgs; int id = 1; bool bogus = false; - for(auto &s : level.sectorPortals) + for(auto &s : sectorPortals) { if (s.mType == PORTS_LINKEDPORTAL) { @@ -982,7 +880,7 @@ void P_CreateLinkedPortals() id = 1; if (orgs.Size() != 0) { - for (auto &sec : level.sectors) + for (auto &sec : sectors) { for (int j = 0; j < 2; j++) { @@ -1006,27 +904,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 < linePortals.Size(); i++) { - if (level.linePortals[i].mType == PORTT_LINKED) + if (linePortals[i].mType == PORTT_LINKED) { - if (level.linePortals[i].mDestination == nullptr) + if (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", linePortals[i].mOrigin->Index()); + linePortals[i].mOrigin->portalindex = UINT_MAX; + 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, linePortals[i].mOrigin->frontsector)) id++; + if (CollectSectors(id, linePortals[i].mDestination->frontsector)) id++; } } } - level.Displacements.Create(id); + Displacements.Create(id); // Check for leftover sectors that connect to a portal - for (auto &sec : level.sectors) + for (auto &sec : sectors) { for (int j = 0; j < 2; j++) { @@ -1041,34 +939,34 @@ void P_CreateLinkedPortals() { AddDisplacementForPortal(orgs[i]); } - for (unsigned i = 0; i < level.linePortals.Size(); i++) + for (unsigned i = 0; i < linePortals.Size(); i++) { - if (level.linePortals[i].mType == PORTT_LINKED) + if (linePortals[i].mType == PORTT_LINKED) { - AddDisplacementForPortal(&level.linePortals[i]); + AddDisplacementForPortal(&linePortals[i]); } } - for (int x = 1; x < level.Displacements.size; x++) + for (int x = 1; x < Displacements.size; x++) { - for (int y = x + 1; y < level.Displacements.size; y++) + for (int y = x + 1; y < Displacements.size; y++) { - FDisplacement &dispxy = level.Displacements(x, y); - FDisplacement &dispyx = level.Displacements(y, x); + FDisplacement &dispxy = Displacements(x, y); + FDisplacement &dispyx = 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 < 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 && sectors[i].PortalGroup == x) sec1 = i; + if (sec2 == -1 && 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 : lines) { if (line.backsector == nullptr && line.frontsector->PortalGroup == 0) { @@ -1076,7 +974,7 @@ void P_CreateLinkedPortals() } } // and now print a message for everything that still wasn't processed. - for (auto &sec : level.sectors) + for (auto &sec : sectors) { if (sec.PortalGroup == 0) { @@ -1086,19 +984,19 @@ void P_CreateLinkedPortals() } } } - bogus |= ConnectGroups(); + bogus |= ConnectPortalGroups(); 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 (Displacements.size > 1) { - level.rejectmatrix.Reset(); + 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 : sectors) { sec.CheckPortalPlane(sector_t::floor); sec.CheckPortalPlane(sector_t::ceiling); @@ -1134,7 +1032,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 (linkedPortals.Size() > 0) { // We need to relink all actors that may touch a linked line portal TThinkerIterator it; @@ -1144,7 +1042,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); + CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check); if (check.Size() > 0) { FLinkContext ctx; @@ -1164,25 +1062,19 @@ void P_CreateLinkedPortals() // //============================================================================ -bool P_CollectConnectedGroups(int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out) +bool FLevelLocals::CollectConnectedGroups(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. - static FPortalBits processMask; - static TArray foundPortals; - static TArray groupsToCheck; - bool retval = false; out.inited = true; - processMask.setSize(level.Displacements.size); - if (level.Displacements.size == 1) + processMask.setSize(Displacements.size); + if (Displacements.size == 1) { processMask.setBit(startgroup); return false; } - if (level.linkedPortals.Size() != 0) + if (linkedPortals.Size() != 0) { processMask.clear(); foundPortals.Clear(); @@ -1191,17 +1083,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 < linkedPortals.Size(); i++) { - line_t *ld = level.linkedPortals[i]->mOrigin; + line_t *ld = linkedPortals[i]->mOrigin; int othergroup = ld->frontsector->PortalGroup; - FDisplacement &disp = level.Displacements(thisgroup, othergroup); + FDisplacement &disp = 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(linkedPortals[i]->mOrigin) != -1) continue; // not touched + foundPortals.Push(linkedPortals[i]); } bool foundone = true; while (foundone) @@ -1228,7 +1120,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 = Displacements.getOffset(startgroup, othergroup) + position; if (processMask.getBit(othergroup)) break; processMask.setBit(othergroup); out.Add(othergroup | FPortalGroupArray::UPPER); @@ -1239,21 +1131,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 = 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 && 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 = Displacements.getOffset(startgroup, thisgroup & ~FPortalGroupArray::FLAT); FBoundingBox box(position.X + disp.X, position.Y + disp.Y, checkradius); FBlockLinesIterator it(box); line_t *ld; diff --git a/src/portal.h b/src/portal.h index 9aefb3a586..cb9d5c7a82 100644 --- a/src/portal.h +++ b/src/portal.h @@ -263,15 +263,6 @@ struct FSectorPortalGroup // //============================================================================ -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(int startgroup, const DVector3 &position, double upperz, double checkradius, FPortalGroupArray &out); -void P_CollectLinkedPortals(); -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); /* code ported from prototype */ @@ -280,7 +271,6 @@ 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); struct FLevelLocals; void InitPortalGroups(FLevelLocals *Level); diff --git a/src/scripting/vmthunks.cpp b/src/scripting/vmthunks.cpp index 9ed1f32864..d90e3b008d 100644 --- a/src/scripting/vmthunks.cpp +++ b/src/scripting/vmthunks.cpp @@ -2585,7 +2585,7 @@ static void Vec2Offset(double x, double y, double dx, double dy, bool absolute, } else { - *result = P_GetOffsetPosition(x, y, dx, dy); + *result = level.GetPortalOffsetPosition(x, y, dx, dy); } } @@ -2610,7 +2610,7 @@ 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 = level.GetPortalOffsetPosition(x, y, dx, dy); *result = (DVector3(v, atz)); } } @@ -2637,7 +2637,7 @@ 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 = level.GetPortalOffsetPosition(x, y, dx, dy); *result = (DVector3(v, z + dz)); } } diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index d83d90916b..61d713e6bc 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -695,6 +695,7 @@ struct LevelLocals native native void StartIntermission(Name type, int state) const; native SpotState GetSpotState(bool create = true); native int FindUniqueTid(int start = 0, int limit = 0); + native uint GetSkyboxPortal(Actor actor); native static clearscope bool IsPointInMap(vector3 p); diff --git a/wadsrc/static/zscript/mapdata.txt b/wadsrc/static/zscript/mapdata.txt index c7a7a51fdc..9d056ffed9 100644 --- a/wadsrc/static/zscript/mapdata.txt +++ b/wadsrc/static/zscript/mapdata.txt @@ -25,9 +25,7 @@ struct SectorPortal native play native Sector mDestination; native Vector2 mDisplacement; native double mPlaneZ; - native Actor mSkybox; - - native static uint GetSkyboxPortal(Actor actor); + native Actor mSkybox; }; diff --git a/wadsrc/static/zscript/shared/skies.txt b/wadsrc/static/zscript/shared/skies.txt index 825db9175d..f80ed8304e 100644 --- a/wadsrc/static/zscript/shared/skies.txt +++ b/wadsrc/static/zscript/shared/skies.txt @@ -119,7 +119,7 @@ class SkyPicker : Actor } else { - int boxindex = SectorPortal.GetSkyboxPortal(box); + int boxindex = level.GetSkyboxPortal(box); // Do not override special portal types, only regular skies. if (0 == (args[1] & 2)) {