Added player events

This commit is contained in:
ZZYZX 2017-02-02 20:26:56 +02:00
parent bc1194d03b
commit 7fa50c22e5
3 changed files with 157 additions and 0 deletions

View file

@ -337,6 +337,30 @@ void E_WorldThingDestroyed(AActor* actor)
handler->WorldThingDestroyed(actor);
}
void E_PlayerEntered(int num)
{
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
handler->PlayerEntered(num);
}
void E_PlayerRespawned(int num)
{
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
handler->PlayerRespawned(num);
}
void E_PlayerDied(int num)
{
for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next)
handler->PlayerDied(num);
}
void E_PlayerDisconnected(int num)
{
for (DStaticEventHandler* handler = E_LastEventHandler; handler; handler = handler->prev)
handler->PlayerDisconnected(num);
}
// normal event loopers (non-special, argument-less)
DEFINE_EVENT_LOOPER(RenderFrame)
DEFINE_EVENT_LOOPER(WorldLightning)
@ -348,6 +372,7 @@ IMPLEMENT_CLASS(DEventHandler, false, false);
IMPLEMENT_CLASS(DBaseEvent, false, false)
IMPLEMENT_CLASS(DRenderEvent, false, false)
IMPLEMENT_CLASS(DWorldEvent, false, false)
IMPLEMENT_CLASS(DPlayerEvent, false, false)
DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewPos);
DEFINE_FIELD_X(RenderEvent, DRenderEvent, ViewAngle);
@ -357,6 +382,7 @@ DEFINE_FIELD_X(RenderEvent, DRenderEvent, FracTic);
DEFINE_FIELD_X(RenderEvent, DRenderEvent, Camera);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsSaveGame);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, IsReopen);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, Thing);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, Inflictor);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, Damage);
@ -365,6 +391,9 @@ DEFINE_FIELD_X(WorldEvent, DWorldEvent, DamageType);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, DamageFlags);
DEFINE_FIELD_X(WorldEvent, DWorldEvent, DamageAngle);
DEFINE_FIELD_X(PlayerEvent, DPlayerEvent, PlayerNumber);
DEFINE_FIELD_X(PlayerEvent, DPlayerEvent, IsReturn);
DEFINE_ACTION_FUNCTION(DEventHandler, Create)
{
PARAM_PROLOGUE;
@ -486,8 +515,14 @@ DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDamaged)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldThingDestroyed)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldLightning)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, WorldTick)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, RenderFrame)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, PlayerEntered)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, PlayerRespawned)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, PlayerDied)
DEFINE_EMPTY_HANDLER(DStaticEventHandler, PlayerDisconnected)
DEFINE_ACTION_FUNCTION(DStaticEventHandler, GetOrder)
{
PARAM_SELF_PROLOGUE(DStaticEventHandler);
@ -505,6 +540,7 @@ static DWorldEvent* E_SetupWorldEvent()
static DWorldEvent* e = nullptr;
if (!e) e = (DWorldEvent*)RUNTIME_CLASS(DWorldEvent)->CreateNew();
e->IsSaveGame = savegamerestore;
e->IsReopen = level.FromSnapshot;
e->Thing = nullptr;
e->Inflictor = nullptr;
e->Damage = 0;
@ -669,6 +705,71 @@ void DStaticEventHandler::RenderFrame()
}
}
static DPlayerEvent* E_SetupPlayerEvent()
{
static DPlayerEvent* e = nullptr;
if (!e) e = (DPlayerEvent*)RUNTIME_CLASS(DPlayerEvent)->CreateNew();
e->PlayerNumber = -1;
e->IsReturn = level.FromSnapshot;
return e;
}
void DStaticEventHandler::PlayerEntered(int num)
{
IFVIRTUAL(DStaticEventHandler, PlayerEntered)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_PlayerEntered_VMPtr)
return;
DPlayerEvent* e = E_SetupPlayerEvent();
e->PlayerNumber = num;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
void DStaticEventHandler::PlayerRespawned(int num)
{
IFVIRTUAL(DStaticEventHandler, PlayerRespawned)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_PlayerRespawned_VMPtr)
return;
DPlayerEvent* e = E_SetupPlayerEvent();
e->PlayerNumber = num;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
void DStaticEventHandler::PlayerDied(int num)
{
IFVIRTUAL(DStaticEventHandler, PlayerDied)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_PlayerDied_VMPtr)
return;
DPlayerEvent* e = E_SetupPlayerEvent();
e->PlayerNumber = num;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
void DStaticEventHandler::PlayerDisconnected(int num)
{
IFVIRTUAL(DStaticEventHandler, PlayerDisconnected)
{
// don't create excessive DObjects if not going to be processed anyway
if (func == DStaticEventHandler_PlayerDisconnected_VMPtr)
return;
DPlayerEvent* e = E_SetupPlayerEvent();
e->PlayerNumber = num;
VMValue params[2] = { (DStaticEventHandler*)this, e };
GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr);
}
}
//
void DStaticEventHandler::OnDestroy()
{

View file

@ -41,6 +41,14 @@ void E_WorldLightning();
void E_WorldTick();
// called on each render frame once.
void E_RenderFrame();
// this executes when a player enters the level (once). PlayerEnter+inhub = RETURN
void E_PlayerEntered(int num);
// this executes when a player respawns. includes resurrect cheat.
void E_PlayerRespawned(int num);
// this executes when a player dies (partially duplicating worldthingdied, but whatever)
void E_PlayerDied(int num);
// this executes when a player leaves the game
void E_PlayerDisconnected(int num);
// serialization stuff
void E_SerializeEvents(FSerializer& arc);
@ -89,6 +97,7 @@ public:
// destroy handler. this unlinks EventHandler from the list automatically.
void OnDestroy() override;
//
virtual void WorldLoaded();
virtual void WorldUnloaded();
virtual void WorldThingSpawned(AActor*);
@ -98,8 +107,16 @@ public:
virtual void WorldThingDestroyed(AActor*);
virtual void WorldLightning();
virtual void WorldTick();
//
virtual void RenderFrame();
//
virtual void PlayerEntered(int num);
virtual void PlayerRespawned(int num);
virtual void PlayerDied(int num);
virtual void PlayerDisconnected(int num);
// gets the order of this item.
int GetOrder();
};
@ -153,6 +170,7 @@ class DWorldEvent : public DBaseEvent
public:
// for loaded/unloaded
bool IsSaveGame;
bool IsReopen;
// for thingspawned, thingdied, thingdestroyed
AActor* Thing;
// for thingdied
@ -167,6 +185,7 @@ public:
DWorldEvent()
{
IsSaveGame = false;
IsReopen = false;
Thing = nullptr;
Inflictor = nullptr;
Damage = 0;
@ -175,4 +194,23 @@ public:
}
};
class DPlayerEvent : public DBaseEvent
{
DECLARE_CLASS(DPlayerEvent, DBaseEvent)
public:
// we currently have only one member: player index
// in ZScript, we have global players[] array from which we can
// get both the player itself and player's body,
// so no need to pass it here.
int PlayerNumber;
// we set this to true if level was reopened (RETURN scripts)
bool IsReturn;
DPlayerEvent()
{
PlayerNumber = -1;
IsReturn = false;
}
};
#endif

View file

@ -14,6 +14,8 @@ class WorldEvent : BaseEvent native
{
// for loaded/unloaded
native readonly bool IsSaveGame;
// this will be true if we are re-entering the hub level.
native readonly bool IsReopen;
// for thingspawned/thingdied/thingdestroyed
native readonly Actor Thing;
// for thingdied. can be null
@ -26,6 +28,15 @@ class WorldEvent : BaseEvent native
native readonly double DamageAngle;
}
class PlayerEvent : BaseEvent native
{
// this is the player number that caused the event.
// note: you can get player struct from this by using players[e.PlayerNumber]
native readonly int PlayerNumber;
// this will be true if we are re-entering the hub level.
native readonly bool IsReturn;
}
class StaticEventHandler : Object native
{
// static event handlers CAN register other static event handlers.
@ -48,8 +59,15 @@ class StaticEventHandler : Object native
virtual native void WorldLightning(WorldEvent e); // for the sake of completeness.
virtual native void WorldTick(WorldEvent e);
//
virtual native void RenderFrame(RenderEvent e);
//
virtual native void PlayerEntered(PlayerEvent e);
virtual native void PlayerRespawned(PlayerEvent e);
virtual native void PlayerDied(PlayerEvent e);
virtual native void PlayerDisconnected(PlayerEvent e);
// this function should return a value that 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.