mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
Fixed prediction thinglist order restoration
Prediction didn't take sector_thinglist and thinglist order into account. This notably broke the order in which things were damaged.
This commit is contained in:
parent
a9bea7d774
commit
be33d2894a
1 changed files with 107 additions and 8 deletions
115
src/p_user.cpp
115
src/p_user.cpp
|
@ -65,6 +65,8 @@ CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||||
static player_t PredictionPlayerBackup;
|
static player_t PredictionPlayerBackup;
|
||||||
static BYTE PredictionActorBackup[sizeof(AActor)];
|
static BYTE PredictionActorBackup[sizeof(AActor)];
|
||||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||||
|
static TArray<AActor *> PredictionSectorListBackup;
|
||||||
|
static TArray<msecnode_t *> PredictionSector_sprev_Backup;
|
||||||
|
|
||||||
// [GRB] Custom player classes
|
// [GRB] Custom player classes
|
||||||
TArray<FPlayerClass> PlayerClasses;
|
TArray<FPlayerClass> PlayerClasses;
|
||||||
|
@ -2661,15 +2663,41 @@ void P_PredictPlayer (player_t *player)
|
||||||
player->cheats |= CF_PREDICTING;
|
player->cheats |= CF_PREDICTING;
|
||||||
|
|
||||||
// The ordering of the touching_sectorlist needs to remain unchanged
|
// 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 *mnode = act->touching_sectorlist;
|
||||||
|
msecnode_t *snode;
|
||||||
|
PredictionSector_sprev_Backup.Clear();
|
||||||
PredictionTouchingSectorsBackup.Clear ();
|
PredictionTouchingSectorsBackup.Clear ();
|
||||||
|
|
||||||
while (mnode != NULL)
|
while (mnode != NULL)
|
||||||
{
|
{
|
||||||
PredictionTouchingSectorsBackup.Push (mnode->m_sector);
|
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;
|
mnode = mnode->m_tnext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep an ordered list off all actors in the linked sector.
|
||||||
|
PredictionSectorListBackup.Clear();
|
||||||
|
if (!(act->flags & MF_NOSECTOR))
|
||||||
|
{
|
||||||
|
AActor *link = act->Sector->thinglist;
|
||||||
|
|
||||||
|
while (link != NULL)
|
||||||
|
{
|
||||||
|
PredictionSectorListBackup.Push(link);
|
||||||
|
link = link->snext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Blockmap ordering also needs to stay the same, so unlink the block nodes
|
// Blockmap ordering also needs to stay the same, so unlink the block nodes
|
||||||
// without releasing them. (They will be used again in P_UnpredictPlayer).
|
// without releasing them. (They will be used again in P_UnpredictPlayer).
|
||||||
FBlockNode *block = act->BlockNode;
|
FBlockNode *block = act->BlockNode;
|
||||||
|
@ -2701,6 +2729,7 @@ void P_UnPredictPlayer ()
|
||||||
|
|
||||||
if (player->cheats & CF_PREDICTING)
|
if (player->cheats & CF_PREDICTING)
|
||||||
{
|
{
|
||||||
|
unsigned int i;
|
||||||
AActor *act = player->mo;
|
AActor *act = player->mo;
|
||||||
AActor *savedcamera = player->camera;
|
AActor *savedcamera = player->camera;
|
||||||
|
|
||||||
|
@ -2710,23 +2739,93 @@ void P_UnPredictPlayer ()
|
||||||
// could cause it to change during prediction.
|
// could cause it to change during prediction.
|
||||||
player->camera = savedcamera;
|
player->camera = savedcamera;
|
||||||
|
|
||||||
act->UnlinkFromWorld ();
|
act->UnlinkFromWorld();
|
||||||
memcpy (&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act));
|
memcpy(&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x - (BYTE *)act));
|
||||||
|
|
||||||
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
// Make the sector_list match the player's touching_sectorlist before it got predicted.
|
||||||
P_DelSeclist (sector_list);
|
P_DelSeclist(sector_list);
|
||||||
sector_list = NULL;
|
sector_list = NULL;
|
||||||
for (unsigned int i = PredictionTouchingSectorsBackup.Size (); i-- > 0; )
|
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||||
{
|
{
|
||||||
sector_list = P_AddSecnode (PredictionTouchingSectorsBackup[i], act, sector_list);
|
sector_list = P_AddSecnode(PredictionTouchingSectorsBackup[i], act, sector_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The blockmap ordering needs to remain unchanged, too. Right now, act has the right
|
// The blockmap ordering needs to remain unchanged, too. Right now, act has the right
|
||||||
// pointers, so temporarily set its MF_NOBLOCKMAP flag so that LinkToWorld() does not
|
// pointers, so temporarily set its MF_NOBLOCKMAP flag so that LinkToWorld() does not
|
||||||
// mess with them.
|
// mess with them.
|
||||||
act->flags |= MF_NOBLOCKMAP;
|
{
|
||||||
act->LinkToWorld ();
|
DWORD keepflags = act->flags;
|
||||||
act->flags &= ~MF_NOBLOCKMAP;
|
act->flags |= MF_NOBLOCKMAP;
|
||||||
|
act->LinkToWorld();
|
||||||
|
act->flags = keepflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore sector links.
|
||||||
|
if (!(act->flags & MF_NOSECTOR))
|
||||||
|
{
|
||||||
|
sector_t *sec = act->Sector;
|
||||||
|
AActor *me, *next;
|
||||||
|
AActor **link;// , **prev;
|
||||||
|
|
||||||
|
// The thinglist is just a pointer chain. We are restoring the exact same things, so we can NULL the head safely
|
||||||
|
sec->thinglist = NULL;
|
||||||
|
|
||||||
|
// [ED850] It doesn't look like I need this method. I'll keep it just incase something crops up, however.
|
||||||
|
/*for (i = PredictionSectorListBackup.Size(); i-- > 0;)
|
||||||
|
{
|
||||||
|
me = PredictionSectorListBackup[i];
|
||||||
|
prev = me->sprev;
|
||||||
|
next = me->snext;
|
||||||
|
|
||||||
|
if (prev != NULL) // prev will be NULL if this actor gets deleted due to cleaning up from a broken savegame
|
||||||
|
{
|
||||||
|
if ((*prev = next)) // unlink from sector list
|
||||||
|
next->sprev = prev;
|
||||||
|
me->snext = NULL;
|
||||||
|
me->sprev = (AActor **)(size_t)0xBeefCafe; // Woo! Bug-catching value!
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
for (i = PredictionSectorListBackup.Size(); i-- > 0;)
|
||||||
|
{
|
||||||
|
me = PredictionSectorListBackup[i];
|
||||||
|
link = &sec->thinglist;
|
||||||
|
next = *link;
|
||||||
|
if ((me->snext = next))
|
||||||
|
next->sprev = &me->snext;
|
||||||
|
me->sprev = link;
|
||||||
|
*link = me;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore sector thinglist order
|
||||||
|
for (i = PredictionTouchingSectorsBackup.Size(); i-- > 0;)
|
||||||
|
{
|
||||||
|
msecnode_t *snode;
|
||||||
|
|
||||||
|
for (snode = PredictionTouchingSectorsBackup[i]->touching_thinglist; snode; snode = snode->m_snext)
|
||||||
|
{
|
||||||
|
// If we were already the head, none of this is needed
|
||||||
|
if (snode->m_thing == act && PredictionSector_sprev_Backup[i])
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now fix the pointers in the blocknode chain
|
// Now fix the pointers in the blocknode chain
|
||||||
FBlockNode *block = act->BlockNode;
|
FBlockNode *block = act->BlockNode;
|
||||||
|
|
Loading…
Reference in a new issue