diff --git a/src/events.cpp b/src/events.cpp index 29647fa6a..97b32df41 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -1,6 +1,8 @@ #include "events.h" #include "virtual.h" #include "r_utility.h" +#include "g_levellocals.h" +#include "v_text.h" DStaticEventHandler* E_FirstEventHandler = nullptr; @@ -16,7 +18,7 @@ bool E_RegisterHandler(DStaticEventHandler* handler) if (handler->next) handler->next->prev = handler; E_FirstEventHandler = handler; - if (handler->IsStatic()) handler->ObjectFlags |= OF_Fixed; + if (handler->IsStatic() && handler->isMapScope) handler->ObjectFlags |= OF_Fixed; return true; } @@ -33,7 +35,7 @@ bool E_UnregisterHandler(DStaticEventHandler* handler) handler->next->prev = handler->prev; if (handler == E_FirstEventHandler) E_FirstEventHandler = handler->next; - if (handler->IsStatic()) + if (handler->IsStatic() && handler->isMapScope) { handler->ObjectFlags |= OF_YesReallyDelete; delete handler; @@ -48,6 +50,64 @@ bool E_CheckHandler(DStaticEventHandler* handler) return false; } +bool E_IsStaticType(PClass* type) +{ + return (!type->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && + !type->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))); +} + +void E_InitStaticHandlers(bool map) +{ + // remove existing + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + { + if (handler->IsStatic() && handler->isMapScope == map) + handler->Destroy(); + } + + // add new + if (map) + { + for (unsigned int i = 0; i < level.info->EventHandlers.Size(); i++) + { + FString typestring = level.info->EventHandlers[i]; + PClass* type = PClass::FindClass(typestring); + + if (type == nullptr) + { + Printf("%cGWarning: unknown event handler class %s in MAPINFO!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + continue; + } + + if (!E_IsStaticType(type)) + { + Printf("%cGWarning: invalid event handler class %s in MAPINFO!\nMAPINFO event handlers should inherit Static* directly!", TEXTCOLOR_ESCAPE, typestring.GetChars()); + continue; + } + + // check if type already exists, don't add twice. + bool typeExists = false; + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + { + if (handler->IsA(type)) + { + typeExists = true; + break; + } + } + + if (typeExists) continue; + DStaticEventHandler* handler = (DStaticEventHandler*)type->CreateNew(); + handler->isMapScope = true; + E_RegisterHandler(handler); + } + } + else + { + + } +} + void E_MapLoaded() { for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) @@ -104,8 +164,7 @@ DEFINE_ACTION_FUNCTION(DEventHandler, Create) PARAM_PROLOGUE; PARAM_CLASS(t, DStaticEventHandler); // check if type inherits dynamic handlers - if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && - !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + if (E_IsStaticType(t)) { // disallow static types creation with Create() ACTION_RETURN_OBJECT(nullptr); @@ -119,8 +178,7 @@ DEFINE_ACTION_FUNCTION(DEventHandler, CreateOnce) PARAM_PROLOGUE; PARAM_CLASS(t, DStaticEventHandler); // check if type inherits dynamic handlers - if (!t->IsDescendantOf(RUNTIME_CLASS(DEventHandler)) && - !t->IsDescendantOf(RUNTIME_CLASS(DRenderEventHandler))) + if (E_IsStaticType(t)) { // disallow static types creation with Create() ACTION_RETURN_OBJECT(nullptr); diff --git a/src/events.h b/src/events.h index b6a858834..8be072735 100755 --- a/src/events.h +++ b/src/events.h @@ -11,6 +11,10 @@ bool E_RegisterHandler(DStaticEventHandler* handler); bool E_UnregisterHandler(DStaticEventHandler* handler); // find bool E_CheckHandler(DStaticEventHandler* handler); +// check type +bool E_IsStaticType(PClass* type); +// init static handlers +void E_InitStaticHandlers(bool map); // called right after the map has loaded (approximately same time as OPEN ACS scripts) void E_MapLoaded(); @@ -33,6 +37,7 @@ public: DStaticEventHandler* next; DStaticEventHandler* unregPrev; DStaticEventHandler* unregNext; + bool isMapScope; // this is only used with IsStatic=true virtual bool IsStatic() { return true; } // destroy handler. this unlinks EventHandler from the list automatically. diff --git a/src/g_level.cpp b/src/g_level.cpp index e92642d00..8ab1f2d48 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1066,6 +1066,8 @@ void G_DoLoadLevel (int position, bool autosave) } } StatusBar->AttachToPlayer (&players[consoleplayer]); + // [ZZ] init per-map static handlers + E_InitStaticHandlers(true); P_DoDeferedScripts (); // [RH] Do script actions that were triggered on another map. if (demoplayback || oldgs == GS_STARTUP || oldgs == GS_TITLELEVEL) diff --git a/src/g_level.h b/src/g_level.h index 1fadcee3a..d59a4fc09 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -338,6 +338,8 @@ struct level_info_t TArray PrecacheSounds; TArray PrecacheTextures; TArray PrecacheClasses; + + TArray EventHandlers; level_info_t() { diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index bb641b23b..a33872ff4 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -52,6 +52,7 @@ #include "version.h" #include "v_text.h" #include "g_levellocals.h" +#include "events.h" TArray wadclusterinfos; TArray wadlevelinfos; @@ -1046,6 +1047,17 @@ DEFINE_MAP_OPTION(PrecacheSounds, true) } while (parse.sc.CheckString(",")); } +DEFINE_MAP_OPTION(EventHandlers, true) +{ + parse.ParseAssign(); + + do + { + parse.sc.MustGetString(); + info->EventHandlers.Push(parse.sc.String); + } while (parse.sc.CheckString(",")); +} + DEFINE_MAP_OPTION(PrecacheTextures, true) { parse.ParseAssign();