mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-11 07:12:16 +00:00
- added a new sector list to AActor that collects all portal-linked sectors the actor's center is in. (Inspired by Eternity's solution to the same problem.)
This is for rendering the sprite properly in all areas the actor touches. The original thinglist is not sufficient for this and Boom's touching thinglist has other purposes and collects too much data. This new list will only get filled in when the actor is actually crossing a portal plane, for the normal sector thinglist will still be used. This piggybacks on the msecnode_t code which has been extended to be able to handle more than one list by passing the sector's membert pointers as parameters.
This commit is contained in:
parent
f66202aef1
commit
54d78df267
8 changed files with 96 additions and 21 deletions
|
@ -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<AInventory> Inventory; // [RH] This actor's inventory
|
||||
DWORD InventoryID; // A unique ID to keep track of inventory items
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -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 ();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue