mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-27 06:12:19 +00:00
0422f40d80
It should be said in no uncertain terms that OnRegister operates on an uninitialized level so it should only be used for setting up the registering process of the event handler itself and nothing else - not even the event handler's data!!!
336 lines
10 KiB
C++
Executable file
336 lines
10 KiB
C++
Executable file
#pragma once
|
|
|
|
#include "dobject.h"
|
|
#include "serializer.h"
|
|
#include "d_event.h"
|
|
#include "d_gui.h"
|
|
#include "sbar.h"
|
|
|
|
class DStaticEventHandler;
|
|
struct EventManager;
|
|
|
|
enum class EventHandlerType
|
|
{
|
|
Global,
|
|
PerMap
|
|
};
|
|
|
|
// ==============================================
|
|
//
|
|
// EventHandler - base class
|
|
//
|
|
// ==============================================
|
|
|
|
class DStaticEventHandler : public DObject // make it a part of normal GC process
|
|
{
|
|
DECLARE_CLASS(DStaticEventHandler, DObject);
|
|
HAS_OBJECT_POINTERS
|
|
public:
|
|
DStaticEventHandler()
|
|
{
|
|
prev = 0;
|
|
next = 0;
|
|
Order = 0;
|
|
IsUiProcessor = false;
|
|
}
|
|
|
|
EventManager *owner;
|
|
DStaticEventHandler* prev;
|
|
DStaticEventHandler* next;
|
|
virtual bool IsStatic() { return true; }
|
|
|
|
//
|
|
int Order;
|
|
bool IsUiProcessor;
|
|
bool RequireMouse;
|
|
|
|
// serialization handler. let's keep it here so that I don't get lost in serialized/not serialized fields
|
|
void Serialize(FSerializer& arc) override
|
|
{
|
|
Super::Serialize(arc);
|
|
/*
|
|
if (arc.isReading())
|
|
{
|
|
Printf("DStaticEventHandler::Serialize: reading object %s\n", GetClass()->TypeName.GetChars());
|
|
}
|
|
else
|
|
{
|
|
Printf("DStaticEventHandler::Serialize: store object %s\n", GetClass()->TypeName.GetChars());
|
|
}
|
|
*/
|
|
|
|
arc("next", next);
|
|
arc("prev", prev);
|
|
arc("Order", Order);
|
|
arc("IsUiProcessor", IsUiProcessor);
|
|
arc("RequireMouse", RequireMouse);
|
|
}
|
|
|
|
// destroy handler. this unlinks EventHandler from the list automatically.
|
|
void OnDestroy() override;
|
|
|
|
//
|
|
void OnRegister(); // you can set order and IsUi here.
|
|
void OnUnregister();
|
|
|
|
//
|
|
void WorldLoaded();
|
|
void WorldUnloaded();
|
|
void WorldThingSpawned(AActor* actor);
|
|
void WorldThingDied(AActor* actor, AActor* inflictor);
|
|
void WorldThingRevived(AActor* actor);
|
|
void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle);
|
|
void WorldThingDestroyed(AActor* actor);
|
|
void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
|
void WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
|
int WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius);
|
|
int WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius);
|
|
void WorldLightning();
|
|
void WorldTick();
|
|
|
|
//
|
|
void RenderFrame();
|
|
void RenderOverlay(EHudState state);
|
|
|
|
//
|
|
void PlayerEntered(int num, bool fromhub);
|
|
void PlayerRespawned(int num);
|
|
void PlayerDied(int num);
|
|
void PlayerDisconnected(int num);
|
|
|
|
// return true if handled.
|
|
bool InputProcess(const event_t* ev);
|
|
bool UiProcess(const event_t* ev);
|
|
void UiTick();
|
|
void PostUiTick();
|
|
|
|
//
|
|
void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3, bool manual);
|
|
|
|
//
|
|
void CheckReplacement(PClassActor* replacee, PClassActor** replacement, bool* final);
|
|
void CheckReplacee(PClassActor** replacee, PClassActor* replacement, bool* final);
|
|
|
|
//
|
|
void NewGame();
|
|
};
|
|
class DEventHandler : public DStaticEventHandler
|
|
{
|
|
DECLARE_CLASS(DEventHandler, DStaticEventHandler) // TODO: make sure this does not horribly break anything
|
|
public:
|
|
bool IsStatic() override { return false; }
|
|
};
|
|
|
|
struct FRenderEvent
|
|
{
|
|
// these are for all render events
|
|
DVector3 ViewPos;
|
|
DAngle ViewAngle;
|
|
DAngle ViewPitch;
|
|
DAngle ViewRoll;
|
|
double FracTic = 0; // 0..1 value that describes where we are inside the current gametic, render-wise.
|
|
AActor* Camera = nullptr;
|
|
int HudState;
|
|
};
|
|
|
|
struct FWorldEvent
|
|
{
|
|
// for loaded/unloaded
|
|
bool IsSaveGame = false;
|
|
bool IsReopen = false;
|
|
// for thingspawned, thingdied, thingdestroyed
|
|
AActor* Thing = nullptr; // for thingdied
|
|
AActor* Inflictor = nullptr; // can be null - for damagemobj
|
|
AActor* DamageSource = nullptr; // can be null
|
|
int Damage = 0; // thingdamaged, sector/line damaged
|
|
FName DamageType = NAME_None; // thingdamaged, sector/line damaged
|
|
int DamageFlags = 0; // thingdamaged
|
|
DAngle DamageAngle; // thingdamaged
|
|
// for line(pre)activated
|
|
line_t* ActivatedLine = nullptr;
|
|
int ActivationType = 0;
|
|
bool ShouldActivate = true;
|
|
// for line/sector damaged
|
|
int DamageSectorPart = 0;
|
|
line_t* DamageLine = nullptr;
|
|
sector_t* DamageSector = nullptr;
|
|
int DamageLineSide = -1;
|
|
DVector3 DamagePosition;
|
|
bool DamageIsRadius; // radius damage yes/no
|
|
int NewDamage = 0; // sector/line damaged. allows modifying damage
|
|
};
|
|
|
|
struct FPlayerEvent
|
|
{
|
|
// 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;
|
|
};
|
|
|
|
struct FUiEvent
|
|
{
|
|
// this essentially translates event_t UI events to ZScript.
|
|
EGUIEvent Type;
|
|
// for keys/chars/whatever
|
|
FString KeyString;
|
|
int KeyChar;
|
|
// for mouse
|
|
int MouseX;
|
|
int MouseY;
|
|
// global (?)
|
|
bool IsShift;
|
|
bool IsCtrl;
|
|
bool IsAlt;
|
|
|
|
FUiEvent(const event_t *ev);
|
|
};
|
|
|
|
struct FInputEvent
|
|
{
|
|
// this translates regular event_t events to ZScript (not UI, UI events are sent via DUiEvent and only if requested!)
|
|
EGenericEvent Type = EV_None;
|
|
// for keys
|
|
int KeyScan;
|
|
FString KeyString;
|
|
int KeyChar;
|
|
// for mouse
|
|
int MouseX;
|
|
int MouseY;
|
|
|
|
FInputEvent(const event_t *ev);
|
|
};
|
|
|
|
struct FConsoleEvent
|
|
{
|
|
// player that activated this event. note that it's always -1 for non-playsim events (i.e. these not called with netevent)
|
|
int Player;
|
|
//
|
|
FString Name;
|
|
int Args[3];
|
|
//
|
|
bool IsManual;
|
|
};
|
|
|
|
struct FReplaceEvent
|
|
{
|
|
PClassActor* Replacee;
|
|
PClassActor* Replacement;
|
|
bool IsFinal;
|
|
};
|
|
|
|
struct FReplacedEvent
|
|
{
|
|
PClassActor* Replacee;
|
|
PClassActor* Replacement;
|
|
bool IsFinal;
|
|
};
|
|
|
|
struct EventManager
|
|
{
|
|
FLevelLocals *Level = nullptr;
|
|
DStaticEventHandler* FirstEventHandler = nullptr;
|
|
DStaticEventHandler* LastEventHandler = nullptr;
|
|
|
|
EventManager() = default;
|
|
EventManager(FLevelLocals *l) { Level = l; }
|
|
~EventManager() { Shutdown(); }
|
|
bool ShouldCallStatic(bool forplay);
|
|
|
|
// for use after loading a savegame. The old handler explicitly reinstalled all handlers instead of doing a list deserialization which resulted in OnRegister being called even when a save was loaded.
|
|
void CallOnRegister();
|
|
// register
|
|
bool RegisterHandler(DStaticEventHandler* handler);
|
|
// unregister
|
|
bool UnregisterHandler(DStaticEventHandler* handler);
|
|
// find
|
|
bool CheckHandler(DStaticEventHandler* handler);
|
|
// check type
|
|
bool IsStaticType(PClass* type);
|
|
// init static handlers
|
|
void InitStaticHandlers(FLevelLocals *l, bool map);
|
|
// shutdown handlers
|
|
void Shutdown();
|
|
|
|
// called right after the map has loaded (approximately same time as OPEN ACS scripts)
|
|
void WorldLoaded();
|
|
// called when the map is about to unload (approximately same time as UNLOADING ACS scripts)
|
|
void WorldUnloaded();
|
|
// called around PostBeginPlay of each actor.
|
|
void WorldThingSpawned(AActor* actor);
|
|
// called after AActor::Die of each actor.
|
|
void WorldThingDied(AActor* actor, AActor* inflictor);
|
|
// called after AActor::Revive.
|
|
void WorldThingRevived(AActor* actor);
|
|
// called before P_DamageMobj and before AActor::DamageMobj virtuals.
|
|
void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle);
|
|
// called before AActor::Destroy of each actor.
|
|
void WorldThingDestroyed(AActor* actor);
|
|
// called in P_ActivateLine before executing special, set shouldactivate to false to prevent activation.
|
|
void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
|
|
// called in P_ActivateLine after successful special execution.
|
|
void WorldLineActivated(line_t* line, AActor* actor, int activationType);
|
|
// called in P_DamageSector and P_DamageLinedef before receiving damage to the sector. returns actual damage
|
|
int WorldSectorDamaged(sector_t* sector, AActor* source, int damage, FName damagetype, int part, DVector3 position, bool isradius);
|
|
// called in P_DamageLinedef before receiving damage to the linedef. returns actual damage
|
|
int WorldLineDamaged(line_t* line, AActor* source, int damage, FName damagetype, int side, DVector3 position, bool isradius);
|
|
// same as ACS SCRIPT_Lightning
|
|
void WorldLightning();
|
|
// this executes on every tick, before everything, only when in valid level and not paused
|
|
void WorldTick();
|
|
// this executes on every tick on UI side, always
|
|
void UiTick();
|
|
// this executes on every tick on UI side, always AND immediately after everything else
|
|
void PostUiTick();
|
|
// called on each render frame once.
|
|
void RenderFrame();
|
|
// called after everything's been rendered, but before console/menus
|
|
void RenderOverlay(EHudState state);
|
|
// this executes when a player enters the level (once). PlayerEnter+inhub = RETURN
|
|
void PlayerEntered(int num, bool fromhub);
|
|
// this executes when a player respawns. includes resurrect cheat.
|
|
void PlayerRespawned(int num);
|
|
// this executes when a player dies (partially duplicating worldthingdied, but whatever)
|
|
void PlayerDied(int num);
|
|
// this executes when a player leaves the game
|
|
void PlayerDisconnected(int num);
|
|
// this executes on events.
|
|
bool Responder(const event_t* ev); // splits events into InputProcess and UiProcess
|
|
// this executes on console/net events.
|
|
void Console(int player, FString name, int arg1, int arg2, int arg3, bool manual);
|
|
|
|
// called when looking up the replacement for an actor class
|
|
bool CheckReplacement(PClassActor* replacee, PClassActor** replacement);
|
|
// called when looking up the replaced for an actor class
|
|
bool CheckReplacee(PClassActor** replacee, PClassActor* replacement);
|
|
|
|
// called on new game
|
|
void NewGame();
|
|
|
|
// send networked event. unified function.
|
|
bool SendNetworkEvent(FString name, int arg1, int arg2, int arg3, bool manual);
|
|
|
|
// check if there is anything that should receive GUI events
|
|
bool CheckUiProcessors();
|
|
// check if we need native mouse due to UiProcessors
|
|
bool CheckRequireMouse();
|
|
|
|
void InitHandler(PClass* type);
|
|
FWorldEvent SetupWorldEvent();
|
|
FRenderEvent SetupRenderEvent();
|
|
|
|
void SetOwnerForHandlers()
|
|
{
|
|
for (DStaticEventHandler* existinghandler = FirstEventHandler; existinghandler; existinghandler = existinghandler->next)
|
|
{
|
|
existinghandler->owner = this;
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
extern EventManager eventManager;
|
|
extern EventManager staticEventManager;
|