diff --git a/src/events.cpp b/src/events.cpp index 11766f6c9..91e66b82b 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -507,10 +507,12 @@ bool E_CheckRequireMouse() return false; } -void E_CheckReplacement( PClassActor *replacee, PClassActor **replacement ) +bool E_CheckReplacement( PClassActor *replacee, PClassActor **replacement ) { + bool final = false; for (DStaticEventHandler *handler = E_FirstEventHandler; handler; handler = handler->next) - handler->CheckReplacement(replacee,replacement); + handler->CheckReplacement(replacee,replacement,&final); + return final; } // normal event loopers (non-special, argument-less) @@ -580,6 +582,7 @@ DEFINE_FIELD_X(ConsoleEvent, FConsoleEvent, IsManual) DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacee) DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacement) +DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, IsFinal) DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder) { @@ -1135,18 +1138,19 @@ void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int } } -void DStaticEventHandler::CheckReplacement( PClassActor *replacee, PClassActor **replacement ) +void DStaticEventHandler::CheckReplacement( PClassActor *replacee, PClassActor **replacement, bool *final ) { IFVIRTUAL(DStaticEventHandler, CheckReplacement) { // don't create excessive DObjects if not going to be processed anyway if (func == DStaticEventHandler_CheckReplacement_VMPtr) return; - FReplaceEvent e = { replacee, *replacement }; + FReplaceEvent e = { replacee, *replacement, *final }; VMValue params[2] = { (DStaticEventHandler*)this, &e }; VMCall(func, params, 2, nullptr, 0); if ( e.Replacement != replacee ) // prevent infinite recursion *replacement = e.Replacement; + *final = e.IsFinal; } } diff --git a/src/events.h b/src/events.h index 4359178ce..1fbf271dc 100755 --- a/src/events.h +++ b/src/events.h @@ -70,7 +70,7 @@ bool E_Responder(const event_t* ev); // splits events into InputProcess and UiPr void E_Console(int player, FString name, int arg1, int arg2, int arg3, bool manual); // called when looking up the replacement for an actor class -void E_CheckReplacement(PClassActor* replacee, PClassActor** replacement); +bool E_CheckReplacement(PClassActor* replacee, PClassActor** replacement); // send networked event. unified function. bool E_SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual); @@ -171,7 +171,7 @@ public: void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual); // - void CheckReplacement(PClassActor* replacee, PClassActor** replacement); + void CheckReplacement(PClassActor* replacee, PClassActor** replacement, bool* final); }; class DEventHandler : public DStaticEventHandler { @@ -272,6 +272,7 @@ struct FReplaceEvent { PClassActor* Replacee; PClassActor* Replacement; + bool IsFinal; }; #endif diff --git a/src/info.cpp b/src/info.cpp index 480c35814..f31abf953 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -427,7 +427,11 @@ PClassActor *PClassActor::GetReplacement(bool lookskill) } // [MK] ZScript replacement through Event Handlers, has priority over others PClassActor *Replacement = ActorInfo()->Replacement; - E_CheckReplacement(this,&Replacement); + if ( E_CheckReplacement(this,&Replacement) ) + { + // [MK] the replacement is final, so don't continue with the chain + return Replacement ? Replacement : this; + } if (Replacement == nullptr && (!lookskill || skillrepname == NAME_None)) { return this; diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt index 038e84515..9a908f060 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -289,6 +289,7 @@ struct ReplaceEvent native version("2.4") { native readonly Class Replacee; native Class Replacement; + native bool IsFinal; } class StaticEventHandler : Object native play version("2.4")