mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2024-11-23 20:32:51 +00:00
- let the prediction code handle all 4 threaded lists an actor gets linked into.
This is mostly a straight refactoring of the existing code to work independently of specific member variables in the involved classes, using a bit of template magic to avoid redundancy and moving the work code into subfunctions. It still needs some testing to see if it a) helps fix the crash issues and b) doesn't break anything-
This commit is contained in:
parent
c52bc06e9b
commit
62ea83a35a
4 changed files with 173 additions and 127 deletions
|
@ -38,9 +38,11 @@ class APlayerPawn;
|
|||
struct line_t;
|
||||
struct sector_t;
|
||||
struct msecnode_t;
|
||||
struct portnode_t;
|
||||
struct secplane_t;
|
||||
struct FCheckPosition;
|
||||
struct FTranslatedLineTarget;
|
||||
struct FLinePortal;
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -389,8 +391,14 @@ int P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance,
|
|||
FName damageType, int flags, int fulldamagedistance=0);
|
||||
|
||||
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_DelSeclist(portnode_t *, portnode_t *FLinePortal::*seclisthead);
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist);
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
nodetype* P_DelSecnode(nodetype *, nodetype *linktype::*head);
|
||||
|
||||
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);
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
// Maintain a freelist of msecnode_t's to reduce memory allocs and frees.
|
||||
//=============================================================================
|
||||
|
||||
msecnode_t *headsecnode = NULL;
|
||||
msecnode_t *headsecnode = nullptr;
|
||||
FMemArena secnodearena;
|
||||
|
||||
//=============================================================================
|
||||
|
@ -55,7 +55,6 @@ msecnode_t *P_GetSecnode()
|
|||
}
|
||||
else
|
||||
{
|
||||
node =
|
||||
node = (msecnode_t *)secnodearena.Alloc(sizeof(*node));
|
||||
}
|
||||
return node;
|
||||
|
@ -87,9 +86,10 @@ void P_PutSecnode(msecnode_t *node)
|
|||
//
|
||||
//=============================================================================
|
||||
|
||||
msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist)
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *P_AddSecnode(linktype *s, AActor *thing, nodetype *nextnode, nodetype *&sec_thinglist)
|
||||
{
|
||||
msecnode_t *node;
|
||||
nodetype *node;
|
||||
|
||||
if (s == 0)
|
||||
{
|
||||
|
@ -110,21 +110,21 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecn
|
|||
// Couldn't find an existing node for this sector. Add one at the head
|
||||
// of the list.
|
||||
|
||||
node = P_GetSecnode();
|
||||
node = (nodetype*)P_GetSecnode();
|
||||
|
||||
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
||||
node->visited = 0;
|
||||
|
||||
node->m_sector = s; // sector
|
||||
node->m_thing = thing; // mobj
|
||||
node->m_tprev = NULL; // prev node on Thing thread
|
||||
node->m_tprev = nullptr; // prev node on Thing thread
|
||||
node->m_tnext = nextnode; // next node on Thing thread
|
||||
if (nextnode)
|
||||
nextnode->m_tprev = node; // set back link on Thing
|
||||
|
||||
// Add new node at head of sector thread starting at s->touching_thinglist
|
||||
|
||||
node->m_sprev = NULL; // prev node on sector thread
|
||||
node->m_sprev = nullptr; // prev node on sector thread
|
||||
node->m_snext = sec_thinglist; // next node on sector thread
|
||||
if (sec_thinglist)
|
||||
node->m_snext->m_sprev = node;
|
||||
|
@ -132,22 +132,26 @@ msecnode_t *P_AddSecnode(sector_t *s, AActor *thing, msecnode_t *nextnode, msecn
|
|||
return node;
|
||||
}
|
||||
|
||||
template msecnode_t *P_AddSecnode<msecnode_t, sector_t>(sector_t *s, AActor *thing, msecnode_t *nextnode, msecnode_t *&sec_thinglist);
|
||||
template portnode_t *P_AddSecnode<portnode_t, FLinePortal>(FLinePortal *s, AActor *thing, portnode_t *nextnode, portnode_t *&sec_thinglist);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// P_DelSecnode
|
||||
//
|
||||
// Deletes a sector node from the list of
|
||||
// sectors this object appears in. Returns a pointer to the next node
|
||||
// on the linked list, or NULL.
|
||||
// on the linked list, or nullptr.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead)
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *P_DelSecnode(nodetype *node, nodetype *linktype::*listhead)
|
||||
{
|
||||
msecnode_t* tp; // prev node on thing thread
|
||||
msecnode_t* tn; // next node on thing thread
|
||||
msecnode_t* sp; // prev node on sector thread
|
||||
msecnode_t* sn; // next node on sector thread
|
||||
nodetype* tp; // prev node on thing thread
|
||||
nodetype* tn; // next node on thing thread
|
||||
nodetype* sp; // prev node on sector thread
|
||||
nodetype* sn; // next node on sector thread
|
||||
|
||||
if (node)
|
||||
{
|
||||
|
@ -175,12 +179,15 @@ msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead)
|
|||
|
||||
// Return this node to the freelist
|
||||
|
||||
P_PutSecnode(node);
|
||||
P_PutSecnode((msecnode_t*)node);
|
||||
return tn;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
} // phares 3/13/98
|
||||
|
||||
template msecnode_t *P_DelSecnode(msecnode_t *node, msecnode_t *sector_t::*listhead);
|
||||
template portnode_t *P_DelSecnode(portnode_t *node, portnode_t *FLinePortal::*listhead);
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// P_DelSeclist
|
||||
|
@ -195,6 +202,13 @@ void P_DelSeclist(msecnode_t *node, msecnode_t *sector_t::*sechead)
|
|||
node = P_DelSecnode(node, sechead);
|
||||
}
|
||||
|
||||
void P_DelSeclist(portnode_t *node, portnode_t *FLinePortal::*sechead)
|
||||
{
|
||||
while (node)
|
||||
node = P_DelSecnode(node, sechead);
|
||||
}
|
||||
|
||||
|
||||
//=============================================================================
|
||||
// phares 3/14/98
|
||||
//
|
||||
|
@ -210,13 +224,13 @@ msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector
|
|||
|
||||
// First, clear out the existing m_thing fields. As each node is
|
||||
// added or verified as needed, m_thing will be set properly. When
|
||||
// finished, delete all nodes where m_thing is still NULL. These
|
||||
// finished, delete all nodes where m_thing is still nullptr. These
|
||||
// represent the sectors the Thing has vacated.
|
||||
|
||||
node = sector_list;
|
||||
while (node)
|
||||
{
|
||||
node->m_thing = NULL;
|
||||
node->m_thing = nullptr;
|
||||
node = node->m_tnext;
|
||||
}
|
||||
|
||||
|
@ -254,12 +268,12 @@ msecnode_t *P_CreateSecNodeList(AActor *thing, double radius, msecnode_t *sector
|
|||
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.
|
||||
// m_thing is still nullptr.
|
||||
|
||||
node = sector_list;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
if (node->m_thing == nullptr)
|
||||
{
|
||||
if (node == sector_list)
|
||||
sector_list = node->m_tnext;
|
||||
|
@ -308,7 +322,7 @@ portnode_t *P_DelPortalnode(portnode_t *node)
|
|||
if (sp)
|
||||
sp->m_snext = sn;
|
||||
else
|
||||
node->m_portal->lineportal_thinglist = sn;
|
||||
node->m_sector->lineportal_thinglist = sn;
|
||||
if (sn)
|
||||
sn->m_sprev = sp;
|
||||
|
||||
|
@ -316,7 +330,7 @@ portnode_t *P_DelPortalnode(portnode_t *node)
|
|||
P_PutSecnode(reinterpret_cast<msecnode_t *>(node));
|
||||
return tn;
|
||||
}
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -340,16 +354,16 @@ portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode)
|
|||
// killough 4/4/98, 4/7/98: mark new nodes unvisited.
|
||||
node->visited = 0;
|
||||
|
||||
node->m_portal = s; // portal
|
||||
node->m_sector = s; // portal
|
||||
node->m_thing = thing; // mobj
|
||||
node->m_tprev = NULL; // prev node on Thing thread
|
||||
node->m_tprev = nullptr; // prev node on Thing thread
|
||||
node->m_tnext = nextnode; // next node on Thing thread
|
||||
if (nextnode)
|
||||
nextnode->m_tprev = node; // set back link on Thing
|
||||
|
||||
// Add new node at head of portal thread starting at s->touching_thinglist
|
||||
|
||||
node->m_sprev = NULL; // prev node on portal thread
|
||||
node->m_sprev = nullptr; // prev node on portal thread
|
||||
node->m_snext = s->lineportal_thinglist; // next node on portal thread
|
||||
if (s->lineportal_thinglist)
|
||||
node->m_snext->m_sprev = node;
|
||||
|
@ -357,7 +371,6 @@ portnode_t *P_AddPortalnode(FLinePortal *s, AActor *thing, portnode_t *nextnode)
|
|||
return node;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Handle the lists used to render actors from other portal areas
|
||||
|
@ -420,18 +433,12 @@ void AActor::UpdateRenderSectorList()
|
|||
|
||||
void AActor::ClearRenderSectorList()
|
||||
{
|
||||
msecnode_t *node = touching_sectorportallist;
|
||||
while (node)
|
||||
node = P_DelSecnode(node, §or_t::sectorportal_thinglist);
|
||||
touching_sectorportallist = NULL;
|
||||
P_DelSeclist(touching_sectorportallist, §or_t::sectorportal_thinglist);
|
||||
touching_sectorportallist = nullptr;
|
||||
}
|
||||
|
||||
void AActor::ClearRenderLineList()
|
||||
{
|
||||
portnode_t *node = touching_lineportallist;
|
||||
while (node)
|
||||
node = P_DelPortalnode(node);
|
||||
touching_lineportallist = NULL;
|
||||
P_DelSeclist(touching_lineportallist, &FLinePortal::lineportal_thinglist);
|
||||
touching_lineportallist = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
|
209
src/p_user.cpp
209
src/p_user.cpp
|
@ -95,9 +95,19 @@ static int PredictionLerptics;
|
|||
|
||||
static player_t PredictionPlayerBackup;
|
||||
static BYTE PredictionActorBackup[sizeof(APlayerPawn)];
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
static TArray<AActor *> PredictionSectorListBackup;
|
||||
static TArray<msecnode_t *> PredictionSector_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionTouchingSectors_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionRenderSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionRenderSectors_sprev_Backup;
|
||||
|
||||
static TArray<sector_t *> PredictionPortalSectorsBackup;
|
||||
static TArray<msecnode_t *> PredictionPortalSectors_sprev_Backup;
|
||||
|
||||
static TArray<FLinePortal *> PredictionPortalLinesBackup;
|
||||
static TArray<portnode_t *> PredictionPortalLines_sprev_Backup;
|
||||
|
||||
// [GRB] Custom player classes
|
||||
TArray<FPlayerClass> PlayerClasses;
|
||||
|
@ -2775,6 +2785,100 @@ bool P_LerpCalculate(AActor *pmo, PredictPos from, PredictPos to, PredictPos &re
|
|||
return (delta.LengthSquared() > cl_predict_lerpthreshold && scale <= 1.00f);
|
||||
}
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
void BackupNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||
{
|
||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
||||
// Also store a copy of all previous sector_thinglist nodes
|
||||
prevbackup.Clear();
|
||||
otherbackup.Clear();
|
||||
|
||||
for (auto mnode = head; mnode != nullptr; mnode = mnode->m_tnext)
|
||||
{
|
||||
otherbackup.Push(mnode->m_sector);
|
||||
|
||||
for (auto snode = mnode->m_sector->*otherlist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
prevbackup.Push(snode->m_sprev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<class nodetype, class linktype>
|
||||
nodetype *RestoreNodeList(AActor *act, nodetype *head, nodetype *linktype::*otherlist, TArray<nodetype*, nodetype*> &prevbackup, TArray<linktype *, linktype *> &otherbackup)
|
||||
{
|
||||
// Destroy old refrences
|
||||
nodetype *node = head;
|
||||
while (node)
|
||||
{
|
||||
node->m_thing = NULL;
|
||||
node = node->m_tnext;
|
||||
}
|
||||
|
||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||
P_DelSeclist(head, otherlist);
|
||||
head = NULL;
|
||||
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||
{
|
||||
head = P_AddSecnode(otherbackup[i], act, head, otherbackup[i]->*otherlist);
|
||||
}
|
||||
//act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
||||
//ctx.sector_list = NULL; // clear for next time
|
||||
|
||||
// In the old code this block never executed because of the commented-out NULL assignment above. Needs to be checked
|
||||
node = head;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
{
|
||||
if (node == head)
|
||||
head = node->m_tnext;
|
||||
node = P_DelSecnode(node, otherlist);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->m_tnext;
|
||||
}
|
||||
}
|
||||
|
||||
nodetype *snode;
|
||||
|
||||
// Restore sector thinglist order
|
||||
for (auto i = otherbackup.Size(); i-- > 0;)
|
||||
{
|
||||
// If we were already the head node, then nothing needs to change
|
||||
if (prevbackup[i] == NULL)
|
||||
continue;
|
||||
|
||||
for (snode = otherbackup[i]->*otherlist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
if (snode->m_sprev)
|
||||
snode->m_sprev->m_snext = snode->m_snext;
|
||||
else
|
||||
snode->m_sector->*otherlist = snode->m_snext;
|
||||
if (snode->m_snext)
|
||||
snode->m_snext->m_sprev = snode->m_sprev;
|
||||
|
||||
snode->m_sprev = prevbackup[i];
|
||||
|
||||
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
||||
if (snode->m_sprev->m_snext)
|
||||
snode->m_sprev->m_snext->m_sprev = snode;
|
||||
snode->m_snext = snode->m_sprev->m_snext;
|
||||
snode->m_sprev->m_snext = snode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
void P_PredictPlayer (player_t *player)
|
||||
{
|
||||
int maxtic;
|
||||
|
@ -2809,28 +2913,10 @@ void P_PredictPlayer (player_t *player)
|
|||
act->flags2 &= ~MF2_PUSHWALL;
|
||||
player->cheats |= CF_PREDICTING;
|
||||
|
||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
||||
// Also store a copy of all previous sector_thinglist nodes
|
||||
msecnode_t *mnode = act->touching_sectorlist;
|
||||
msecnode_t *snode;
|
||||
PredictionSector_sprev_Backup.Clear();
|
||||
PredictionTouchingSectorsBackup.Clear ();
|
||||
|
||||
while (mnode != NULL)
|
||||
{
|
||||
PredictionTouchingSectorsBackup.Push (mnode->m_sector);
|
||||
|
||||
for (snode = mnode->m_sector->touching_thinglist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
PredictionSector_sprev_Backup.Push(snode->m_sprev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mnode = mnode->m_tnext;
|
||||
}
|
||||
BackupNodeList(act, act->touching_sectorlist, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||
BackupNodeList(act, act->touching_rendersectors, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||
BackupNodeList(act, act->touching_sectorportallist, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||
BackupNodeList(act, act->touching_lineportallist, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||
|
||||
// Keep an ordered list off all actors in the linked sector.
|
||||
PredictionSectorListBackup.Clear();
|
||||
|
@ -2940,6 +3026,12 @@ void P_UnPredictPlayer ()
|
|||
player->camera = savedcamera;
|
||||
|
||||
FLinkContext ctx;
|
||||
// Unlink from all list, includeing those which are not being handled by UnlinkFromWorld.
|
||||
auto sectorportal_list = act->touching_sectorportallist;
|
||||
auto lineportal_list = act->touching_lineportallist;
|
||||
act->touching_sectorportallist = nullptr;
|
||||
act->touching_lineportallist = nullptr;
|
||||
|
||||
act->UnlinkFromWorld(&ctx);
|
||||
memcpy(&act->snext, PredictionActorBackup, sizeof(APlayerPawn) - ((BYTE *)&act->snext - (BYTE *)act));
|
||||
|
||||
|
@ -2968,71 +3060,10 @@ void P_UnPredictPlayer ()
|
|||
*link = me;
|
||||
}
|
||||
|
||||
// Destroy old refrences
|
||||
msecnode_t *node = ctx.sector_list;
|
||||
while (node)
|
||||
{
|
||||
node->m_thing = NULL;
|
||||
node = node->m_tnext;
|
||||
}
|
||||
|
||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||
P_DelSeclist(ctx.sector_list, §or_t::touching_thinglist);
|
||||
ctx.sector_list = NULL;
|
||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||
{
|
||||
ctx.sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, ctx.sector_list, PredictionTouchingSectorsBackup[i]->touching_thinglist);
|
||||
}
|
||||
act->touching_sectorlist = ctx.sector_list; // Attach to thing
|
||||
ctx.sector_list = NULL; // clear for next time
|
||||
|
||||
// Huh???
|
||||
node = ctx.sector_list;
|
||||
while (node)
|
||||
{
|
||||
if (node->m_thing == NULL)
|
||||
{
|
||||
if (node == ctx.sector_list)
|
||||
ctx.sector_list = node->m_tnext;
|
||||
node = P_DelSecnode(node, §or_t::touching_thinglist);
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->m_tnext;
|
||||
}
|
||||
}
|
||||
|
||||
msecnode_t *snode;
|
||||
|
||||
// Restore sector thinglist order
|
||||
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||
{
|
||||
// If we were already the head node, then nothing needs to change
|
||||
if (PredictionSector_sprev_Backup[i] == NULL)
|
||||
continue;
|
||||
|
||||
for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext)
|
||||
{
|
||||
if (snode->m_thing == act)
|
||||
{
|
||||
if (snode->m_sprev)
|
||||
snode->m_sprev->m_snext = snode->m_snext;
|
||||
else
|
||||
snode->m_sector->touching_thinglist = snode->m_snext;
|
||||
if (snode->m_snext)
|
||||
snode->m_snext->m_sprev = snode->m_sprev;
|
||||
|
||||
snode->m_sprev = PredictionSector_sprev_Backup[i];
|
||||
|
||||
// At the moment, we don't exist in the list anymore, but we do know what our previous node is, so we set its current m_snext->m_sprev to us.
|
||||
if (snode->m_sprev->m_snext)
|
||||
snode->m_sprev->m_snext->m_sprev = snode;
|
||||
snode->m_snext = snode->m_sprev->m_snext;
|
||||
snode->m_sprev->m_snext = snode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
act->touching_sectorlist = RestoreNodeList(act, ctx.sector_list, §or_t::touching_thinglist, PredictionTouchingSectors_sprev_Backup, PredictionTouchingSectorsBackup);
|
||||
act->touching_rendersectors = RestoreNodeList(act, ctx.render_list, §or_t::touching_renderthings, PredictionRenderSectors_sprev_Backup, PredictionRenderSectorsBackup);
|
||||
act->touching_sectorportallist = RestoreNodeList(act, sectorportal_list, §or_t::sectorportal_thinglist, PredictionPortalSectors_sprev_Backup, PredictionPortalSectorsBackup);
|
||||
act->touching_lineportallist = RestoreNodeList(act, lineportal_list, &FLinePortal::lineportal_thinglist, PredictionPortalLines_sprev_Backup, PredictionPortalLinesBackup);
|
||||
}
|
||||
|
||||
// Now fix the pointers in the blocknode chain
|
||||
|
|
|
@ -1372,7 +1372,7 @@ struct msecnode_t
|
|||
// use the same memory layout as msecnode_t so both can be used from the same freelist.
|
||||
struct portnode_t
|
||||
{
|
||||
FLinePortal *m_portal; // a portal containing this object
|
||||
FLinePortal *m_sector; // a portal containing this object (no, this isn't a sector, but if we want to use templates it needs the same variable names as msecnode_t.)
|
||||
AActor *m_thing; // this object
|
||||
struct portnode_t *m_tprev; // prev msecnode_t for this thing
|
||||
struct portnode_t *m_tnext; // next msecnode_t for this thing
|
||||
|
|
Loading…
Reference in a new issue