Added CheckReplacement to event handlers, a function inspired by its namesake in Unreal's Mutator class.

Performs runtime replacement of actor classes.
Takes priority over the "replaces" keyword in both DECORATE and ZScript.
This commit is contained in:
Mari the Deer 2018-08-15 17:46:03 +02:00 committed by Christoph Oelckers
commit e18b17217f
4 changed files with 51 additions and 1 deletions

View file

@ -38,6 +38,7 @@
#include "actor.h"
#include "c_dispatch.h"
#include "d_net.h"
#include "info.h"
DStaticEventHandler* E_FirstEventHandler = nullptr;
DStaticEventHandler* E_LastEventHandler = nullptr;
@ -506,6 +507,12 @@ bool E_CheckRequireMouse()
return false;
}
void E_CheckReplacement( PClassActor *replacee, PClassActor **replacement )
{
for (DStaticEventHandler *handler = E_FirstEventHandler; handler; handler = handler->next)
handler->CheckReplacement(replacee,replacement);
}
// normal event loopers (non-special, argument-less)
DEFINE_EVENT_LOOPER(RenderFrame)
DEFINE_EVENT_LOOPER(WorldLightning)
@ -571,6 +578,9 @@ DEFINE_FIELD_X(ConsoleEvent, FConsoleEvent, Name)
DEFINE_FIELD_X(ConsoleEvent, FConsoleEvent, Args)
DEFINE_FIELD_X(ConsoleEvent, FConsoleEvent, IsManual)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacee)
DEFINE_FIELD_X(ReplaceEvent, FReplaceEvent, Replacement)
DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder)
{
PARAM_SELF_PROLOGUE(DStaticEventHandler);
@ -653,6 +663,8 @@ DEFINE_EMPTY_HANDLER(DStaticEventHandler, PostUiTick);
DEFINE_EMPTY_HANDLER(DStaticEventHandler, ConsoleProcess);
DEFINE_EMPTY_HANDLER(DStaticEventHandler, NetworkProcess);
DEFINE_EMPTY_HANDLER(DStaticEventHandler, CheckReplacement);
// ===========================================
//
// Event handlers
@ -1123,6 +1135,21 @@ void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int
}
}
void DStaticEventHandler::CheckReplacement( PClassActor *replacee, PClassActor **replacement )
{
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 };
VMValue params[2] = { (DStaticEventHandler*)this, &e };
VMCall(func, params, 2, nullptr, 0);
if ( e.Replacement != replacee ) // prevent infinite recursion
*replacement = e.Replacement;
}
}
//
void DStaticEventHandler::OnDestroy()
{