Implemented WorldThingDied (calls at the same point as SCRIPT_Kill); Added Inflictor parameter for WorldThingDied.

This commit is contained in:
ZZYZX 2017-01-31 02:07:00 +02:00
parent 27c8140c46
commit 71f62af6db
4 changed files with 94 additions and 0 deletions

View File

@ -239,8 +239,27 @@ void E_WorldThingSpawned(AActor* actor)
handler->WorldThingSpawned(actor); handler->WorldThingSpawned(actor);
} }
void E_WorldThingDied(AActor* actor, AActor* inflictor)
{
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if (actor->ObjectFlags & OF_EuthanizeMe)
return;
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
handler->WorldThingDied(actor, inflictor);
}
void E_WorldThingDestroyed(AActor* actor)
{
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if (actor->ObjectFlags & OF_EuthanizeMe)
return;
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
handler->WorldThingDestroyed(actor);
}
// normal event loopers (non-special, argument-less) // normal event loopers (non-special, argument-less)
DEFINE_EVENT_LOOPER(RenderFrame) DEFINE_EVENT_LOOPER(RenderFrame)
DEFINE_EVENT_LOOPER(WorldLightning)
// declarations // declarations
IMPLEMENT_CLASS(DStaticEventHandler, false, false); IMPLEMENT_CLASS(DStaticEventHandler, false, false);
@ -258,6 +277,7 @@ DEFINE_FIELD_X(RenderEvent, DRenderEvent, Camera);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsSaveGame); DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsSaveGame);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, Thing); DEFINE_FIELD_X(WorldEvent, DWorldEvent, Thing);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, Inflictor);
DEFINE_ACTION_FUNCTION(DEventHandler, Create) DEFINE_ACTION_FUNCTION(DEventHandler, Create)
@ -375,14 +395,24 @@ DEFINE_ACTION_FUNCTION(DStaticEventHandler, Unregister)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLoaded) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLoaded)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldUnloaded) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldUnloaded)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingSpawned) DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingSpawned)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDied)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDestroyed)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLightning)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, RenderFrame) DEFINE_EMPTY_HANDLER(DStaticEventHandler, RenderFrame)
// ===========================================
//
// Event handlers
//
// ===========================================
static DWorldEvent* E_SetupWorldEvent() static DWorldEvent* E_SetupWorldEvent()
{ {
static DWorldEvent* e = nullptr; static DWorldEvent* e = nullptr;
if (!e) e = (DWorldEvent*)RUNTIME_CLASS(DWorldEvent)->CreateNew(); if (!e) e = (DWorldEvent*)RUNTIME_CLASS(DWorldEvent)->CreateNew();
e->IsSaveGame = savegamerestore; e->IsSaveGame = savegamerestore;
e->Thing = nullptr; e->Thing = nullptr;
e->Inflictor = nullptr;
return e; return e;
} }
@ -426,6 +456,48 @@ void DStaticEventHandler::WorldThingSpawned(AActor* actor)
} }
} }
void DStaticEventHandler::WorldThingDied(AActor* actor, AActor* inflictor)
{
IFVIRTUAL(DStaticEventHandler, WorldThingDied)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_WorldThingDied_VMPtr)
return;
DWorldEvent* e = E_SetupWorldEvent();
e->Thing = actor;
e->Inflictor = inflictor;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
void DStaticEventHandler::WorldThingDestroyed(AActor* actor)
{
IFVIRTUAL(DStaticEventHandler, WorldThingDestroyed)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_WorldThingDestroyed_VMPtr)
return;
DWorldEvent* e = E_SetupWorldEvent();
e->Thing = actor;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
void DStaticEventHandler::WorldLightning()
{
IFVIRTUAL(DStaticEventHandler, WorldLightning)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_WorldLightning_VMPtr)
return;
DWorldEvent* e = E_SetupWorldEvent();
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
static DRenderEvent* E_SetupRenderEvent() static DRenderEvent* E_SetupRenderEvent()
{ {
static DRenderEvent* e = nullptr; static DRenderEvent* e = nullptr;

View File

@ -27,6 +27,12 @@ void E_WorldLoadedUnsafe();
void E_WorldUnloadedUnsafe(); void E_WorldUnloadedUnsafe();
// called around PostBeginPlay of each actor. // called around PostBeginPlay of each actor.
void E_WorldThingSpawned(AActor* actor); void E_WorldThingSpawned(AActor* actor);
// called after AActor::Die of each actor.
void E_WorldThingDied(AActor* actor, AActor* inflictor);
// called before AActor::Destroy of each actor.
void E_WorldThingDestroyed(AActor* actor);
// same as ACS SCRIPT_Lightning
void E_WorldLightning();
// called on each render frame once. // called on each render frame once.
void E_RenderFrame(); void E_RenderFrame();
@ -77,6 +83,9 @@ public:
virtual void WorldLoaded(); virtual void WorldLoaded();
virtual void WorldUnloaded(); virtual void WorldUnloaded();
virtual void WorldThingSpawned(AActor*); virtual void WorldThingSpawned(AActor*);
virtual void WorldThingDied(AActor*, AActor*);
virtual void WorldThingDestroyed(AActor*);
virtual void WorldLightning();
virtual void RenderFrame(); virtual void RenderFrame();
}; };
class DEventHandler : public DStaticEventHandler class DEventHandler : public DStaticEventHandler
@ -141,11 +150,14 @@ public:
bool IsSaveGame; bool IsSaveGame;
// for thingspawned, thingdied, thingdestroyed // for thingspawned, thingdied, thingdestroyed
AActor* Thing; AActor* Thing;
// for thingdied
AActor* Inflictor; // can be null
DWorldEvent() DWorldEvent()
{ {
IsSaveGame = false; IsSaveGame = false;
Thing = nullptr; Thing = nullptr;
Inflictor = nullptr;
} }
void Serialize(FSerializer& arc) override void Serialize(FSerializer& arc) override
@ -153,6 +165,7 @@ public:
Super::Serialize(arc); Super::Serialize(arc);
arc("IsSaveGame", IsSaveGame); arc("IsSaveGame", IsSaveGame);
arc("Thing", Thing); arc("Thing", Thing);
arc("Inflictor", Inflictor);
} }
}; };

