diff --git a/src/actor.h b/src/actor.h index e7fe048ef9..d369e5fa92 100644 --- a/src/actor.h +++ b/src/actor.h @@ -959,11 +959,14 @@ public: // Triggers SECSPAC_Exit/SECSPAC_Enter and related events if oldsec != current sector void CheckSectorTransition(sector_t *oldsec); + void UpdateRenderSectorList(); + void ClearRenderSectorList(); // info for drawing // NOTE: The first member variable *must* be snext. AActor *snext, **sprev; // links in sector (if needed) DVector3 __Pos; // double underscores so that it won't get used by accident. Access to this should be exclusively through the designated access functions. + DVector3 OldRenderPos; DRotator Angles; DVector3 Vel; @@ -1094,6 +1097,8 @@ public: // a linked list of sectors where this object appears struct msecnode_t *touching_sectorlist; // phares 3/14/98 + struct msecnode_t *render_sectorlist; // same for cross-portal rendering + TObjPtr Inventory; // [RH] This actor's inventory DWORD InventoryID; // A unique ID to keep track of inventory items diff --git a/src/p_local.h b/src/p_local.h index a5336a9ee1..1a89154956 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -350,7 +350,8 @@ void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, void P_DelSector_List(); void P_DelSeclist(msecnode_t *); // phares 3/16/98 -msecnode_t* P_DelSecnode(msecnode_t *); +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 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 8254ac5bb0..d1cd918160 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -5555,6 +5555,7 @@ int P_PushUp(AActor *thing, FChangePosition *cpos) intersect->SetZ(oldz); return 2; } + intersect->UpdateRenderSectorList(); } thing->CheckPortalTransition(true); return 0; @@ -5602,6 +5603,7 @@ int P_PushDown(AActor *thing, FChangePosition *cpos) intersect->SetZ(oldz); return 2; } + intersect->UpdateRenderSectorList(); } } thing->CheckPortalTransition(true); @@ -5634,6 +5636,7 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos) { thing->SetZ(thing->floorz); P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); } } else if ((thing->Z() != oldfloorz && !(thing->flags & MF_NOLIFTDROP))) @@ -5642,6 +5645,7 @@ void PIT_FloorDrop(AActor *thing, FChangePosition *cpos) { thing->AddZ(-oldfloorz + thing->floorz); P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); } } if (thing->player && thing->player->mo == thing) @@ -5689,10 +5693,12 @@ void PIT_FloorRaise(AActor *thing, FChangePosition *cpos) { default: P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); break; case 1: P_DoCrunch(thing, cpos); P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); break; case 2: P_DoCrunch(thing, cpos); @@ -5735,6 +5741,7 @@ void PIT_CeilingLower(AActor *thing, FChangePosition *cpos) { thing->SetZ(thing->floorz); } + thing->UpdateRenderSectorList(); switch (P_PushDown(thing, cpos)) { case 2: @@ -5744,9 +5751,11 @@ void PIT_CeilingLower(AActor *thing, FChangePosition *cpos) thing->SetZ(thing->floorz); P_DoCrunch(thing, cpos); P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); break; default: P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); break; } } @@ -5782,6 +5791,7 @@ void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos) thing->SetZ(thing->ceilingz - thing->Height); } P_CheckFakeFloorTriggers(thing, oldz); + thing->UpdateRenderSectorList(); } else if ((thing->flags2 & MF2_PASSMOBJ) && !isgood && thing->Top() < thing->ceilingz) { @@ -5789,6 +5799,7 @@ void PIT_CeilingRaise(AActor *thing, FChangePosition *cpos) if (!P_TestMobjZ(thing, true, &onmobj) && onmobj->Z() <= thing->Z()) { thing->SetZ(MIN(thing->ceilingz - thing->Height, onmobj->Top())); + thing->UpdateRenderSectorList(); } } if (thing->player && thing->player->mo == thing) @@ -6023,7 +6034,7 @@ void P_PutSecnode(msecnode_t *node) // //============================================================================= -msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode) +msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist) { msecnode_t *node; @@ -6061,10 +6072,10 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode) // Add new node at head of sector thread starting at s->touching_thinglist node->m_sprev = NULL; // prev node on sector thread - node->m_snext = s->touching_thinglist; // next node on sector thread - if (s->touching_thinglist) + node->m_snext = sec_thinglist; // next node on sector thread + if (sec_thinglist) node->m_snext->m_sprev = node; - s->touching_thinglist = node; + sec_thinglist = node; return node; } @@ -6078,7 +6089,7 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode) // //============================================================================= -msecnode_t *P_DelSecnode(msecnode_t *node) +msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead) { msecnode_t* tp; // prev node on thing thread msecnode_t* tn; // next node on thing thread @@ -6105,7 +6116,7 @@ msecnode_t *P_DelSecnode(msecnode_t *node) if (sp) sp->m_snext = sn; else - node->m_sector->touching_thinglist = sn; + node->m_sector->*listhead = sn; if (sn) sn->m_sprev = sp; @@ -6145,7 +6156,7 @@ void P_DelSector_List() void P_DelSeclist(msecnode_t *node) { while (node) - node = P_DelSecnode(node); + node = P_DelSecnode(node, §or_t::touching_thinglist); } //============================================================================= @@ -6173,13 +6184,15 @@ void P_CreateSecNodeList(AActor *thing) node = node->m_tnext; } - FBoundingBox box(thing->X(), thing->Y(), thing->radius); - FBlockLinesIterator it(box); - line_t *ld; + FPortalGroupArray grouplist; + FMultiBlockLinesIterator mit(grouplist, thing); + FMultiBlockLinesIterator::CheckResult cres; - while ((ld = it.Next())) + while (mit.Next(&cres)) { - if (!box.inRange(ld) || box.BoxOnLineSide(ld) != -1) + line_t *ld = cres.line; + + if (!mit.Box().inRange(ld) || mit.Box().BoxOnLineSide(ld) != -1) continue; // This line crosses through the object. @@ -6189,7 +6202,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); + sector_list = P_AddSecnode(ld->frontsector, thing, sector_list, ld->frontsector->touching_thinglist); // Don't assume all lines are 2-sided, since some Things // like MT_TFOG are allowed regardless of whether their radius takes @@ -6199,12 +6212,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); + sector_list = P_AddSecnode(ld->backsector, thing, sector_list, ld->backsector->touching_thinglist); } // Add the sector of the (x,y) point to sector_list. - sector_list = P_AddSecnode(thing->Sector, thing, sector_list); + sector_list = P_AddSecnode(thing->Sector, thing, sector_list, thing->Sector->touching_thinglist); // Now delete any nodes that won't be used. These are the ones where // m_thing is still NULL. @@ -6216,7 +6229,7 @@ void P_CreateSecNodeList(AActor *thing) { if (node == sector_list) sector_list = node->m_tnext; - node = P_DelSecnode(node); + node = P_DelSecnode(node, §or_t::touching_thinglist); } else { @@ -6225,6 +6238,54 @@ void P_CreateSecNodeList(AActor *thing) } } + +//========================================================================== +// +// Handle the lists used to render actors from other portal areas +// +//========================================================================== + +void AActor::UpdateRenderSectorList() +{ + static const double SPRITE_SPACE = 64.; + if (Pos() != OldRenderPos) + { + sector_t *sec = Sector; + double lasth = -FLT_MAX; + ClearRenderSectorList(); + while (!sec->PortalBlocksMovement(sector_t::ceiling)) + { + double planeh = sec->SkyBoxes[sector_t::ceiling]->specialf1; + if (planeh < lasth) break; // broken setup. + if (Top() + SPRITE_SPACE < planeh) break; + lasth = planeh; + DVector2 newpos = Pos() + sec->SkyBoxes[sector_t::ceiling]->Scale; + sec = P_PointInSector(newpos); + render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); + } + lasth = FLT_MAX; + while (!sec->PortalBlocksMovement(sector_t::floor)) + { + double planeh = sec->SkyBoxes[sector_t::floor]->specialf1; + if (planeh > lasth) break; // broken setup. + if (Z() - SPRITE_SPACE > planeh) break; + lasth = planeh; + DVector2 newpos = Pos() + sec->SkyBoxes[sector_t::floor]->Scale; + sec = P_PointInSector(newpos); + render_sectorlist = P_AddSecnode(sec, this, render_sectorlist, sec->render_thinglist); + } + } +} + +void AActor::ClearRenderSectorList() +{ + msecnode_t *node = render_sectorlist; + while (node) + node = P_DelSecnode(node, §or_t::render_thinglist); + render_sectorlist = NULL; +} + + //========================================================================== // // diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index f018be55b5..18caa2f3c1 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3752,6 +3752,9 @@ void AActor::Tick () if (!CheckNoDelay()) return; // freed itself // cycle through states, calling action functions at transitions + + UpdateRenderSectorList(); + if (tics != -1) { // [RH] Use tics <= 0 instead of == 0 so that spawnstates @@ -4011,6 +4014,7 @@ AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t a } actor->SetXYZ(pos); + actor->OldRenderPos = { FLT_MAX, FLT_MAX, FLT_MAX }; actor->picnum.SetInvalid(); actor->health = actor->SpawnHealth(); @@ -4322,12 +4326,15 @@ void AActor::Deactivate (AActor *activator) } } + // // P_RemoveMobj // void AActor::Destroy () { + ClearRenderSectorList(); + // [RH] Destroy any inventory this actor is carrying DestroyAllInventory (); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 148dcbea85..718e54e9b6 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1510,6 +1510,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) tagManager.AddSectorTag(i, LittleShort(ms->tag)); ss->thinglist = NULL; ss->touching_thinglist = NULL; // phares 3/14/98 + ss->render_thinglist = NULL; 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 017f73cf15..20852a5858 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1291,6 +1291,7 @@ public: sec->SetAlpha(sector_t::ceiling, 1.); sec->thinglist = NULL; sec->touching_thinglist = NULL; // phares 3/14/98 + sec->render_thinglist = NULL; 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 30a849b846..4860440704 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2860,8 +2860,6 @@ void P_PredictPlayer (player_t *player) } } -extern msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode); - void P_UnPredictPlayer () { player_t *player = &players[consoleplayer]; @@ -2922,7 +2920,7 @@ void P_UnPredictPlayer () sector_list = NULL; for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;) { - sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list); + sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist); } act->touching_sectorlist = sector_list; // Attach to thing sector_list = NULL; // clear for next time @@ -2934,7 +2932,7 @@ void P_UnPredictPlayer () { if (node == sector_list) sector_list = node->m_tnext; - node = P_DelSecnode(node); + node = P_DelSecnode(node, §or_t::touching_thinglist); } else { diff --git a/src/r_defs.h b/src/r_defs.h index 2b7b4a218f..79af0929f2 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -1057,6 +1057,7 @@ public: // list of mobjs that are at least partially in the sector // 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. double gravity; // [RH] Sector gravity (1.0 is normal) FNameNoInit damagetype; // [RH] Means-of-death for applied damage