- fixed some issues with the bodyque and moved this variable into FLevelLocals

* it was never saved in savegames, leaving the state of dead bodies undefined
* it shouldn't be subjected to pointer substitution because all it contains is old dead bodies, not live ones.
This commit is contained in:
Christoph Oelckers 2018-11-19 18:13:23 +01:00
parent 02de10f657
commit ad04001135
12 changed files with 47 additions and 45 deletions

View file

@ -38,7 +38,6 @@
#include "actor.h"
#include "doomstat.h" // Ideally, DObjects can be used independant of Doom.
#include "d_player.h" // See p_user.cpp to find out why this doesn't work.
#include "g_game.h" // Needed for bodyque.
#include "c_dispatch.h"
#include "dsectoreffect.h"
#include "serializer.h"
@ -500,16 +499,6 @@ size_t DObject::StaticPointerSubstitution (AActor *old, AActor *notOld)
last = probe;
}
// Go through the bodyque.
for (i = 0; i < BODYQUESIZE; ++i)
{
if (bodyque[i] == old)
{
bodyque[i] = notOld;
changed++;
}
}
// Go through players.
for (i = 0; i < MAXPLAYERS; i++)
{

View file

@ -325,15 +325,8 @@ static void MarkRoot()
FCanvasTextureInfo::Mark();
Mark(E_FirstEventHandler);
Mark(E_LastEventHandler);
for (auto &s : level.sectorPortals)
{
Mark(s.mSkybox);
}
// Mark dead bodies.
for (i = 0; i < BODYQUESIZE; ++i)
{
Mark(bodyque[i]);
}
level.Mark();
// Mark players.
for (i = 0; i < MAXPLAYERS; i++)
{

View file

@ -224,7 +224,10 @@ template<class T,class U> inline T barrier_cast(TObjPtr<U> &o)
return static_cast<T>(static_cast<U>(o));
}
template<class T> inline void GC::Mark(TObjPtr<T> &obj)
namespace GC
{
template<class T> inline void Mark(TObjPtr<T> &obj)
{
GC::Mark(&obj.o);
}
}

View file

@ -197,8 +197,6 @@ EXTERN_CVAR (Float, mouse_sensitivity)
// debug flag to cancel adaptiveness
extern bool singletics;
extern int bodyqueslot;
// Needed to store the number of the dummy sky flat.

View file

@ -70,6 +70,7 @@
#include "p_spec.h"
#include "serializer.h"
#include "vm.h"
#include "dobjgc.h"
#include "g_hub.h"
#include "g_levellocals.h"
@ -211,9 +212,6 @@ FString savedescription;
// [RH] Name of screenshot file to generate (usually NULL)
FString shotfile;
AActor* bodyque[BODYQUESIZE];
int bodyqueslot;
FString savename;
FString BackupSaveName;
@ -1676,13 +1674,14 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickPlayerStart)
static void G_QueueBody (AActor *body)
{
// flush an old corpse if needed
int modslot = bodyqueslot%BODYQUESIZE;
int modslot = level.bodyqueslot%level.BODYQUESIZE;
level.bodyqueslot = modslot + 1;
if (bodyqueslot >= BODYQUESIZE && bodyque[modslot] != NULL)
if (level.bodyqueslot >= level.BODYQUESIZE && level.bodyque[modslot] != NULL)
{
bodyque[modslot]->Destroy ();
level.bodyque[modslot]->Destroy ();
}
bodyque[modslot] = body;
level.bodyque[modslot] = body;
// Copy the player's translation, so that if they change their color later, only
// their current body will change and not all their old corpses.
@ -1706,7 +1705,6 @@ static void G_QueueBody (AActor *body)
body->Scale.Y *= skin.Scale.Y / defaultActor->Scale.Y;
}
bodyqueslot++;
}
//

View file

@ -30,6 +30,7 @@
struct event_t;
#include "dobjgc.h"
//
// GAME
@ -94,10 +95,6 @@ void G_AddViewPitch (int look, bool mouse = false);
// Adds to consoleplayer's viewangle if allowed
void G_AddViewAngle (int yaw, bool mouse = false);
#define BODYQUESIZE 32
class AActor;
extern AActor *bodyque[BODYQUESIZE];
extern int bodyqueslot;
class AInventory;
extern const AInventory *SendItemUse, *SendItemDrop;
extern int SendItemDropAmount;

View file

@ -1956,6 +1956,24 @@ void FLevelLocals::Tick ()
//
//==========================================================================
void FLevelLocals::Mark()
{
for (auto &s : sectorPortals)
{
GC::Mark(s.mSkybox);
}
// Mark dead bodies.
for (auto &p : bodyque)
{
GC::Mark(p);
}
}
//==========================================================================
//
//
//==========================================================================
void FLevelLocals::AddScroller (int secnum)
{
if (secnum < 0)

View file

@ -47,6 +47,7 @@
struct FLevelLocals
{
void Tick ();
void Mark();
void AddScroller (int secnum);
void SetInterMusic(const char *nextmap);
void SetMusicVolume(float v);
@ -86,6 +87,11 @@ struct FLevelLocals
node_t *headgamenode;
TArray<uint8_t> rejectmatrix;
static const int BODYQUESIZE = 32;
TObjPtr<AActor*> bodyque[BODYQUESIZE];
int bodyqueslot;
TArray<FSectorPortal> sectorPortals;
TArray<FLinePortal> linePortals;

View file

@ -5772,10 +5772,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
}
DObject::StaticPointerSubstitution (oldactor, p->mo);
// PointerSubstitution() will also affect the bodyque, so undo that now.
for (int ii=0; ii < BODYQUESIZE; ++ii)
if (bodyque[ii] == p->mo)
bodyque[ii] = oldactor;
E_PlayerRespawned(int(p - players));
FBehavior::StaticStartTypedScripts (SCRIPT_Respawn, p->mo, true);
}

View file

@ -971,7 +971,9 @@ void G_SerializeLevel(FSerializer &arc, bool hubload)
("level.skytexture2", level.skytexture2)
("level.fogdensity", level.fogdensity)
("level.outsidefogdensity", level.outsidefogdensity)
("level.skyfog", level.skyfog);
("level.skyfog", level.skyfog)
("level.bodyqueslot", level.bodyqueslot)
.Array("level.bodyque", level.bodyque, level.BODYQUESIZE);
// Hub transitions must keep the current total time
if (!hubload)

View file

@ -4048,12 +4048,12 @@ void P_SetupLevel(const char *lumpname, int position, bool newGame)
FixHoles();
}
bodyqueslot = 0;
level.bodyqueslot = 0;
// phares 8/10/98: Clear body queue so the corpses from previous games are
// not assumed to be from this one.
for (i = 0; i < BODYQUESIZE; i++)
bodyque[i] = NULL;
for(auto & p : level.bodyque)
p = nullptr;
CreateSections(level.sections);

View file

@ -49,6 +49,7 @@
#include "vm.h"
#include "v_text.h"
#include "m_crc32.h"
#include "g_levellocals.h"
#include "gi.h"
@ -926,7 +927,7 @@ void R_InitTranslationTables ()
// Each player corpse has its own translation so they won't change
// color if the player who created them changes theirs.
for (i = 0; i < BODYQUESIZE; ++i)
for (i = 0; i < level.BODYQUESIZE; ++i)
{
PushIdentityTable(TRANSLATION_PlayerCorpses);
}