View File

@ -60,6 +60,7 @@
#include "a_morph.h" #include "a_morph.h"
#include "virtual.h" #include "virtual.h"
#include "g_levellocals.h" #include "g_levellocals.h"
#include "events.h"
static FRandom pr_obituary ("Obituary"); static FRandom pr_obituary ("Obituary");
static FRandom pr_botrespawn ("BotRespawn"); static FRandom pr_botrespawn ("BotRespawn");
@ -384,6 +385,9 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags)
target = source; target = source;
} }
// [ZZ] Fire WorldThingDied script hook.
E_WorldThingDied(this, inflictor);
// [JM] Fire KILL type scripts for actor. Not needed for players, since they have the "DEATH" script type. // [JM] Fire KILL type scripts for actor. Not needed for players, since they have the "DEATH" script type.
if (!player && !(flags7 & MF7_NOKILLSCRIPTS) && ((flags7 & MF7_USEKILLSCRIPTS) || gameinfo.forcekillscripts)) if (!player && !(flags7 & MF7_NOKILLSCRIPTS) && ((flags7 & MF7_USEKILLSCRIPTS) || gameinfo.forcekillscripts))
{ {

View File

@ -16,6 +16,8 @@ class WorldEvent : BaseEvent native
native readonly bool IsSaveGame; native readonly bool IsSaveGame;
// for thingspawned/thingdied/thingdestroyed // for thingspawned/thingdied/thingdestroyed
native readonly Actor Thing; native readonly Actor Thing;
// for thingdied. can be null
native readonly Actor Inflictor;
} }
class StaticEventHandler : Object native class StaticEventHandler : Object native
@ -33,6 +35,9 @@ class StaticEventHandler : Object native
virtual native void WorldLoaded(WorldEvent e); virtual native void WorldLoaded(WorldEvent e);
virtual native void WorldUnloaded(WorldEvent e); virtual native void WorldUnloaded(WorldEvent e);
virtual native void WorldThingSpawned(WorldEvent e); virtual native void WorldThingSpawned(WorldEvent e);
virtual native void WorldThingDied(WorldEvent e);
virtual native void WorldThingDestroyed(WorldEvent e);
virtual native void WorldLightning(WorldEvent e); // for the sake of completeness.
virtual native void RenderFrame(RenderEvent e); virtual native void RenderFrame(RenderEvent e);
} }