2017-04-17 11:33:19 +00:00
/*
* *
* *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* * Copyright 2017 ZZYZX
* * All rights reserved .
* *
* * Redistribution and use in source and binary forms , with or without
* * modification , are permitted provided that the following conditions
* * are met :
* *
* * 1. Redistributions of source code must retain the above copyright
* * notice , this list of conditions and the following disclaimer .
* * 2. Redistributions in binary form must reproduce the above copyright
* * notice , this list of conditions and the following disclaimer in the
* * documentation and / or other materials provided with the distribution .
* * 3. The name of the author may not be used to endorse or promote products
* * derived from this software without specific prior written permission .
* *
* * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* * IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* * INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* * NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* * DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* * THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* * ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* * THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* *
*/
2017-01-22 00:33:53 +00:00
# include "events.h"
2017-04-12 23:12:04 +00:00
# include "vm.h"
2017-01-22 00:33:53 +00:00
# include "r_utility.h"
2017-01-22 07:36:39 +00:00
# include "g_levellocals.h"
2017-01-22 07:58:48 +00:00
# include "gi.h"
2017-01-30 07:10:33 +00:00
# include "actor.h"
2017-02-06 13:52:20 +00:00
# include "c_dispatch.h"
2017-02-06 14:02:44 +00:00
# include "d_net.h"
2018-08-15 15:46:03 +00:00
# include "info.h"
2017-01-22 00:33:53 +00:00
2017-01-22 06:56:57 +00:00
DStaticEventHandler * E_FirstEventHandler = nullptr ;
2017-02-02 17:57:00 +00:00
DStaticEventHandler * E_LastEventHandler = nullptr ;
2017-01-22 00:33:53 +00:00
2017-01-22 06:56:57 +00:00
bool E_RegisterHandler ( DStaticEventHandler * handler )
2017-01-22 00:33:53 +00:00
{
if ( handler = = nullptr | | handler - > ObjectFlags & OF_EuthanizeMe )
2017-01-22 06:56:57 +00:00
return false ;
if ( E_CheckHandler ( handler ) )
return false ;
2017-02-03 10:28:40 +00:00
handler - > OnRegister ( ) ;
2017-02-02 17:57:00 +00:00
2017-01-22 00:33:53 +00:00
// link into normal list
2017-02-02 17:57:00 +00:00
// update: link at specific position based on order.
DStaticEventHandler * before = nullptr ;
for ( DStaticEventHandler * existinghandler = E_FirstEventHandler ; existinghandler ; existinghandler = existinghandler - > next )
{
2017-02-03 10:28:40 +00:00
if ( existinghandler - > Order > handler - > Order )
2017-02-02 17:57:00 +00:00
{
before = existinghandler ;
break ;
}
}
// 1. MyHandler2->1:
// E_FirstEventHandler = MyHandler2, E_LastEventHandler = MyHandler2
// 2. MyHandler3->2:
// E_FirstEventHandler = MyHandler2, E_LastEventHandler = MyHandler3
2017-02-09 13:35:45 +00:00
// (Yes, all those write barriers here are really needed!)
2017-02-02 17:57:00 +00:00
if ( before ! = nullptr )
{
// if before is not null, link it before the existing handler.
// note that before can be first handler, check for this.
handler - > next = before ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler , before ) ;
2017-02-02 17:57:00 +00:00
handler - > prev = before - > prev ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler , before - > prev ) ;
2017-02-02 17:57:00 +00:00
before - > prev = handler ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( before , handler ) ;
2017-02-02 17:57:00 +00:00
if ( before = = E_FirstEventHandler )
2017-02-09 13:35:45 +00:00
{
2017-02-02 17:57:00 +00:00
E_FirstEventHandler = handler ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler ) ;
}
2017-02-02 17:57:00 +00:00
}
else
{
// so if before is null, it means add last.
// it can also mean that we have no handlers at all yet.
handler - > prev = E_LastEventHandler ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler , E_LastEventHandler ) ;
2017-02-02 17:57:00 +00:00
handler - > next = nullptr ;
2017-02-09 13:35:45 +00:00
if ( E_FirstEventHandler = = nullptr ) E_FirstEventHandler = handler ;
2017-02-02 17:57:00 +00:00
E_LastEventHandler = handler ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler ) ;
2017-02-02 17:57:00 +00:00
if ( handler - > prev ! = nullptr )
2017-02-09 13:35:45 +00:00
{
2017-02-02 17:57:00 +00:00
handler - > prev - > next = handler ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler - > prev , handler ) ;
}
2017-02-02 17:57:00 +00:00
}
2017-01-30 05:50:09 +00:00
if ( handler - > IsStatic ( ) )
{
2017-01-31 04:24:39 +00:00
handler - > ObjectFlags | = OF_Transient ;
2017-01-30 05:50:09 +00:00
}
2017-02-02 17:57:00 +00:00
2017-01-22 06:56:57 +00:00
return true ;
2017-01-22 00:33:53 +00:00
}
2017-01-22 06:56:57 +00:00
bool E_UnregisterHandler ( DStaticEventHandler * handler )
2017-01-22 00:33:53 +00:00
{
if ( handler = = nullptr | | handler - > ObjectFlags & OF_EuthanizeMe )
2017-01-22 06:56:57 +00:00
return false ;
if ( ! E_CheckHandler ( handler ) )
return false ;
2017-02-03 10:28:40 +00:00
handler - > OnUnregister ( ) ;
2017-01-22 00:33:53 +00:00
// link out of normal list
if ( handler - > prev )
2017-02-09 13:35:45 +00:00
{
2017-01-22 00:33:53 +00:00
handler - > prev - > next = handler - > next ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler - > prev , handler - > next ) ;
}
2017-01-22 00:33:53 +00:00
if ( handler - > next )
2017-02-09 13:35:45 +00:00
{
2017-01-22 00:33:53 +00:00
handler - > next - > prev = handler - > prev ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler - > next , handler - > prev ) ;
}
2017-01-22 00:56:15 +00:00
if ( handler = = E_FirstEventHandler )
2017-02-09 13:35:45 +00:00
{
2017-01-22 00:56:15 +00:00
E_FirstEventHandler = handler - > next ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler - > next ) ;
}
2017-02-02 17:57:00 +00:00
if ( handler = = E_LastEventHandler )
2017-02-09 13:35:45 +00:00
{
2017-02-02 17:57:00 +00:00
E_LastEventHandler = handler - > prev ;
2017-02-09 13:35:45 +00:00
GC : : WriteBarrier ( handler - > prev ) ;
}
2017-01-30 05:50:09 +00:00
if ( handler - > IsStatic ( ) )
2017-01-22 06:58:59 +00:00
{
2017-02-09 13:35:45 +00:00
handler - > ObjectFlags & = ~ OF_Transient ;
2017-01-30 05:50:09 +00:00
handler - > Destroy ( ) ;
2017-01-22 06:58:59 +00:00
}
2017-01-22 06:56:57 +00:00
return true ;
}
2017-03-06 09:25:30 +00:00
bool E_SendNetworkEvent ( FString name , int arg1 , int arg2 , int arg3 , bool manual )
2017-03-03 22:57:41 +00:00
{
if ( gamestate ! = GS_LEVEL )
return false ;
Net_WriteByte ( DEM_NETEVENT ) ;
Net_WriteString ( name ) ;
Net_WriteByte ( 3 ) ;
Net_WriteLong ( arg1 ) ;
Net_WriteLong ( arg2 ) ;
Net_WriteLong ( arg3 ) ;
2017-03-06 09:25:30 +00:00
Net_WriteByte ( manual ) ;
2017-03-03 22:57:41 +00:00
return true ;
}
2017-01-22 06:56:57 +00:00
bool E_CheckHandler ( DStaticEventHandler * handler )
{
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
if ( handler = = lhandler ) return true ;
return false ;
2017-01-22 00:33:53 +00:00
}
2017-01-22 07:36:39 +00:00
bool E_IsStaticType ( PClass * type )
{
2018-03-29 13:41:29 +00:00
assert ( type ! = nullptr ) ;
assert ( type - > IsDescendantOf ( RUNTIME_CLASS ( DStaticEventHandler ) ) ) ;
return ! type - > IsDescendantOf ( RUNTIME_CLASS ( DEventHandler ) ) ;
2017-01-22 07:36:39 +00:00
}
2017-01-23 21:05:51 +00:00
void E_SerializeEvents ( FSerializer & arc )
{
// todo : stuff
2017-01-23 22:17:12 +00:00
if ( arc . BeginArray ( " eventhandlers " ) )
{
int numlocalhandlers = 0 ;
TArray < DStaticEventHandler * > handlers ;
if ( arc . isReading ( ) )
{
numlocalhandlers = arc . ArraySize ( ) ;
// delete all current local handlers, if any
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
if ( ! lhandler - > IsStatic ( ) ) lhandler - > Destroy ( ) ;
}
else
{
for ( DStaticEventHandler * lhandler = E_FirstEventHandler ; lhandler ; lhandler = lhandler - > next )
{
if ( lhandler - > IsStatic ( ) ) continue ;
numlocalhandlers + + ;
handlers . Push ( lhandler ) ;
}
}
for ( int i = 0 ; i < numlocalhandlers ; i + + )
{
// serialize the object properly.
if ( arc . isReading ( ) )
{
// get object and put it into the array
DStaticEventHandler * lhandler ;
arc ( nullptr , lhandler ) ;
if ( lhandler ! = nullptr )
handlers . Push ( lhandler ) ;
}
else
{
: : Serialize < DStaticEventHandler > ( arc , nullptr , handlers [ i ] , nullptr ) ;
}
}
if ( arc . isReading ( ) )
{
// add all newly deserialized handlers into the list
for ( int i = 0 ; i < numlocalhandlers ; i + + )
E_RegisterHandler ( handlers [ i ] ) ;
}
arc . EndArray ( ) ;
}
2017-01-23 21:05:51 +00:00
}
2018-03-29 13:41:29 +00:00
static PClass * E_GetHandlerClass ( const FString & typeName )
2017-01-22 07:58:48 +00:00
{
2018-03-29 13:41:29 +00:00
PClass * type = PClass : : FindClass ( typeName ) ;
2017-01-22 07:58:48 +00:00
if ( type = = nullptr )
{
2018-03-29 13:41:29 +00:00
I_Error ( " Fatal: unknown event handler class %s " , typeName . GetChars ( ) ) ;
2017-01-22 07:58:48 +00:00
}
2018-03-29 13:41:29 +00:00
else if ( ! type - > IsDescendantOf ( RUNTIME_CLASS ( DStaticEventHandler ) ) )
2017-01-22 07:58:48 +00:00
{
2018-03-29 13:41:29 +00:00
I_Error ( " Fatal: event handler class %s is not derived from StaticEventHandler " , typeName . GetChars ( ) ) ;
2017-01-22 07:58:48 +00:00
}
2018-03-29 13:41:29 +00:00
return type ;
}
static void E_InitHandler ( PClass * type )
{
2017-01-22 07:58:48 +00:00
// check if type already exists, don't add twice.
bool typeExists = false ;
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
if ( handler - > IsA ( type ) )
{
typeExists = true ;
break ;
}
}
if ( typeExists ) return ;
DStaticEventHandler * handler = ( DStaticEventHandler * ) type - > CreateNew ( ) ;
E_RegisterHandler ( handler ) ;
}
2017-01-22 07:36:39 +00:00
void E_InitStaticHandlers ( bool map )
{
2018-03-29 13:41:29 +00:00
// don't initialize map handlers if restoring from savegame.
2017-01-30 05:50:09 +00:00
if ( savegamerestore )
return ;
2017-01-22 07:36:39 +00:00
2017-02-03 11:01:15 +00:00
// just make sure
E_Shutdown ( map ) ;
2018-03-29 13:41:29 +00:00
// initialize event handlers from gameinfo
for ( const FString & typeName : gameinfo . EventHandlers )
2017-01-22 07:36:39 +00:00
{
2018-03-29 13:41:29 +00:00
PClass * type = E_GetHandlerClass ( typeName ) ;
// don't init the really global stuff here on startup initialization.
// don't init map-local global stuff here on level setup.
if ( map = = E_IsStaticType ( type ) )
continue ;
E_InitHandler ( type ) ;
2017-01-22 07:36:39 +00:00
}
2018-03-29 13:41:29 +00:00
if ( ! map )
return ;
// initialize event handlers from mapinfo
for ( const FString & typeName : level . info - > EventHandlers )
2017-01-22 07:36:39 +00:00
{
2018-03-29 13:41:29 +00:00
PClass * type = E_GetHandlerClass ( typeName ) ;
if ( E_IsStaticType ( type ) )
I_Error ( " Fatal: invalid event handler class %s in MAPINFO! \n Map-specific event handlers cannot be static. \n " , typeName . GetChars ( ) ) ;
E_InitHandler ( type ) ;
2017-01-22 07:36:39 +00:00
}
}
2017-02-03 11:01:15 +00:00
void E_Shutdown ( bool map )
{
// delete handlers.
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
if ( handler - > IsStatic ( ) = = ! map )
handler - > Destroy ( ) ;
}
}
2017-01-23 22:17:12 +00:00
# define DEFINE_EVENT_LOOPER(name) void E_##name() \
{ \
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next ) \
handler - > name ( ) ; \
2017-01-22 00:33:53 +00:00
}
2017-01-30 05:50:09 +00:00
// note for the functions below.
// *Unsafe is executed on EVERY map load/close, including savegame loading, etc.
// There is no point in allowing non-static handlers to receive unsafe event separately, as there is no point in having static handlers receive safe event.
// Because the main point of safe WorldLoaded/Unloading is that it will be preserved in savegames.
void E_WorldLoaded ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-31 04:24:39 +00:00
if ( handler - > IsStatic ( ) ) continue ;
if ( savegamerestore ) continue ; // don't execute WorldLoaded for handlers loaded from the savegame.
2017-01-30 05:50:09 +00:00
handler - > WorldLoaded ( ) ;
}
}
2017-01-30 06:47:15 +00:00
void E_WorldUnloaded ( )
2017-01-30 05:50:09 +00:00
{
2017-02-02 17:57:00 +00:00
for ( DStaticEventHandler * handler = E_LastEventHandler ; handler ; handler = handler - > prev )
2017-01-30 05:50:09 +00:00
{
2017-01-31 04:24:39 +00:00
if ( handler - > IsStatic ( ) ) continue ;
2017-01-30 06:47:15 +00:00
handler - > WorldUnloaded ( ) ;
2017-01-30 05:50:09 +00:00
}
}
void E_WorldLoadedUnsafe ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
{
2017-01-31 04:24:39 +00:00
if ( ! handler - > IsStatic ( ) ) continue ;
2017-01-30 05:50:09 +00:00
handler - > WorldLoaded ( ) ;
}
}
2017-01-30 06:47:15 +00:00
void E_WorldUnloadedUnsafe ( )
2017-01-30 05:50:09 +00:00
{
2017-02-02 17:57:00 +00:00
for ( DStaticEventHandler * handler = E_LastEventHandler ; handler ; handler = handler - > prev )
2017-01-30 05:50:09 +00:00
{
2017-01-31 04:24:39 +00:00
if ( ! handler - > IsStatic ( ) ) continue ;
2017-01-30 06:47:15 +00:00
handler - > WorldUnloaded ( ) ;
2017-01-30 05:50:09 +00:00
}
}
2017-01-30 06:47:15 +00:00
void E_WorldThingSpawned ( AActor * actor )
{
2017-01-30 07:10:33 +00:00
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if ( actor - > ObjectFlags & OF_EuthanizeMe )
return ;
2017-01-30 06:47:15 +00:00
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
handler - > WorldThingSpawned ( actor ) ;
}
2017-01-31 00:07:00 +00:00
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 ) ;
}
2017-01-31 02:11:09 +00:00
void E_WorldThingRevived ( 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 - > WorldThingRevived ( actor ) ;
}
2017-01-31 02:35:44 +00:00
void E_WorldThingDamaged ( AActor * actor , AActor * inflictor , AActor * source , int damage , FName mod , int flags , DAngle angle )
{
// 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 - > WorldThingDamaged ( actor , inflictor , source , damage , mod , flags , angle ) ;
}
2017-01-31 00:07:00 +00:00
void E_WorldThingDestroyed ( AActor * actor )
{
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if ( actor - > ObjectFlags & OF_EuthanizeMe )
return ;
2017-01-31 02:53:18 +00:00
// don't call anything for non-spawned things (i.e. those that were created, but immediately destroyed)
// this is because Destroyed should be reverse of Spawned. we don't want to catch random inventory give failures.
if ( ! ( actor - > ObjectFlags & OF_Spawned ) )
return ;
2017-02-02 17:57:00 +00:00
for ( DStaticEventHandler * handler = E_LastEventHandler ; handler ; handler = handler - > prev )
2017-01-31 00:07:00 +00:00
handler - > WorldThingDestroyed ( actor ) ;
}
2018-04-14 08:33:17 +00:00
void E_WorldLinePreActivated ( line_t * line , AActor * actor , int activationType , bool * shouldactivate )
2018-03-24 14:59:20 +00:00
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2018-04-14 08:33:17 +00:00
handler - > WorldLinePreActivated ( line , actor , activationType , shouldactivate ) ;
2018-03-24 14:59:20 +00:00
}
2018-04-14 08:33:17 +00:00
void E_WorldLineActivated ( line_t * line , AActor * actor , int activationType )
2018-03-17 15:01:47 +00:00
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2018-04-14 08:33:17 +00:00
handler - > WorldLineActivated ( line , actor , activationType ) ;
2018-03-17 15:01:47 +00:00
}
2017-02-02 18:46:10 +00:00
void E_PlayerEntered ( int num , bool fromhub )
2017-02-02 18:26:56 +00:00
{
2017-02-02 18:46:10 +00:00
// this event can happen during savegamerestore. make sure that local handlers don't receive it.
// actually, global handlers don't want it too.
if ( savegamerestore & & ! fromhub )
return ;
2017-02-02 18:26:56 +00:00
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2017-02-02 18:46:10 +00:00
handler - > PlayerEntered ( num , fromhub ) ;
2017-02-02 18:26:56 +00:00
}
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 ) ;
}
2017-03-07 09:43:14 +00:00
bool E_Responder ( const event_t * ev )
2017-02-03 10:28:40 +00:00
{
2017-03-07 09:43:14 +00:00
bool uiProcessorsFound = false ;
2017-02-03 10:28:40 +00:00
if ( ev - > type = = EV_GUI_Event )
{
// iterate handlers back to front by order, and give them this event.
for ( DStaticEventHandler * handler = E_LastEventHandler ; handler ; handler = handler - > prev )
{
2017-03-07 09:43:14 +00:00
if ( handler - > IsUiProcessor )
{
uiProcessorsFound = true ;
if ( handler - > UiProcess ( ev ) )
return true ; // event was processed
}
2017-02-03 10:28:40 +00:00
}
}
else
{
// not sure if we want to handle device changes, but whatevs.
for ( DStaticEventHandler * handler = E_LastEventHandler ; handler ; handler = handler - > prev )
{
2017-03-07 09:43:14 +00:00
if ( handler - > IsUiProcessor )
uiProcessorsFound = true ;
2017-02-03 18:34:34 +00:00
if ( handler - > InputProcess ( ev ) )
2017-02-03 10:28:40 +00:00
return true ; // event was processed
}
}
2017-03-07 09:43:14 +00:00
return ( uiProcessorsFound & & ( ev - > type = = EV_Mouse ) ) ; // mouse events are eaten by the event system if there are any uiprocessors.
2017-02-03 10:28:40 +00:00
}
2017-03-06 09:25:30 +00:00
void E_Console ( int player , FString name , int arg1 , int arg2 , int arg3 , bool manual )
2017-02-06 13:52:20 +00:00
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2017-03-06 09:25:30 +00:00
handler - > ConsoleProcess ( player , name , arg1 , arg2 , arg3 , manual ) ;
2017-02-06 13:52:20 +00:00
}
2017-03-29 21:51:53 +00:00
void E_RenderOverlay ( EHudState state )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
handler - > RenderOverlay ( state ) ;
}
2017-02-03 10:28:40 +00:00
bool E_CheckUiProcessors ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
if ( handler - > IsUiProcessor )
return true ;
2017-02-03 18:34:34 +00:00
return false ;
}
bool E_CheckRequireMouse ( )
{
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
if ( handler - > IsUiProcessor & & handler - > RequireMouse )
return true ;
2017-02-03 10:28:40 +00:00
return false ;
}
2018-08-16 18:46:40 +00:00
bool E_CheckReplacement ( PClassActor * replacee , PClassActor * * replacement )
2018-08-15 15:46:03 +00:00
{
2018-08-16 18:46:40 +00:00
bool final = false ;
2018-08-15 15:46:03 +00:00
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2018-08-16 18:46:40 +00:00
handler - > CheckReplacement ( replacee , replacement , & final ) ;
return final ;
2018-08-15 15:46:03 +00:00
}
2017-01-30 06:47:15 +00:00
// normal event loopers (non-special, argument-less)
2017-01-23 22:17:12 +00:00
DEFINE_EVENT_LOOPER ( RenderFrame )
2017-01-31 00:07:00 +00:00
DEFINE_EVENT_LOOPER ( WorldLightning )
2017-01-31 01:24:38 +00:00
DEFINE_EVENT_LOOPER ( WorldTick )
2017-03-09 12:49:18 +00:00
DEFINE_EVENT_LOOPER ( UiTick )
2018-03-09 01:06:41 +00:00
DEFINE_EVENT_LOOPER ( PostUiTick )
2017-01-22 00:33:53 +00:00
// declarations
2017-02-26 09:58:22 +00:00
IMPLEMENT_CLASS ( DStaticEventHandler , false , true ) ;
IMPLEMENT_POINTERS_START ( DStaticEventHandler )
IMPLEMENT_POINTER ( next )
IMPLEMENT_POINTER ( prev )
IMPLEMENT_POINTERS_END
2017-01-22 00:33:53 +00:00
IMPLEMENT_CLASS ( DEventHandler , false , false ) ;
2017-02-03 10:28:40 +00:00
DEFINE_FIELD_X ( StaticEventHandler , DStaticEventHandler , Order ) ;
DEFINE_FIELD_X ( StaticEventHandler , DStaticEventHandler , IsUiProcessor ) ;
2017-02-03 18:34:34 +00:00
DEFINE_FIELD_X ( StaticEventHandler , DStaticEventHandler , RequireMouse ) ;
2017-01-22 00:33:53 +00:00
2017-03-06 21:27:51 +00:00
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , ViewPos ) ;
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , ViewAngle ) ;
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , ViewPitch ) ;
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , ViewRoll ) ;
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , FracTic ) ;
DEFINE_FIELD_X ( RenderEvent , FRenderEvent , Camera ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , IsSaveGame ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , IsReopen ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , Thing ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , Inflictor ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , Damage ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , DamageSource ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , DamageType ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , DamageFlags ) ;
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , DamageAngle ) ;
2018-03-17 15:01:47 +00:00
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , ActivatedLine ) ;
2018-04-14 08:33:17 +00:00
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , ActivationType ) ;
2018-03-24 14:59:20 +00:00
DEFINE_FIELD_X ( WorldEvent , FWorldEvent , ShouldActivate ) ;
2017-03-06 21:27:51 +00:00
DEFINE_FIELD_X ( PlayerEvent , FPlayerEvent , PlayerNumber ) ;
DEFINE_FIELD_X ( PlayerEvent , FPlayerEvent , IsReturn ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , Type ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , KeyString ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , KeyChar ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , MouseX ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , MouseY ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , IsShift ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , IsAlt ) ;
DEFINE_FIELD_X ( UiEvent , FUiEvent , IsCtrl ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , Type ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , KeyScan ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , KeyString ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , KeyChar ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , MouseX ) ;
DEFINE_FIELD_X ( InputEvent , FInputEvent , MouseY ) ;
DEFINE_FIELD_X ( ConsoleEvent , FConsoleEvent , Player )
DEFINE_FIELD_X ( ConsoleEvent , FConsoleEvent , Name )
DEFINE_FIELD_X ( ConsoleEvent , FConsoleEvent , Args )
DEFINE_FIELD_X ( ConsoleEvent , FConsoleEvent , IsManual )
2017-02-06 13:52:20 +00:00
2018-08-15 15:46:03 +00:00
DEFINE_FIELD_X ( ReplaceEvent , FReplaceEvent , Replacee )
DEFINE_FIELD_X ( ReplaceEvent , FReplaceEvent , Replacement )
2018-08-16 18:46:40 +00:00
DEFINE_FIELD_X ( ReplaceEvent , FReplaceEvent , IsFinal )
2018-08-15 15:46:03 +00:00
2017-02-03 18:44:27 +00:00
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , SetOrder )
{
PARAM_SELF_PROLOGUE ( DStaticEventHandler ) ;
PARAM_INT ( order ) ;
if ( E_CheckHandler ( self ) )
return 0 ;
self - > Order = order ;
return 0 ;
}
2017-03-03 22:57:41 +00:00
DEFINE_ACTION_FUNCTION ( DEventHandler , SendNetworkEvent )
{
PARAM_PROLOGUE ;
PARAM_STRING ( name ) ;
2017-04-22 07:28:53 +00:00
PARAM_INT_DEF ( arg1 ) ;
PARAM_INT_DEF ( arg2 ) ;
PARAM_INT_DEF ( arg3 ) ;
2017-03-03 22:57:41 +00:00
//
2017-03-06 09:25:30 +00:00
ACTION_RETURN_BOOL ( E_SendNetworkEvent ( name , arg1 , arg2 , arg3 , false ) ) ;
2017-03-03 22:57:41 +00:00
}
2017-01-30 07:33:06 +00:00
DEFINE_ACTION_FUNCTION ( DEventHandler , Find )
{
PARAM_PROLOGUE ;
PARAM_CLASS ( t , DStaticEventHandler ) ;
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
if ( handler - > GetClass ( ) = = t ) // check precise class
ACTION_RETURN_OBJECT ( handler ) ;
ACTION_RETURN_OBJECT ( nullptr ) ;
}
// we might later want to change this
DEFINE_ACTION_FUNCTION ( DStaticEventHandler , Find )
2017-01-22 00:56:15 +00:00
{
PARAM_PROLOGUE ;
2017-01-22 06:56:57 +00:00
PARAM_CLASS ( t , DStaticEventHandler ) ;
for ( DStaticEventHandler * handler = E_FirstEventHandler ; handler ; handler = handler - > next )
2017-01-22 00:56:15 +00:00
if ( handler - > GetClass ( ) = = t ) // check precise class
ACTION_RETURN_OBJECT ( handler ) ;
ACTION_RETURN_OBJECT ( nullptr ) ;
}
2017-01-30 23:28:47 +00:00
# define DEFINE_EMPTY_HANDLER(cls, funcname) DEFINE_ACTION_FUNCTION(cls, funcname) \
2017-01-22 04:23:44 +00:00
{ \
2017-01-30 23:28:47 +00:00
PARAM_SELF_PROLOGUE ( cls ) ; \
return 0 ; \
2017-01-22 04:23:44 +00:00
}
2017-02-03 10:28:40 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , OnRegister )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , OnUnregister )
2017-01-30 23:28:47 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldLoaded )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldUnloaded )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldThingSpawned )
2017-01-31 00:07:00 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldThingDied )
2017-01-31 02:11:09 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldThingRevived )
2017-01-31 02:35:44 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldThingDamaged )
2017-01-31 00:07:00 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldThingDestroyed )
2018-03-24 14:59:20 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldLinePreActivated )
2018-03-17 15:01:47 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldLineActivated )
2017-01-31 00:07:00 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldLightning )
2017-01-31 01:24:38 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , WorldTick )
2017-02-02 18:26:56 +00:00
2017-01-30 23:28:47 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , RenderFrame )
2017-02-03 11:29:17 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , RenderOverlay )
2017-01-30 23:28:47 +00:00
2017-02-02 18:26:56 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , PlayerEntered )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , PlayerRespawned )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , PlayerDied )
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , PlayerDisconnected )
2017-02-03 10:28:40 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , UiProcess ) ;
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , InputProcess ) ;
2017-03-09 12:49:18 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , UiTick ) ;
2018-03-09 01:06:41 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , PostUiTick ) ;
2017-02-02 17:57:00 +00:00
2017-02-06 13:52:20 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , ConsoleProcess ) ;
2017-03-03 21:21:12 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , NetworkProcess ) ;
2017-02-06 13:52:20 +00:00
2018-08-15 15:46:03 +00:00
DEFINE_EMPTY_HANDLER ( DStaticEventHandler , CheckReplacement ) ;
2017-01-31 00:07:00 +00:00
// ===========================================
//
// Event handlers
//
// ===========================================
2017-02-03 10:28:40 +00:00
void DStaticEventHandler : : OnRegister ( )
{
IFVIRTUAL ( DStaticEventHandler , OnRegister )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_OnRegister_VMPtr )
return ;
VMValue params [ 1 ] = { ( DStaticEventHandler * ) this } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 1 , nullptr , 0 ) ;
2017-02-03 10:28:40 +00:00
}
}
void DStaticEventHandler : : OnUnregister ( )
{
IFVIRTUAL ( DStaticEventHandler , OnUnregister )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_OnUnregister_VMPtr )
return ;
VMValue params [ 1 ] = { ( DStaticEventHandler * ) this } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 1 , nullptr , 0 ) ;
2017-02-03 10:28:40 +00:00
}
}
2017-03-06 21:27:51 +00:00
static FWorldEvent E_SetupWorldEvent ( )
2017-01-30 23:28:47 +00:00
{
2017-03-06 21:27:51 +00:00
FWorldEvent e ;
e . IsSaveGame = savegamerestore ;
e . IsReopen = level . FromSnapshot & & ! savegamerestore ; // each one by itself isnt helpful, but with hub load we have savegamerestore==0 and level.FromSnapshot==1.
e . DamageAngle = 0.0 ;
2017-01-30 23:28:47 +00:00
return e ;
}
void DStaticEventHandler : : WorldLoaded ( )
{
IFVIRTUAL ( DStaticEventHandler , WorldLoaded )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldLoaded_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-30 23:28:47 +00:00
}
}
void DStaticEventHandler : : WorldUnloaded ( )
{
IFVIRTUAL ( DStaticEventHandler , WorldUnloaded )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldUnloaded_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-30 23:28:47 +00:00
}
}
void DStaticEventHandler : : WorldThingSpawned ( AActor * actor )
{
IFVIRTUAL ( DStaticEventHandler , WorldThingSpawned )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldThingSpawned_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-30 23:28:47 +00:00
}
}
2017-01-31 00:07:00 +00:00
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 ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
e . Inflictor = inflictor ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-31 02:11:09 +00:00
}
}
void DStaticEventHandler : : WorldThingRevived ( AActor * actor )
{
IFVIRTUAL ( DStaticEventHandler , WorldThingRevived )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldThingRevived_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-31 02:35:44 +00:00
}
}
void DStaticEventHandler : : WorldThingDamaged ( AActor * actor , AActor * inflictor , AActor * source , int damage , FName mod , int flags , DAngle angle )
{
IFVIRTUAL ( DStaticEventHandler , WorldThingDamaged )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldThingDamaged_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
2017-08-09 13:16:33 +00:00
e . Inflictor = inflictor ;
2017-03-06 21:27:51 +00:00
e . Damage = damage ;
e . DamageSource = source ;
e . DamageType = mod ;
e . DamageFlags = flags ;
e . DamageAngle = angle ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-31 00:07:00 +00:00
}
}
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 ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-31 00:07:00 +00:00
}
}
2018-04-14 08:33:17 +00:00
void DStaticEventHandler : : WorldLinePreActivated ( line_t * line , AActor * actor , int activationType , bool * shouldactivate )
2018-03-24 14:59:20 +00:00
{
IFVIRTUAL ( DStaticEventHandler , WorldLinePreActivated )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldLinePreActivated_VMPtr )
return ;
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
e . ActivatedLine = line ;
2018-04-14 08:33:17 +00:00
e . ActivationType = activationType ;
2018-03-24 14:59:20 +00:00
e . ShouldActivate = * shouldactivate ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
VMCall ( func , params , 2 , nullptr , 0 ) ;
* shouldactivate = e . ShouldActivate ;
}
}
2018-04-14 08:33:17 +00:00
void DStaticEventHandler : : WorldLineActivated ( line_t * line , AActor * actor , int activationType )
2018-03-17 15:01:47 +00:00
{
IFVIRTUAL ( DStaticEventHandler , WorldLineActivated )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldLineActivated_VMPtr )
return ;
FWorldEvent e = E_SetupWorldEvent ( ) ;
e . Thing = actor ;
e . ActivatedLine = line ;
2018-04-14 08:33:17 +00:00
e . ActivationType = activationType ;
2018-03-17 15:01:47 +00:00
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
VMCall ( func , params , 2 , nullptr , 0 ) ;
}
}
2017-01-31 00:07:00 +00:00
void DStaticEventHandler : : WorldLightning ( )
{
IFVIRTUAL ( DStaticEventHandler , WorldLightning )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldLightning_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FWorldEvent e = E_SetupWorldEvent ( ) ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-31 00:07:00 +00:00
}
}
2017-01-31 01:24:38 +00:00
void DStaticEventHandler : : WorldTick ( )
{
IFVIRTUAL ( DStaticEventHandler , WorldTick )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_WorldTick_VMPtr )
return ;
2017-03-09 13:08:49 +00:00
VMValue params [ 1 ] = { ( DStaticEventHandler * ) this } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 1 , nullptr , 0 ) ;
2017-01-31 01:24:38 +00:00
}
}
2017-03-06 21:27:51 +00:00
static FRenderEvent E_SetupRenderEvent ( )
2017-01-30 23:28:47 +00:00
{
2017-03-06 21:27:51 +00:00
FRenderEvent e ;
2018-06-19 09:20:36 +00:00
auto & vp = r_viewpoint ;
e . ViewPos = vp . Pos ;
e . ViewAngle = vp . Angles . Yaw ;
e . ViewPitch = vp . Angles . Pitch ;
e . ViewRoll = vp . Angles . Roll ;
e . FracTic = vp . TicFrac ;
e . Camera = vp . camera ;
2017-01-30 23:28:47 +00:00
return e ;
}
void DStaticEventHandler : : RenderFrame ( )
{
IFVIRTUAL ( DStaticEventHandler , RenderFrame )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_RenderFrame_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FRenderEvent e = E_SetupRenderEvent ( ) ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-02-03 11:29:17 +00:00
}
}
2017-03-29 21:51:53 +00:00
void DStaticEventHandler : : RenderOverlay ( EHudState state )
2017-02-03 11:29:17 +00:00
{
IFVIRTUAL ( DStaticEventHandler , RenderOverlay )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_RenderOverlay_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FRenderEvent e = E_SetupRenderEvent ( ) ;
2017-03-29 21:51:53 +00:00
e . HudState = int ( state ) ;
2017-03-06 21:27:51 +00:00
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-01-30 23:28:47 +00:00
}
}
2017-01-22 00:33:53 +00:00
2017-02-02 18:46:10 +00:00
void DStaticEventHandler : : PlayerEntered ( int num , bool fromhub )
2017-02-02 18:26:56 +00:00
{
IFVIRTUAL ( DStaticEventHandler , PlayerEntered )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_PlayerEntered_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FPlayerEvent e = { num , fromhub } ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-02-02 18:26:56 +00:00
}
}
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 ;
2017-03-06 21:27:51 +00:00
FPlayerEvent e = { num , false } ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-02-02 18:26:56 +00:00
}
}
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 ;
2017-03-06 21:27:51 +00:00
FPlayerEvent e = { num , false } ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-02-02 18:26:56 +00:00
}
}
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 ;
2017-03-06 21:27:51 +00:00
FPlayerEvent e = { num , false } ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-02-02 18:26:56 +00:00
}
}
2017-03-07 09:43:14 +00:00
FUiEvent : : FUiEvent ( const event_t * ev )
2017-01-22 00:33:53 +00:00
{
2017-03-06 21:27:51 +00:00
Type = ( EGUIEvent ) ev - > subtype ;
KeyChar = 0 ;
IsShift = false ;
IsAlt = false ;
IsCtrl = false ;
MouseX = 0 ;
MouseY = 0 ;
// we don't want the modders to remember what weird fields mean what for what events.
switch ( ev - > subtype )
{
case EV_GUI_None :
break ;
case EV_GUI_KeyDown :
case EV_GUI_KeyRepeat :
case EV_GUI_KeyUp :
KeyChar = ev - > data1 ;
KeyString = FString ( char ( ev - > data1 ) ) ;
IsShift = ! ! ( ev - > data3 & GKM_SHIFT ) ;
IsAlt = ! ! ( ev - > data3 & GKM_ALT ) ;
IsCtrl = ! ! ( ev - > data3 & GKM_CTRL ) ;
break ;
case EV_GUI_Char :
KeyChar = ev - > data1 ;
KeyString = FString ( char ( ev - > data1 ) ) ;
IsAlt = ! ! ev - > data2 ; // only true for Win32, not sure about SDL
break ;
default : // mouse event
// note: SDL input doesn't seem to provide these at all
//Printf("Mouse data: %d, %d, %d, %d\n", ev->x, ev->y, ev->data1, ev->data2);
MouseX = ev - > data1 ;
MouseY = ev - > data2 ;
IsShift = ! ! ( ev - > data3 & GKM_SHIFT ) ;
IsAlt = ! ! ( ev - > data3 & GKM_ALT ) ;
IsCtrl = ! ! ( ev - > data3 & GKM_CTRL ) ;
break ;
}
2017-01-22 00:33:53 +00:00
}
2017-02-02 17:57:00 +00:00
2017-03-07 09:43:14 +00:00
bool DStaticEventHandler : : UiProcess ( const event_t * ev )
2017-02-03 10:28:40 +00:00
{
IFVIRTUAL ( DStaticEventHandler , UiProcess )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_UiProcess_VMPtr )
return false ;
2017-03-06 21:27:51 +00:00
FUiEvent e = ev ;
2017-02-03 10:28:40 +00:00
int processed ;
VMReturn results [ 1 ] = { & processed } ;
2017-03-06 21:27:51 +00:00
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , results , 1 ) ;
2017-02-03 10:28:40 +00:00
return ! ! processed ;
}
return false ;
}
2017-03-07 09:43:14 +00:00
FInputEvent : : FInputEvent ( const event_t * ev )
2017-02-02 17:57:00 +00:00
{
2017-03-06 21:27:51 +00:00
Type = ( EGenericEvent ) ev - > type ;
// we don't want the modders to remember what weird fields mean what for what events.
KeyScan = 0 ;
KeyChar = 0 ;
MouseX = 0 ;
MouseY = 0 ;
switch ( Type )
{
case EV_None :
break ;
case EV_KeyDown :
case EV_KeyUp :
KeyScan = ev - > data1 ;
KeyChar = ev - > data2 ;
KeyString = FString ( char ( ev - > data1 ) ) ;
break ;
case EV_Mouse :
MouseX = ev - > x ;
MouseY = ev - > y ;
break ;
default :
break ; // EV_DeviceChange = wat?
}
2017-02-03 10:28:40 +00:00
}
2017-02-02 17:57:00 +00:00
2017-03-07 09:43:14 +00:00
bool DStaticEventHandler : : InputProcess ( const event_t * ev )
2017-02-03 10:28:40 +00:00
{
IFVIRTUAL ( DStaticEventHandler , InputProcess )
2017-02-02 17:57:00 +00:00
{
2017-02-03 10:28:40 +00:00
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_InputProcess_VMPtr )
return false ;
2017-03-06 21:27:51 +00:00
FInputEvent e = ev ;
2017-02-03 10:28:40 +00:00
//
int processed ;
VMReturn results [ 1 ] = { & processed } ;
2017-03-06 21:27:51 +00:00
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , results , 1 ) ;
2017-02-03 10:28:40 +00:00
return ! ! processed ;
2017-02-02 17:57:00 +00:00
}
2017-02-03 10:28:40 +00:00
return false ;
}
2017-03-09 12:49:18 +00:00
void DStaticEventHandler : : UiTick ( )
{
IFVIRTUAL ( DStaticEventHandler , UiTick )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_UiTick_VMPtr )
return ;
2017-03-09 13:08:49 +00:00
VMValue params [ 1 ] = { ( DStaticEventHandler * ) this } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 1 , nullptr , 0 ) ;
2017-03-09 12:49:18 +00:00
}
}
2018-03-09 01:06:41 +00:00
void DStaticEventHandler : : PostUiTick ( )
{
IFVIRTUAL ( DStaticEventHandler , PostUiTick )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_PostUiTick_VMPtr )
return ;
VMValue params [ 1 ] = { ( DStaticEventHandler * ) this } ;
VMCall ( func , params , 1 , nullptr , 0 ) ;
}
}
2017-03-06 09:25:30 +00:00
void DStaticEventHandler : : ConsoleProcess ( int player , FString name , int arg1 , int arg2 , int arg3 , bool manual )
2017-02-06 13:52:20 +00:00
{
2017-03-03 21:21:12 +00:00
if ( player < 0 )
2017-02-06 13:52:20 +00:00
{
2017-03-03 21:21:12 +00:00
IFVIRTUAL ( DStaticEventHandler , ConsoleProcess )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_ConsoleProcess_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FConsoleEvent e ;
2017-03-03 21:21:12 +00:00
//
2017-03-06 21:27:51 +00:00
e . Player = player ;
e . Name = name ;
e . Args [ 0 ] = arg1 ;
e . Args [ 1 ] = arg2 ;
e . Args [ 2 ] = arg3 ;
e . IsManual = manual ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-03-03 21:21:12 +00:00
}
}
else
{
IFVIRTUAL ( DStaticEventHandler , NetworkProcess )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_NetworkProcess_VMPtr )
return ;
2017-03-06 21:27:51 +00:00
FConsoleEvent e ;
2017-03-03 21:21:12 +00:00
//
2017-03-06 21:27:51 +00:00
e . Player = player ;
e . Name = name ;
e . Args [ 0 ] = arg1 ;
e . Args [ 1 ] = arg2 ;
e . Args [ 2 ] = arg3 ;
e . IsManual = manual ;
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
2017-04-12 23:12:04 +00:00
VMCall ( func , params , 2 , nullptr , 0 ) ;
2017-03-03 21:21:12 +00:00
}
2017-02-06 13:52:20 +00:00
}
}
2018-08-16 18:46:40 +00:00
void DStaticEventHandler : : CheckReplacement ( PClassActor * replacee , PClassActor * * replacement , bool * final )
2018-08-15 15:46:03 +00:00
{
IFVIRTUAL ( DStaticEventHandler , CheckReplacement )
{
// don't create excessive DObjects if not going to be processed anyway
if ( func = = DStaticEventHandler_CheckReplacement_VMPtr )
return ;
2018-08-16 18:46:40 +00:00
FReplaceEvent e = { replacee , * replacement , * final } ;
2018-08-15 15:46:03 +00:00
VMValue params [ 2 ] = { ( DStaticEventHandler * ) this , & e } ;
VMCall ( func , params , 2 , nullptr , 0 ) ;
if ( e . Replacement ! = replacee ) // prevent infinite recursion
* replacement = e . Replacement ;
2018-08-16 18:46:40 +00:00
* final = e . IsFinal ;
2018-08-15 15:46:03 +00:00
}
}
2017-02-03 10:28:40 +00:00
//
void DStaticEventHandler : : OnDestroy ( )
{
E_UnregisterHandler ( this ) ;
Super : : OnDestroy ( ) ;
}
2017-02-06 13:52:20 +00:00
// console stuff
// this is kinda like puke, except it distinguishes between local events and playsim events.
CCMD ( event )
{
int argc = argv . argc ( ) ;
if ( argc < 2 | | argc > 5 )
{
Printf ( " Usage: event <name> [arg1] [arg2] [arg3] \n " ) ;
}
else
{
int arg [ 3 ] = { 0 , 0 , 0 } ;
int argn = MIN < int > ( argc - 2 , countof ( arg ) ) ;
for ( int i = 0 ; i < argn ; i + + )
arg [ i ] = atoi ( argv [ 2 + i ] ) ;
// call locally
2017-03-06 09:25:30 +00:00
E_Console ( - 1 , argv [ 1 ] , arg [ 0 ] , arg [ 1 ] , arg [ 2 ] , true ) ;
2017-02-06 13:52:20 +00:00
}
}
CCMD ( netevent )
{
2017-02-06 14:14:18 +00:00
if ( gamestate ! = GS_LEVEL /* && gamestate != GS_TITLELEVEL*/ ) // not sure if this should work in title level, but probably not, because this is for actual playing
{
Printf ( " netevent cannot be used outside of a map. \n " ) ;
return ;
}
2017-02-06 14:02:44 +00:00
int argc = argv . argc ( ) ;
2017-02-06 13:52:20 +00:00
2017-02-06 14:02:44 +00:00
if ( argc < 2 | | argc > 5 )
{
2017-02-06 14:14:18 +00:00
Printf ( " Usage: netevent <name> [arg1] [arg2] [arg3] \n " ) ;
2017-02-06 14:02:44 +00:00
}
else
{
int arg [ 3 ] = { 0 , 0 , 0 } ;
int argn = MIN < int > ( argc - 2 , countof ( arg ) ) ;
for ( int i = 0 ; i < argn ; i + + )
arg [ i ] = atoi ( argv [ 2 + i ] ) ;
// call networked
2017-03-06 09:25:30 +00:00
E_SendNetworkEvent ( argv [ 1 ] , arg [ 0 ] , arg [ 1 ] , arg [ 2 ] , true ) ;
2017-02-06 14:02:44 +00:00
}
2017-02-14 20:13:31 +00:00
}