This commit is contained in:
Rachael Alexanderson 2018-11-20 19:09:43 -05:00
commit 17eca07a6f
23 changed files with 90 additions and 175 deletions

View file

@ -116,7 +116,7 @@ public:
botinfo_t *botinfo;
int spawn_tries;
int wanted_botnum;
TObjPtr<AActor*> firstthing;
TObjPtr<AInventory*> firstthing;
TObjPtr<AActor*> body1;
TObjPtr<AActor*> body2;

View file

@ -372,7 +372,6 @@ public:
player_t &operator= (const player_t &p);
void Serialize(FSerializer &arc);
size_t FixPointers (const DObject *obj, DObject *replacement);
size_t PropagateMark();
void SetLogNumber (int num);

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"
@ -307,7 +306,6 @@ DObject::~DObject ()
if (!(ObjectFlags & OF_Released))
{
// Find all pointers that reference this object and NULL them.
StaticPointerSubstitution(this, NULL);
Release();
}
}
@ -478,11 +476,15 @@ size_t DObject::PointerSubstitution (DObject *old, DObject *notOld)
//==========================================================================
//
//
// This once was the main method for pointer cleanup, but
// nowadays its only use is swapping out PlayerPawns.
// This requires pointer fixing throughout all objects and a few
// global variables, but it only needs to look at pointers that
// can point to a player.
//
//==========================================================================
size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults)
size_t DObject::StaticPointerSubstitution (AActor *old, AActor *notOld)
{
DObject *probe;
size_t changed = 0;
@ -497,62 +499,29 @@ size_t DObject::StaticPointerSubstitution (DObject *old, DObject *notOld, bool s
last = probe;
}
if (scandefaults)
{
for (auto p : PClassActor::AllActorClasses)
{
auto def = GetDefaultByType(p);
if (def != nullptr)
{
def->DObject::PointerSubstitution(old, notOld);
}
}
}
// Go through the bodyque.
for (i = 0; i < BODYQUESIZE; ++i)
{
if (bodyque[i] == old)
{
bodyque[i] = static_cast<AActor *>(notOld);
changed++;
}
}
// Go through players.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
changed += players[i].FixPointers (old, notOld);
}
for (auto &s : level.sectorPortals)
{
if (s.mSkybox == old)
{
s.mSkybox = static_cast<AActor*>(notOld);
changed++;
APlayerPawn *replacement = static_cast<APlayerPawn *>(notOld);
auto &p = players[i];
if (p.mo == old) p.mo = replacement, changed++;
if (p.poisoner.pp == old) p.poisoner = replacement, changed++;
if (p.attacker.pp == old) p.attacker = replacement, changed++;
if (p.camera.pp == old) p.camera = replacement, changed++;
if (p.ConversationNPC.pp == old) p.ConversationNPC = replacement, changed++;
if (p.ConversationPC == old) p.ConversationPC = replacement, changed++;
}
}
// Go through sectors.
for (auto &sec : level.sectors)
{
#define SECTOR_CHECK(f,t) \
if (sec.f.pp == static_cast<t *>(old)) { sec.f = static_cast<t *>(notOld); changed++; }
SECTOR_CHECK( SoundTarget, AActor );
SECTOR_CHECK( SecActTarget, AActor );
SECTOR_CHECK( floordata, DSectorEffect );
SECTOR_CHECK( ceilingdata, DSectorEffect );
SECTOR_CHECK( lightingdata, DSectorEffect );
#undef SECTOR_CHECK
if (sec.SoundTarget == old) sec.SoundTarget = notOld;
}
// Go through bot stuff.
if (bglobal.firstthing.pp == (AActor *)old) bglobal.firstthing = (AActor *)notOld, ++changed;
if (bglobal.body1.pp == (AActor *)old) bglobal.body1 = (AActor *)notOld, ++changed;
if (bglobal.body2.pp == (AActor *)old) bglobal.body2 = (AActor *)notOld, ++changed;
return changed;
}

View file

