Skip to content

Commit

Permalink
Added CheckReplacement to event handlers, a function inspired by its …
Browse files Browse the repository at this point in the history
…namesake in Unreal's Mutator class.

Performs runtime replacement of actor classes.
Takes priority over the "replaces" keyword in both DECORATE and ZScript.
  • Loading branch information
Marisa Kirisame authored and coelckers committed Aug 15, 2018
1 parent 7d40edd commit e18b172
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 1 deletion.
27 changes: 27 additions & 0 deletions src/events.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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()
{
Expand Down
12 changes: 12 additions & 0 deletions src/events.h
Expand Up @@ -69,6 +69,9 @@ bool E_Responder(const event_t* ev); // splits events into InputProcess and UiPr
// this executes on console/net events.
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);

// send networked event. unified function.
bool E_SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual);

Expand Down Expand Up @@ -166,6 +169,9 @@ class DStaticEventHandler : public DObject // make it a part of normal GC proces

//
void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual);

//
void CheckReplacement(PClassActor* replacee, PClassActor** replacement);
};
class DEventHandler : public DStaticEventHandler
{
Expand Down Expand Up @@ -262,4 +268,10 @@ struct FConsoleEvent
bool IsManual;
};

struct FReplaceEvent
{
PClassActor* Replacee;
PClassActor* Replacement;
};

#endif
4 changes: 3 additions & 1 deletion src/info.cpp
Expand Up @@ -425,7 +425,9 @@ PClassActor *PClassActor::GetReplacement(bool lookskill)
lookskill = false; skillrepname = NAME_None;
}
}
auto Replacement = ActorInfo()->Replacement;
// [MK] ZScript replacement through Event Handlers, has priority over others
PClassActor *Replacement = ActorInfo()->Replacement;
E_CheckReplacement(this,&Replacement);
if (Replacement == nullptr && (!lookskill || skillrepname == NAME_None))
{
return this;
Expand Down
9 changes: 9 additions & 0 deletions wadsrc/static/zscript/events.txt
Expand Up @@ -285,6 +285,12 @@ struct ConsoleEvent native version("2.4")
native readonly bool IsManual;
}

struct ReplaceEvent native version("2.4")

This comment has been minimized.

Copy link
@edward-san

edward-san Aug 15, 2018

Contributor

Is it there a reason to not have the version string "3.6" (post GZDoom 3.5)?

{
native readonly Class<Actor> Replacee;
native Class<Actor> Replacement;
}

class StaticEventHandler : Object native play version("2.4")
{
// static event handlers CAN register other static event handlers.
Expand Down Expand Up @@ -329,6 +335,9 @@ class StaticEventHandler : Object native play version("2.4")
virtual native ui void ConsoleProcess(ConsoleEvent e);
virtual native void NetworkProcess(ConsoleEvent e);

//
virtual native void CheckReplacement(ReplaceEvent e);

// this value will be queried on Register() to decide the relative order of this handler to every other.
// this is most useful in UI systems.
// default is 0.
Expand Down

0 comments on commit e18b172

Please sign in to comment.