Add "IsFinal" parameter for CheckReplacement.

If set to true it guarantees that the replacement is final and will not go through the rest of the replacement chain.
This commit is contained in:
Marisa Kirisame 2018-08-16 20:46:40 +02:00 committed by Christoph Oelckers
parent 4e690b1f60
commit 02926a5567
4 changed files with 17 additions and 7 deletions

View file

@ -507,10 +507,12 @@ bool E_CheckRequireMouse()
return false; 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) 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) // 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, Replacee)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacement) DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacement)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, IsFinal)
DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder) 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) IFVIRTUAL(DStaticEventHandler, CheckReplacement)
{ {
// don't create excessive DObjects if not going to be processed anyway // don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_CheckReplacement_VMPtr) if (func == DStaticEventHandler_CheckReplacement_VMPtr)
return; return;
FReplaceEvent e = { replacee, *replacement }; FReplaceEvent e = { replacee, *replacement, *final };
VMValue params[2] = { (DStaticEventHandler*)this, &e }; VMValue params[2] = { (DStaticEventHandler*)this, &e };
VMCall(func, params, 2, nullptr, 0); VMCall(func, params, 2, nullptr, 0);
if ( e.Replacement != replacee ) // prevent infinite recursion if ( e.Replacement != replacee ) // prevent infinite recursion
*replacement = e.Replacement; *replacement = e.Replacement;
*final = e.IsFinal;
} }
} }

View file

@ -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); 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 // 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. // send networked event. unified function.
bool E_SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual); 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 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 class DEventHandler : public DStaticEventHandler
{ {
@ -272,6 +272,7 @@ struct FReplaceEvent
{ {
PClassActor* Replacee; PClassActor* Replacee;
PClassActor* Replacement; PClassActor* Replacement;
bool IsFinal;
}; };
#endif #endif

View file

@ -427,7 +427,11 @@ PClassActor *PClassActor::GetReplacement(bool lookskill)
} }
// [MK] ZScript replacement through Event Handlers, has priority over others // [MK] ZScript replacement through Event Handlers, has priority over others
PClassActor *Replacement = ActorInfo()->Replacement; 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)) if (Replacement == nullptr && (!lookskill || skillrepname == NAME_None))
{ {
return this; return this;

View file

@ -289,6 +289,7 @@ struct ReplaceEvent native version("2.4")
{ {
native readonly Class<Actor> Replacee; native readonly Class<Actor> Replacee;
native Class<Actor> Replacement; native Class<Actor> Replacement;
native bool IsFinal;
} }
class StaticEventHandler : Object native play version("2.4") class StaticEventHandler : Object native play version("2.4")