diff --git a/src/events.cpp b/src/events.cpp index a4ff68836..f1601911e 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -203,12 +203,12 @@ void E_WorldLoaded() } } -void E_WorldUnloading() +void E_WorldUnloaded() { for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) { if (handler->IsStatic() && !handler->isMapScope) continue; - handler->WorldUnloading(); + handler->WorldUnloaded(); } } @@ -221,22 +221,31 @@ void E_WorldLoadedUnsafe() } } -void E_WorldUnloadingUnsafe() +void E_WorldUnloadedUnsafe() { for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) { if (!handler->IsStatic() || handler->isMapScope) continue; - handler->WorldUnloading(); + handler->WorldUnloaded(); } } +void E_WorldThingSpawned(AActor* actor) +{ + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + handler->WorldThingSpawned(actor); +} + +// normal event loopers (non-special, argument-less) DEFINE_EVENT_LOOPER(RenderFrame) // declarations IMPLEMENT_CLASS(DStaticEventHandler, false, false); IMPLEMENT_CLASS(DStaticRenderEventHandler, false, false); +IMPLEMENT_CLASS(DStaticWorldEventHandler, false, false); IMPLEMENT_CLASS(DEventHandler, false, false); IMPLEMENT_CLASS(DRenderEventHandler, false, false); +IMPLEMENT_CLASS(DWorldEventHandler, false, false); DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewPos); DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewAngle); @@ -245,6 +254,9 @@ DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, ViewRoll); DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, FracTic); DEFINE_FIELD_X(StaticRenderEventHandler, DStaticRenderEventHandler, Camera); +DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, IsSaveGame); +DEFINE_FIELD_X(StaticWorldEventHandler, DStaticWorldEventHandler, Thing); + DEFINE_ACTION_FUNCTION(DEventHandler, Create) { @@ -321,7 +333,8 @@ void cls::funcname(args) \ } DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldLoaded,) -DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldUnloading,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldUnloaded,) +DEFINE_EVENT_HANDLER(DStaticEventHandler, WorldThingSpawned, AActor*) DEFINE_EVENT_HANDLER(DStaticEventHandler, RenderFrame, ) // @@ -346,3 +359,28 @@ void DStaticRenderEventHandler::RenderFrame() Setup(); Super::RenderFrame(); } + +void DStaticWorldEventHandler::Setup() +{ + IsSaveGame = savegamerestore; + Thing = nullptr; +} + +void DStaticWorldEventHandler::WorldLoaded() +{ + Setup(); + Super::WorldLoaded(); +} + +void DStaticWorldEventHandler::WorldUnloaded() +{ + Setup(); + Super::WorldUnloaded(); +} + +void DStaticWorldEventHandler::WorldThingSpawned(AActor* actor) +{ + Setup(); + Thing = actor; + Super::WorldThingSpawned(actor); +} \ No newline at end of file diff --git a/src/events.h b/src/events.h index 172d14485..fa9b16c32 100755 --- a/src/events.h +++ b/src/events.h @@ -20,17 +20,25 @@ void E_InitStaticHandlers(bool map); // called right after the map has loaded (approximately same time as OPEN ACS scripts) void E_WorldLoaded(); // called when the map is about to unload (approximately same time as UNLOADING ACS scripts) -void E_WorldUnloading(); +void E_WorldUnloaded(); // called right after the map has loaded (every time, UNSAFE VERSION) void E_WorldLoadedUnsafe(); // called right before the map is unloaded (every time, UNSAFE VERSION) -void E_WorldUnloadingUnsafe(); +void E_WorldUnloadedUnsafe(); +// called around PostBeginPlay of each actor. +void E_WorldThingSpawned(AActor* actor); // called on each render frame once. void E_RenderFrame(); // serialization stuff void E_SerializeEvents(FSerializer& arc); +// ============================================== +// +// EventHandler - base class +// +// ============================================== + class DStaticEventHandler : public DObject // make it a part of normal GC process { DECLARE_CLASS(DStaticEventHandler, DObject) @@ -67,7 +75,8 @@ public: void OnDestroy() override; virtual void WorldLoaded(); - virtual void WorldUnloading(); + virtual void WorldUnloaded(); + virtual void WorldThingSpawned(AActor*); virtual void RenderFrame(); }; class DEventHandler : public DStaticEventHandler @@ -78,6 +87,13 @@ public: }; extern DStaticEventHandler* E_FirstEventHandler; + +// ============================================== +// +// RenderEventHandler - for renderer events +// +// ============================================== + class DStaticRenderEventHandler : public DStaticEventHandler { DECLARE_CLASS(DStaticRenderEventHandler, DStaticEventHandler) @@ -90,6 +106,12 @@ public: double FracTic; // 0..1 value that describes where we are inside the current gametic, render-wise. AActor* Camera; + DStaticRenderEventHandler() + { + FracTic = 0; + Camera = nullptr; + } + // serialization handler for our local stuff void Serialize(FSerializer& arc) override { @@ -114,4 +136,46 @@ public: bool IsStatic() override { return false; } }; +// ============================================== +// +// WorldEventHandler - for world events +// +// ============================================== +class DStaticWorldEventHandler : public DStaticEventHandler +{ + DECLARE_CLASS(DStaticWorldEventHandler, DStaticEventHandler) +public: + // for WorldLoaded, WorldUnloaded. + bool IsSaveGame; // this will be true if world event was triggered during savegame loading. + // for WorldThingSpawned + AActor* Thing; + + DStaticWorldEventHandler() + { + IsSaveGame = false; + Thing = nullptr; + } + + void Serialize(FSerializer& arc) override + { + Super::Serialize(arc); + arc("IsSaveGame", IsSaveGame); + arc("Thing", Thing); + } + + void WorldLoaded() override; + void WorldUnloaded() override; + void WorldThingSpawned(AActor*) override; + +private: + void Setup(); +}; +// not sure if anyone wants non-static world handler, but here it is, just in case. +class DWorldEventHandler : public DStaticWorldEventHandler +{ + DECLARE_CLASS(DWorldEventHandler, DStaticWorldEventHandler) +public: + bool IsStatic() override { return false; } +}; + #endif \ No newline at end of file diff --git a/src/g_level.cpp b/src/g_level.cpp index 0310b3846..19c397437 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -409,7 +409,7 @@ void G_InitNew (const char *mapname, bool bTitleLevel) // did we have any level before? if (level.info != nullptr) - E_WorldUnloadingUnsafe(); + E_WorldUnloadedUnsafe(); if (!savegamerestore) { @@ -661,9 +661,9 @@ void G_ChangeLevel(const char *levelname, int position, int flags, int nextSkill unloading = true; FBehavior::StaticStartTypedScripts (SCRIPT_Unloading, NULL, false, 0, true); // [ZZ] safe world unload - E_WorldUnloading(); + E_WorldUnloaded(); // [ZZ] unsafe world unload (changemap != map) - E_WorldUnloadingUnsafe(); + E_WorldUnloadedUnsafe(); unloading = false; STAT_ChangeLevel(nextlevel); diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt index c604101ce..e3ee54025 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -1,7 +1,8 @@ class StaticEventHandler : Object native { virtual native void WorldLoaded(); - virtual native void WorldUnloading(); + virtual native void WorldUnloaded(); + virtual native void WorldThingSpawned(); virtual native void RenderFrame(); } @@ -17,6 +18,13 @@ class StaticRenderEventHandler : StaticEventHandler native native readonly Actor Camera; } +class StaticWorldEventHandler : StaticEventHandler native +{ + // for world + native readonly bool IsSaveGame; // this is set to true if static WorldLoaded was triggered during savegame loading. + native readonly Actor Thing; // this is for WorldThingSpawned +} + class EventHandler : StaticEventHandler native { static native StaticEventHandler Create(class type);