diff --git a/game-music-emu/gme/gme_types.h b/game-music-emu/gme/gme_types.h old mode 100644 new mode 100755 index 06226f4aa..bd3670e64 --- a/game-music-emu/gme/gme_types.h +++ b/game-music-emu/gme/gme_types.h @@ -1,11 +1,13 @@ #ifndef GME_TYPES_H #define GME_TYPES_H -/* - * This is a default gme_types.h for use when *not* using - * CMake. If CMake is in use gme_types.h.in will be - * processed instead. +/* CMake will either define the following to 1, or #undef it, + * depending on the options passed to CMake. This is used to + * conditionally compile in the various emulator types. + * + * See gme_type_list() in gme.cpp */ + #define USE_GME_AY #define USE_GME_GBS #define USE_GME_GYM diff --git a/src/actor.h b/src/actor.h index 03891c8ba..5445c92be 100644 --- a/src/actor.h +++ b/src/actor.h @@ -33,6 +33,7 @@ // States are tied to finite states are tied to animation frames. #include "info.h" +#include #include "doomdef.h" #include "textures/textures.h" #include "r_data/renderstyle.h" @@ -561,8 +562,15 @@ inline T *GetDefault () struct line_t; struct secplane_t; +struct msecnode_t; struct FStrifeDialogueNode; +struct FLinkContext +{ + msecnode_t *sector_list = nullptr; + msecnode_t *render_list = nullptr; +}; + class DDropItem : public DObject { DECLARE_CLASS(DDropItem, DObject) @@ -1035,6 +1043,7 @@ public: struct sector_t *ceilingsector; FTextureID ceilingpic; // contacted sec ceilingpic double radius, Height; // for movement checking + double renderradius; double projectilepassheight; // height for clipping projectile movement against this actor @@ -1141,6 +1150,8 @@ public: struct msecnode_t *touching_sectorlist; // phares 3/14/98 struct msecnode_t *render_sectorlist; // same for cross-sectorportal rendering struct portnode_t *render_portallist; // and for cross-lineportal + struct msecnode_t *touching_rendersectors; // this is the list of sectors that this thing interesects with it's max(radius, renderradius). + int validcount; TObjPtr Inventory; // [RH] This actor's inventory @@ -1216,8 +1227,8 @@ private: bool FixMapthingPos(); public: - void LinkToWorld (bool spawningmapthing=false, sector_t *sector = NULL); - void UnlinkFromWorld (); + void LinkToWorld (FLinkContext *ctx, bool spawningmapthing=false, sector_t *sector = NULL); + void UnlinkFromWorld(FLinkContext *ctx); void AdjustFloorClip (); bool InStateSequence(FState * newstate, FState * basestate); int GetTics(FState * newstate); diff --git a/src/b_game.cpp b/src/b_game.cpp index 9d6419787..b99b97a60 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -118,23 +118,24 @@ void FCajunMaster::Main () } //Check if player should go observer. Or un observe + FLinkContext ctx; if (bot_observer && !observer && !netgame) { Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); observer = true; - players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; players[consoleplayer].mo->flags2 |= MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); + players[consoleplayer].mo->LinkToWorld (&ctx); } else if (!bot_observer && observer && !netgame) //Go back { Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); observer = false; - players[consoleplayer].mo->UnlinkFromWorld (); + players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; players[consoleplayer].mo->flags2 &= ~MF2_FLY; - players[consoleplayer].mo->LinkToWorld (); + players[consoleplayer].mo->LinkToWorld (&ctx); } } diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index 42af5e87f..f019a8053 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -636,14 +636,9 @@ void AInventory::BecomeItem () { if (!(flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) { - UnlinkFromWorld (); - if (sector_list) - { - P_DelSeclist (sector_list); - sector_list = NULL; - } + UnlinkFromWorld (nullptr); flags |= MF_NOBLOCKMAP|MF_NOSECTOR; - LinkToWorld (); + LinkToWorld (nullptr); } RemoveFromHash (); flags &= ~MF_SPECIAL; @@ -674,9 +669,9 @@ void AInventory::BecomePickup () } if (flags & (MF_NOBLOCKMAP|MF_NOSECTOR)) { - UnlinkFromWorld (); + UnlinkFromWorld (nullptr); flags &= ~(MF_NOBLOCKMAP|MF_NOSECTOR); - LinkToWorld (); + LinkToWorld (nullptr); P_FindFloorCeiling (this); } flags = (GetDefault()->flags | MF_DROPPED) & ~MF_COUNTITEM; diff --git a/src/g_level.cpp b/src/g_level.cpp index c13e71ee6..f8ccd13be 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1196,8 +1196,7 @@ void G_StartTravel () // Only living players travel. Dead ones get a new body on the new level. if (players[i].health > 0) { - pawn->UnlinkFromWorld (); - P_DelSector_List (); + pawn->UnlinkFromWorld (nullptr); int tid = pawn->tid; // Save TID pawn->RemoveFromHash (); pawn->tid = tid; // Restore TID (but no longer linked into the hash chain) @@ -1206,8 +1205,7 @@ void G_StartTravel () for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { inv->ChangeStatNum (STAT_TRAVELLING); - inv->UnlinkFromWorld (); - P_DelSector_List (); + inv->UnlinkFromWorld (nullptr); } } } @@ -1304,7 +1302,7 @@ void G_FinishTravel () { pawndup->Destroy(); } - pawn->LinkToWorld (); + pawn->LinkToWorld (nullptr); pawn->ClearInterpolation(); pawn->AddToHash (); pawn->SetState(pawn->SpawnState); @@ -1313,7 +1311,7 @@ void G_FinishTravel () for (inv = pawn->Inventory; inv != NULL; inv = inv->Inventory) { inv->ChangeStatNum (STAT_INVENTORY); - inv->LinkToWorld (); + inv->LinkToWorld (nullptr); inv->Travelled (); } if (ib_compatflags & BCOMPATF_RESETPLAYERSPEED) diff --git a/src/g_pch.h b/src/g_pch.h index a22649815..2c3676f5a 100644 --- a/src/g_pch.h +++ b/src/g_pch.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index a1ffe5dc6..c09d93fd5 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -364,6 +364,7 @@ void APathFollower::NewNode () bool APathFollower::Interpolate () { DVector3 dpos(0, 0, 0); + FLinkContext ctx; if ((args[2] & 8) && Time > 0.f) { @@ -372,7 +373,7 @@ bool APathFollower::Interpolate () if (CurrNode->Next==NULL) return false; - UnlinkFromWorld (); + UnlinkFromWorld (&ctx); DVector3 newpos; if (args[2] & 1) { // linear @@ -389,7 +390,7 @@ bool APathFollower::Interpolate () newpos.Z = Splerp(PrevNode->Z(), CurrNode->Z(), CurrNode->Next->Z(), CurrNode->Next->Next->Z()); } SetXYZ(newpos); - LinkToWorld (); + LinkToWorld (&ctx); if (args[2] & 6) { @@ -541,10 +542,11 @@ void AActorMover::Activate (AActor *activator) tracer->flags |= MF_NOGRAVITY; if (args[2] & 128) { - tracer->UnlinkFromWorld (); + FLinkContext ctx; + tracer->UnlinkFromWorld (&ctx); tracer->flags |= MF_NOBLOCKMAP; tracer->flags &= ~MF_SOLID; - tracer->LinkToWorld (); + tracer->LinkToWorld (&ctx); } if (tracer->flags3 & MF3_ISMONSTER) { @@ -563,9 +565,10 @@ void AActorMover::Deactivate (AActor *activator) Super::Deactivate (activator); if (tracer != NULL) { - tracer->UnlinkFromWorld (); + FLinkContext ctx; + tracer->UnlinkFromWorld (&ctx); tracer->flags = ActorFlags::FromInt (special1); - tracer->LinkToWorld (); + tracer->LinkToWorld (&ctx); tracer->flags2 = ActorFlags2::FromInt (special2); } } diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index e292447bf..4136ec331 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -5229,12 +5229,13 @@ void A_Weave(AActor *self, int xyspeed, int zspeed, double xydist, double zdist) } else { - self->UnlinkFromWorld (); + FLinkContext ctx; + self->UnlinkFromWorld (&ctx); self->flags |= MF_NOBLOCKMAP; // We need to do portal offsetting here explicitly, because SetXY cannot do that. newpos -= self->Pos().XY(); self->SetXY(self->Vec2Offset(newpos.X, newpos.Y)); - self->LinkToWorld (); + self->LinkToWorld (&ctx); } self->WeaveIndexXY = weaveXY; } @@ -6862,17 +6863,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_SetSize) double oldradius = self->radius; double oldheight = self->Height; - self->UnlinkFromWorld(); + FLinkContext ctx; + self->UnlinkFromWorld(&ctx); self->radius = newradius; self->Height = newheight; - self->LinkToWorld(); + self->LinkToWorld(&ctx); if (testpos && !P_TestMobjLocation(self)) { - self->UnlinkFromWorld(); + self->UnlinkFromWorld(&ctx); self->radius = oldradius; self->Height = oldheight; - self->LinkToWorld(); + self->LinkToWorld(&ctx); ACTION_RETURN_BOOL(false); } diff --git a/src/p_local.h b/src/p_local.h index ef702e018..93bbbbf11 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -245,10 +245,6 @@ AActor *P_RoughMonsterSearch (AActor *mo, int distance, bool onlyseekable=false, // -// If "floatok" true, move would be ok -// if within "tmfloorz - tmceilingz". -extern msecnode_t *sector_list; // phares 3/16/98 - struct spechit_t { line_t *line; @@ -395,11 +391,10 @@ enum int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, int flags, int fulldamagedistance=0); -void P_DelSector_List(); -void P_DelSeclist(msecnode_t *); // phares 3/16/98 +void P_DelSeclist(msecnode_t *, msecnode_t *sector_t::*seclisthead); msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist); msecnode_t* P_DelSecnode(msecnode_t *, msecnode_t *sector_t::*head); -void P_CreateSecNodeList(AActor*); // phares 3/14/98 +msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead); double P_GetMoveFactor(const AActor *mo, double *frictionp); // phares 3/6/98 double P_GetFriction(const AActor *mo, double *frictionfactor); diff --git a/src/p_map.cpp b/src/p_map.cpp index 81934ceb7..85c3e3da8 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "templates.h" @@ -81,9 +82,6 @@ static FRandom pr_crunch("DoCrunch"); TArray spechit; TArray portalhit; -// Temporary holder for thing_sectorlist threads -msecnode_t* sector_list = NULL; // phares 3/16/98 - //========================================================================== // // FindRefPoint @@ -2389,10 +2387,11 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, FLinePortal *port = ld->getPortal(); if (port->mType == PORTT_LINKED) { - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); thing->SetXY(tm.pos + port->mDisplacement); thing->Prev += port->mDisplacement; - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); portalcrossed = true; tm.portalstep = false; @@ -2413,11 +2412,12 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, thing->flags6 &= ~MF6_INTRYMOVE; return false; } - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); thing->SetXYZ(pos); P_TranslatePortalVXVY(ld, thing->Vel.X, thing->Vel.Y); P_TranslatePortalAngle(ld, thing->Angles.Yaw); - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); thing->ClearInterpolation(); portalcrossed = true; @@ -2458,7 +2458,8 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, if (!portalcrossed) { // the move is ok, so link the thing into its new position - thing->UnlinkFromWorld(); + FLinkContext ctx; + thing->UnlinkFromWorld(&ctx); oldsector = thing->Sector; thing->floorz = tm.floorz; @@ -2471,7 +2472,7 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, thing->ceilingsector = tm.ceilingsector; thing->SetXY(pos); - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); } if (thing->flags2 & MF2_FLOORCLIP) @@ -2564,13 +2565,14 @@ bool P_TryMove(AActor *thing, const DVector2 &pos, // If the actor stepped through a ceiling portal we need to reacquire the actual position info after the transition if (tm.portalstep) { + FLinkContext ctx; DVector3 oldpos = thing->Pos(); - thing->UnlinkFromWorld(); + thing->UnlinkFromWorld(&ctx); thing->SetXYZ(thing->PosRelative(thing->Sector->GetOppositePortalGroup(sector_t::ceiling))); thing->Prev = thing->Pos() - oldpos; thing->Sector = P_PointInSector(thing->Pos()); thing->PrevPortalGroup = thing->Sector->PortalGroup; - thing->LinkToWorld(); + thing->LinkToWorld(&ctx); P_FindFloorCeiling(thing); } @@ -6531,23 +6533,6 @@ msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) return NULL; } // phares 3/13/98 -//============================================================================= -// -// P_DelSector_List -// -// Deletes the sector_list and NULLs it. -// -//============================================================================= - -void P_DelSector_List() -{ - if (sector_list != NULL) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } -} - //============================================================================= // // P_DelSeclist @@ -6556,10 +6541,10 @@ void P_DelSector_List() // //============================================================================= -void P_DelSeclist(msecnode_t *node) +void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead) { while (node) - node = P_DelSecnode(node, §or_t::touching_thinglist); + node = P_DelSecnode(node, sechead); } //============================================================================= @@ -6571,7 +6556,7 @@ void P_DelSeclist(msecnode_t *node) // //============================================================================= -void P_CreateSecNodeList(AActor *thing) +msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector_list, msecnode_t *sector_t::*seclisthead) { msecnode_t *node; @@ -6587,7 +6572,7 @@ void P_CreateSecNodeList(AActor *thing) node = node->m_tnext; } - FBoundingBox box(thing->X(), thing->Y(), thing->radius); + FBoundingBox box(thing->X(), thing->Y(), radius); FBlockLinesIterator it(box); line_t *ld; @@ -6603,7 +6588,7 @@ void P_CreateSecNodeList(AActor *thing) // allowed to move to this position, then the sector_list // will be attached to the Thing's AActor at touching_sectorlist. - sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->touching_thinglist); + sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->*seclisthead); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -6613,12 +6598,12 @@ void P_CreateSecNodeList(AActor *thing) // Use sidedefs instead of 2s flag to determine two-sidedness. if (ld->backsector) - sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->touching_thinglist); + sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->*seclisthead); } // Add the sector of the (x,y) point to sector_list. - sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->touching_thinglist); + sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->*seclisthead); // Now delete any nodes that won't be used. These are the ones where // m_thing is still NULL. @@ -6630,16 +6615,16 @@ void P_CreateSecNodeList(AActor *thing) { if (node == sector_list) sector_list = node->m_tnext; - node = P_DelSecnode(node, §or_t::touching_thinglist); + node = P_DelSecnode(node, seclisthead); } else { node = node->m_tnext; } } + return sector_list; } - //============================================================================= // // P_DelPortalnode @@ -6770,6 +6755,7 @@ void AActor::UpdateRenderSectorList() sec = P_PointInSector(newpos); render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); } + sec = Sector; lasth = FLT_MAX; while (!sec->PortalBlocksMovement(sector_t::floor)) { diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index d676e966c..d4ac79ce7 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -242,9 +242,9 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, co // //========================================================================== -void AActor::UnlinkFromWorld () +void AActor::UnlinkFromWorld (FLinkContext *ctx) { - sector_list = NULL; + if (ctx != nullptr) ctx->sector_list = nullptr; if (!(flags & MF_NOSECTOR)) { // invisible things don't need to be in sector list @@ -271,12 +271,19 @@ void AActor::UnlinkFromWorld () // put it back into touching_sectorlist. It's done this way to // avoid a lot of deleting/creating for nodes, when most of the // time you just get back what you deleted anyway. - // - // If this Thing is being removed entirely, then the calling - // routine will clear out the nodes in sector_list. - sector_list = touching_sectorlist; - touching_sectorlist = NULL; //to be restored by P_SetThingPosition + if (ctx != nullptr) + { + ctx->sector_list = touching_sectorlist; + ctx->render_list = touching_rendersectors; + } + else + { + P_DelSeclist(touching_sectorlist, §or_t::touching_thinglist); + P_DelSeclist(touching_rendersectors, §or_t::touching_renderthings); + } + touching_sectorlist = nullptr; //to be restored by P_SetThingPosition + touching_rendersectors = nullptr; } } @@ -388,7 +395,7 @@ bool AActor::FixMapthingPos() DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld) { PARAM_SELF_PROLOGUE(AActor); - self->UnlinkFromWorld(); + self->UnlinkFromWorld(nullptr); // fixme return 0; } @@ -401,7 +408,7 @@ DEFINE_ACTION_FUNCTION(AActor, UnlinkFromWorld) // //========================================================================== -void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) +void AActor::LinkToWorld(FLinkContext *ctx, bool spawningmapthing, sector_t *sector) { bool spawning = spawningmapthing; @@ -453,9 +460,13 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) // When a node is deleted, its sector links (the links starting // at sector_t->touching_thinglist) are broken. When a node is // added, new sector links are created. - P_CreateSecNodeList(this); - touching_sectorlist = sector_list; // Attach to thing - sector_list = NULL; // clear for next time + touching_sectorlist = P_CreateSecNodeList(this, radius, ctx != nullptr? ctx->sector_list : nullptr, §or_t::touching_thinglist); // Attach to thing + if (renderradius >= 0) touching_rendersectors = P_CreateSecNodeList(this, MAX(radius, renderradius), ctx != nullptr ? ctx->render_list : nullptr, §or_t::touching_renderthings); + else + { + touching_rendersectors = nullptr; + if (ctx != nullptr) P_DelSeclist(ctx->render_list, §or_t::touching_renderthings); + } } @@ -518,15 +529,16 @@ void AActor::LinkToWorld(bool spawningmapthing, sector_t *sector) DEFINE_ACTION_FUNCTION(AActor, LinkToWorld) { PARAM_SELF_PROLOGUE(AActor); - self->LinkToWorld(); + self->LinkToWorld(nullptr); // fixme return 0; } void AActor::SetOrigin(double x, double y, double z, bool moving) { - UnlinkFromWorld (); + FLinkContext ctx; + UnlinkFromWorld (&ctx); SetXYZ(x, y, z); - LinkToWorld (); + LinkToWorld (&ctx); P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS); if (!moving) ClearInterpolation(); } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 72ddd9395..7e5dbc88e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -204,6 +204,7 @@ DEFINE_FIELD(AActor, ceilingsector) DEFINE_FIELD(AActor, ceilingpic) DEFINE_FIELD(AActor, Height) DEFINE_FIELD(AActor, radius) +DEFINE_FIELD(AActor, renderradius) DEFINE_FIELD(AActor, projectilepassheight) DEFINE_FIELD(AActor, tics) DEFINE_FIELD_NAMED(AActor, state, curstate) // clashes with type 'state'. @@ -373,6 +374,7 @@ void AActor::Serialize(FSerializer &arc) A("floorsector", floorsector) A("ceilingsector", ceilingsector) A("radius", radius) + A("renderradius", renderradius) A("height", Height) A("ppassheight", projectilepassheight) A("vel", Vel) @@ -509,8 +511,9 @@ void AActor::Serialize(FSerializer &arc) void AActor::PostSerialize() { - touching_sectorlist = NULL; - LinkToWorld(false, Sector); + touching_sectorlist = nullptr; + touching_rendersectors = nullptr; + LinkToWorld(nullptr, false, Sector); AddToHash(); if (player) @@ -3686,12 +3689,13 @@ DVector3 AActor::GetPortalTransition(double byoffset, sector_t **pSec) void AActor::CheckPortalTransition(bool islinked) { bool moved = false; + FLinkContext ctx; while (!Sector->PortalBlocksMovement(sector_t::ceiling)) { if (Z() >= Sector->GetPortalPlaneZ(sector_t::ceiling)) { DVector3 oldpos = Pos(); - if (islinked && !moved) UnlinkFromWorld(); + if (islinked && !moved) UnlinkFromWorld(&ctx); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::ceiling))); Prev = Pos() - oldpos; Sector = P_PointInSector(Pos()); @@ -3708,7 +3712,7 @@ void AActor::CheckPortalTransition(bool islinked) if (Z() < portalz && floorz < portalz) { DVector3 oldpos = Pos(); - if (islinked && !moved) UnlinkFromWorld(); + if (islinked && !moved) UnlinkFromWorld(&ctx); SetXYZ(PosRelative(Sector->GetOppositePortalGroup(sector_t::floor))); Prev = Pos() - oldpos; Sector = P_PointInSector(Pos()); @@ -3718,7 +3722,7 @@ void AActor::CheckPortalTransition(bool islinked) else break; } } - if (islinked && moved) LinkToWorld(); + if (islinked && moved) LinkToWorld(&ctx); } // @@ -3781,11 +3785,12 @@ void AActor::Tick () if (!Vel.isZero() || !(flags & MF_NOBLOCKMAP)) { - UnlinkFromWorld(); + FLinkContext ctx; + UnlinkFromWorld(&ctx); flags |= MF_NOBLOCKMAP; SetXYZ(Vec3Offset(Vel)); CheckPortalTransition(false); - LinkToWorld(); + LinkToWorld(&ctx); } } else @@ -4543,12 +4548,13 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a actor->sprite = st->sprite; actor->frame = st->GetFrame(); actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | ActorRenderFlags::FromInt (st->GetFullbright()); - actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 + actor->touching_sectorlist = nullptr; // NULL head of sector list // phares 3/13/98 + actor->touching_rendersectors = nullptr; if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0) actor->Speed = actor->GetClass()->FastSpeed; // set subsector and/or block links - actor->LinkToWorld (SpawningMapThing); + actor->LinkToWorld (nullptr, SpawningMapThing); actor->ClearInterpolation(); actor->dropoffz = actor->floorz = actor->Sector->floorplane.ZatPoint(pos); @@ -4925,12 +4931,9 @@ void AActor::Destroy () RemoveFromHash (); // unlink from sector and block lists - UnlinkFromWorld (); + UnlinkFromWorld (nullptr); flags |= MF_NOSECTOR|MF_NOBLOCKMAP; - // Delete all nodes on the current sector_list phares 3/16/98 - P_DelSector_List(); - // Transform any playing sound into positioned, non-actor sounds. S_RelinkSound (this, NULL); @@ -7481,9 +7484,10 @@ void AActor::RestoreSpecialPosition() // Move item back to its original location DVector2 sp = SpawnPoint; - UnlinkFromWorld(); + FLinkContext ctx; + UnlinkFromWorld(&ctx); SetXY(sp); - LinkToWorld(true); + LinkToWorld(&ctx, true); SetZ(Sector->floorplane.ZatPoint(sp)); P_FindFloorCeiling(this, FFCF_ONLYSPAWNPOS | FFCF_NOPORTALS); // no portal checks here so that things get spawned in this sector. diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 11aef9d8d..d3bcc742d 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1509,9 +1509,10 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) else // [RH] Translate to new sector special ss->special = P_TranslateSectorSpecial (LittleShort(ms->special)); tagManager.AddSectorTag(i, LittleShort(ms->tag)); - ss->thinglist = NULL; - ss->touching_thinglist = NULL; // phares 3/14/98 - ss->render_thinglist = NULL; + ss->thinglist = nullptr; + ss->touching_thinglist = nullptr; // phares 3/14/98 + ss->render_thinglist = nullptr; + ss->touching_renderthings = nullptr; ss->seqType = defSeqType; ss->SeqName = NAME_None; ss->nextsec = -1; //jff 2/26/98 add fields to support locking out diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index c1a64f84b..2ef8a9ced 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1294,9 +1294,10 @@ public: sec->SetYScale(sector_t::ceiling, 1.); sec->SetAlpha(sector_t::floor, 1.); sec->SetAlpha(sector_t::ceiling, 1.); - sec->thinglist = NULL; - sec->touching_thinglist = NULL; // phares 3/14/98 - sec->render_thinglist = NULL; + sec->thinglist = nullptr; + sec->touching_thinglist = nullptr; // phares 3/14/98 + sec->render_thinglist = nullptr; + sec->touching_renderthings = nullptr; sec->seqType = (level.flags & LEVEL_SNDSEQTOTALCTRL) ? 0 : -1; sec->nextsec = -1; //jff 2/26/98 add fields to support locking out sec->prevsec = -1; // stair retriggering until build completes diff --git a/src/p_user.cpp b/src/p_user.cpp index 28047b4e2..c8f30e0d7 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2940,7 +2940,8 @@ void P_UnPredictPlayer () // could cause it to change during prediction. player->camera = savedcamera; - act->UnlinkFromWorld(); + FLinkContext ctx; + act->UnlinkFromWorld(&ctx); memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act)); // The blockmap ordering needs to remain unchanged, too. @@ -2969,7 +2970,7 @@ void P_UnPredictPlayer () } // Destroy old refrences - msecnode_t *node = sector_list; + msecnode_t *node = ctx.sector_list; while (node) { node->m_thing = NULL; @@ -2977,22 +2978,23 @@ void P_UnPredictPlayer () } // Make the sector_list match the player's touching_sectorlist before it got predicted. - P_DelSeclist(sector_list); - sector_list = NULL; + P_DelSeclist(ctx.sector_list, §or_t::touching_thinglist); + ctx.sector_list = NULL; for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); + ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); } - act->touching_sectorlist = sector_list; // Attach to thing - sector_list = NULL; // clear for next time + act->touching_sectorlist = ctx.sector_list; // Attach to thing + ctx.sector_list = NULL; // clear for next time - node = sector_list; + // Huh??? + node = ctx.sector_list; while (node) { if (node->m_thing == NULL) { - if (node == sector_list) - sector_list = node->m_tnext; + if (node == ctx.sector_list) + ctx.sector_list = node->m_tnext; node = P_DelSecnode(node, §or_t::touching_thinglist); } else diff --git a/src/portal.cpp b/src/portal.cpp index 156643cfb..121b05e19 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1140,8 +1140,9 @@ void P_CreateLinkedPortals() P_CollectConnectedGroups(actor->Sector->PortalGroup, actor->Pos(), actor->Top(), actor->radius, check); if (check.Size() > 0) { - actor->UnlinkFromWorld(); - actor->LinkToWorld(); + FLinkContext ctx; + actor->UnlinkFromWorld(&ctx); + actor->LinkToWorld(&ctx); } } } diff --git a/src/r_defs.h b/src/r_defs.h index ca29bb632..36318be85 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -23,6 +23,7 @@ #ifndef __R_DEFS_H__ #define __R_DEFS_H__ +#include #include "doomdef.h" #include "templates.h" #include "memarena.h" @@ -1048,6 +1049,7 @@ public: // thinglist is a subset of touching_thinglist struct msecnode_t *touching_thinglist; // phares 3/14/98 struct msecnode_t *render_thinglist; // for cross-portal rendering. + struct msecnode_t *touching_renderthings; // this is used to allow wide things to be rendered not only from their main sector. double gravity; // [RH] Sector gravity (1.0 is normal) FNameNoInit damagetype; // [RH] Means-of-death for applied damage diff --git a/src/r_things.cpp b/src/r_things.cpp index 472ecc8ea..40fbf782a 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -769,7 +769,7 @@ void R_DrawVisVoxel(vissprite_t *spr, int minslabz, int maxslabz, short *cliptop // R_ProjectSprite // Generates a vissprite for a thing if it might be visible. // -void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling) +void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor *fakeceiling, sector_t *current_sector) { double tr_x; double tr_y; @@ -1141,6 +1141,10 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor } FDynamicColormap *mybasecolormap = basecolormap; + if (current_sector->sectornum != thing->Sector->sectornum) // compare sectornums to account for R_FakeFlat copies. + { + // Todo: The actor is from a different sector so we have to retrieve the proper basecolormap for that sector. + } // Sprites that are added to the scene must fade to black. if (vis->Style.RenderStyle == LegacyRenderStyles[STYLE_Add] && mybasecolormap->Fade != 0) @@ -1274,7 +1278,6 @@ static void R_ProjectWallSprite(AActor *thing, const DVector3 &pos, FTextureID p // [RH] Save which side of heightsec sprite is on here. void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) { - AActor *thing; F3DFloor *fakeceiling = NULL; F3DFloor *fakefloor = NULL; @@ -1282,7 +1285,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) // A sector might have been split into several // subsectors during BSP building. // Thus we check whether it was already added. - if (sec->thinglist == NULL || sec->validcount == validcount) + if (sec->touching_renderthings == nullptr || sec->validcount == validcount) return; // Well, now it will be done. @@ -1291,8 +1294,12 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) spriteshade = LIGHT2SHADE(lightlevel + r_actualextralight); // Handle all things in sector. - for (thing = sec->thinglist; thing; thing = thing->snext) + for(auto p = sec->touching_renderthings; p != nullptr; p = p->m_snext) { + auto thing = p->m_thing; + if (thing->validcount == validcount) continue; + thing->validcount = validcount; + FIntCVar *cvar = thing->GetClass()->distancecheck; if (cvar != NULL && *cvar >= 0) { @@ -1305,7 +1312,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) } // find fake level - for(auto rover : frontsector->e->XFloor.ffloors) + for(auto rover : thing->Sector->e->XFloor.ffloors) { if(!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) continue; if(!(rover->flags & FF_SOLID) || rover->alpha != 255) continue; @@ -1321,7 +1328,7 @@ void R_AddSprites (sector_t *sec, int lightlevel, int fakeside) if(rover->bottom.plane->ZatPoint(0., 0.) >= thing->Top()) fakeceiling = rover; } } - R_ProjectSprite (thing, fakeside, fakefloor, fakeceiling); + R_ProjectSprite (thing, fakeside, fakefloor, fakeceiling, sec); fakeceiling = NULL; fakefloor = NULL; } diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index e318a9806..27b7ab2d3 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -216,9 +216,10 @@ bool ModActorFlag(AActor *actor, FString &flagname, bool set, bool printerror) // If these 2 flags get changed we need to update the blockmap and sector links. bool linkchange = flagp == &actor->flags && (fd->flagbit == MF_NOBLOCKMAP || fd->flagbit == MF_NOSECTOR); - if (linkchange) actor->UnlinkFromWorld(); + FLinkContext ctx; + if (linkchange) actor->UnlinkFromWorld(&ctx); ModActorFlag(actor, fd, set); - if (linkchange) actor->LinkToWorld(); + if (linkchange) actor->LinkToWorld(&ctx); } if (actor->CountsAsKill() && actor->health > 0) ++level.total_monsters; @@ -713,6 +714,15 @@ DEFINE_PROPERTY(radius, F, Actor) defaults->radius = id; } +//========================================================================== +// +//========================================================================== +DEFINE_PROPERTY(renderradius, F, Actor) +{ + PROP_DOUBLE_PARM(id, 0); + defaults->renderradius = id; +} + //========================================================================== // //========================================================================== diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 4324f162a..2ced709ae 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -45,6 +45,7 @@ class Actor : Thinker native native TextureID ceilingpic; native double Height; native readonly double Radius; + native readonly double RenderRadius; native double projectilepassheight; native int tics; native readonly State CurState; @@ -201,6 +202,7 @@ class Actor : Thinker native Health DEFAULT_HEALTH; Reactiontime 8; Radius 20; + RenderRadius 0; Height 16; Mass 100; RenderStyle 'Normal'; diff --git a/wadsrc/static/zscript/shared/bridge.txt b/wadsrc/static/zscript/shared/bridge.txt index ea38796a7..6fb0a99d5 100644 --- a/wadsrc/static/zscript/shared/bridge.txt +++ b/wadsrc/static/zscript/shared/bridge.txt @@ -85,6 +85,7 @@ class InvisibleBridge : Actor native { RenderStyle "None"; Radius 32; + RenderRadius -1; Height 4; +SOLID +NOGRAVITY