diff --git a/src/d_player.h b/src/d_player.h index dc5f6cd540..79a0cb5284 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -235,7 +235,7 @@ enum // The VM cannot deal with this as an invalid pointer because it performs a read barrier on every object pointer read. // This doesn't have to point to a valid weapon, though, because WP_NOCHANGE is never dereferenced, but it must point to a valid object // and the class descriptor just works fine for that. -#define WP_NOCHANGE ((AWeapon*)RUNTIME_CLASS_CASTLESS(AWeapon)) +extern AWeapon *WP_NOCHANGE; #define MAXPLAYERNAME 15 diff --git a/src/dobjtype.cpp b/src/dobjtype.cpp index 0ae2b47716..62a810969a 100644 --- a/src/dobjtype.cpp +++ b/src/dobjtype.cpp @@ -74,6 +74,12 @@ TArray PClass::FunctionPtrList; bool PClass::bShutdown; bool PClass::bVMOperational; +// Originally this was just a bogus pointer, but with the VM performing a read barrier on every object pointer write +// that does not work anymore. WP_NOCHANGE needs to point to a vaild object to work as intended. +// This Object does not need to be garbage collected, though, but it needs to provide the proper structure so that the +// GC can process it. +AWeapon *WP_NOCHANGE; +DEFINE_GLOBAL(WP_NOCHANGE); // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -218,6 +224,10 @@ void PClass::StaticInit () // I'm not sure if this is really necessary to maintain any sort of sync. qsort(&AllClasses[0], AllClasses.Size(), sizeof(AllClasses[0]), cregcmp); + // WP_NOCHANGE must point to a valid object, although it does not need to be a weapon. + // A simple DObject is enough to give the GC the ability to deal with it, if subjected to it. + WP_NOCHANGE = (AWeapon*)new DObject; + WP_NOCHANGE->Release(); } //========================================================================== @@ -230,6 +240,12 @@ void PClass::StaticInit () void PClass::StaticShutdown () { + if (WP_NOCHANGE != nullptr) + { + WP_NOCHANGE->ObjectFlags |= OF_YesReallyDelete; + delete WP_NOCHANGE; + } + // delete all variables containing pointers to script functions. for (auto p : FunctionPtrList) { diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index 3c2b4e3f12..be8726b06c 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -70,14 +70,6 @@ static TArray FieldTable; extern int BackbuttonTime; extern float BackbuttonAlpha; -// Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but is used everywhere as a special flag. -// It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' -// is to create a static variable from it that points to an otherwise unused object and reference that in the script. Yuck!!! -// This must point to a valid DObject derived object so that the garbage collector can deal with it. -// The global VM types are the most convenient options here because they get created before the compiler is started and they -// are not exposed in other ways to scripts - and they do not change unless the engine is shut down. -DEFINE_GLOBAL_NAMED(TypeSInt32, wp_nochange); - //========================================================================== // // List of all flags