@ -185,6 +185,8 @@ protected: \
#include "dobjgc.h"
class AActor;
class DObject
{
public:
@ -249,11 +251,9 @@ public:
inline FString &StringVar(FName field);
template<class T> T*& PointerVar(FName field);
// If you need to replace one object with another and want to
// change any pointers from the old object to the new object,
// use this method.
// This is only needed for swapping out PlayerPawns and absolutely nothing else!
virtual size_t PointerSubstitution (DObject *old, DObject *notOld);
static size_t StaticPointerSubstitution (DObject *old, DObject *notOld, bool scandefaults = false);
static size_t StaticPointerSubstitution (AActor *old, AActor *notOld);
PClass *GetClass() const
{

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
{
GC::Mark(&obj.o);
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

@ -467,17 +467,6 @@ FState *AWeapon::GetReadyState ()
return nullptr;
}
//===========================================================================
//
// AWeapon :: GetStateForButtonName
//
//===========================================================================
FState *AWeapon::GetStateForButtonName (FName button)
{
return FindState(button);
}
/* Weapon slots ***********************************************************/

View file

@ -132,8 +132,6 @@ public:
FState *GetUpState ();
FState *GetDownState ();
FState *GetReadyState ();
FState *GetStateForButtonName (FName button);
enum
{

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);
@ -85,6 +86,11 @@ struct FLevelLocals
TArray<node_t> gamenodes;
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

@ -43,6 +43,7 @@
#include "serializer.h"
#include "doomdata.h"
#include "g_levellocals.h"
#include "vm.h"
static double DecalWidth, DecalLeft, DecalRight;
static double SpreadZ;
@ -753,29 +754,20 @@ DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *
return NULL;
}
class ADecal : public AActor
DEFINE_ACTION_FUNCTION(ADecal, SpawnDecal)
{
DECLARE_CLASS (ADecal, AActor);
public:
void BeginPlay ();
};
PARAM_SELF_PROLOGUE(AActor);
IMPLEMENT_CLASS(ADecal, false, false)
void ADecal::BeginPlay ()
{
const FDecalTemplate *tpl = nullptr;
Super::BeginPlay ();
if (args[0] < 0)
if (self->args[0] < 0)
{
FName name = ENamedName(-args[0]);
FName name = ENamedName(-self->args[0]);
tpl = DecalLibrary.GetDecalByName(name.GetChars());
}
else
{
int decalid = args[0] + (args[1] << 8); // [KS] High byte for decals.
int decalid = self->args[0] + (self->args[1] << 8); // [KS] High byte for decals.
tpl = DecalLibrary.GetDecalByNum(decalid);
}
@ -784,23 +776,22 @@ void ADecal::BeginPlay ()
{
if (!tpl->PicNum.Exists())
{
Printf("Decal actor at (%f,%f) does not have a valid texture\n", X(), Y());
Printf("Decal actor at (%f,%f) does not have a valid texture\n", self->X(), self->Y());
}
else
{
// Look for a wall within 64 units behind the actor. If none can be
// found, then no decal is created, and this actor is destroyed
// without effectively doing anything.
if (NULL == ShootDecal(tpl, this, Sector, X(), Y(), Z(), Angles.Yaw + 180, 64., true))
if (NULL == ShootDecal(tpl, self, self->Sector, self->X(), self->Y(), self->Z(), self->Angles.Yaw + 180, 64., true))
{
DPrintf (DMSG_WARNING, "Could not find a wall to stick decal to at (%f,%f)\n", X(), Y());
DPrintf (DMSG_WARNING, "Could not find a wall to stick decal to at (%f,%f)\n", self->X(), self->Y());
}
}
}
else
{
DPrintf (DMSG_ERROR, "Decal actor at (%f,%f) does not have a good template\n", X(), Y());
DPrintf (DMSG_ERROR, "Decal actor at (%f,%f) does not have a good template\n", self->X(), self->Y());
}
// This actor doesn't need to stick around anymore.
Destroy();
return 0;
}

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

@ -892,7 +892,7 @@ static void P_CheckWeaponButtons (player_t *player)
if ((player->WeaponState & ButtonChecks[i].StateFlag) &&
(player->cmd.ucmd.buttons & ButtonChecks[i].ButtonFlag))
{
FState *state = weapon->GetStateForButtonName(ButtonChecks[i].StateName);
FState *state = weapon->FindState(ButtonChecks[i].StateName);
// [XA] don't change state if still null, so if the modder
// sets WRF_xxx to true but forgets to define the corresponding
// state, the weapon won't disappear. ;)

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

@ -396,38 +396,6 @@ player_t &player_t::operator=(const player_t &p)
return *this;
}
// This function supplements the pointer cleanup in dobject.cpp, because
// player_t is not derived from DObject. (I tried it, and DestroyScan was
// unable to properly determine the player object's type--possibly
// because it gets staticly allocated in an array.)
//
// This function checks all the DObject pointers in a player_t and NULLs any
// that match the pointer passed in. If you add any pointers that point to
// DObject (or a subclass), add them here too.
size_t player_t::FixPointers (const DObject *old, DObject *rep)
{
APlayerPawn *replacement = static_cast<APlayerPawn *>(rep);
size_t changed = 0;
// The construct *& is used in several of these to avoid the read barriers
// that would turn the pointer we want to check to NULL if the old object
// is pending deletion.
if (mo == old) mo = replacement, changed++;
if (*&poisoner == old) poisoner = replacement, changed++;
if (*&attacker == old) attacker = replacement, changed++;
if (*&camera == old) camera = replacement, changed++;
if (*&Bot == old) Bot = static_cast<DBot *>(rep), changed++;
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
if (*&PremorphWeapon == old) PremorphWeapon = static_cast<AWeapon *>(rep), changed++;
if (psprites == old) psprites = static_cast<DPSprite *>(rep), changed++;
if (*&ConversationNPC == old) ConversationNPC = replacement, changed++;
if (*&ConversationPC == old) ConversationPC = replacement, changed++;
if (*&MUSINFOactor == old) MUSINFOactor = replacement, changed++;
return changed;
}
size_t player_t::PropagateMark()
{
GC::Mark(mo);

View file

@ -67,7 +67,6 @@ public:
void Interpolate(double smoothratio);
virtual void Serialize(FSerializer &arc);
size_t PointerSubstitution (DObject *old, DObject *notOld);
size_t PropagateMark();
};
@ -535,25 +534,6 @@ void DSectorPlaneInterpolation::Serialize(FSerializer &arc)
("attached", attached);
}
//==========================================================================
//
//
//
//==========================================================================
size_t DSectorPlaneInterpolation::PointerSubstitution (DObject *old, DObject *notOld)
{
int subst = 0;
for(unsigned i=0; i<attached.Size(); i++)
{
if (attached[i] == old)
{
attached[i] = (DInterpolation*)notOld;
subst++;
}
}
return subst;
}
//==========================================================================
//

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);
}

View file

@ -1048,7 +1048,7 @@ void FunctionCallEmitter::AddParameterStringConst(const FString &konst)
ExpEmit FunctionCallEmitter::EmitCall(VMFunctionBuilder *build, TArray<ExpEmit> *ReturnRegs)
{
int paramcount = 0;
unsigned paramcount = 0;
for (auto &func : emitters)
{
paramcount += func(build);

View file

@ -1,3 +1,11 @@
class Decal : Actor native
class Decal : Actor
{
native void SpawnDecal();
override void BeginPlay()
{
Super.BeginPlay();
SpawnDecal();
Destroy();
}
}