# HG changeset patch # User Adam Kaminski # Date 1631400006 14400 # Sat Sep 11 18:40:06 2021 -0400 # Node ID 9c5e95167355a5d3477598e80fd302bd3f6ef93d # Parent deaf05345cb3187676f15cb4ee8b07b8847407df - Added the EVENT script type GAMEEVENT_ACTOR_DAMAGED, which is triggered whenever an actor receives damage. Much like GAMEEVENT_ACTOR_SPAWNED, this event only executes if the actor has the USEDAMAGEEVENTSCRIPT flag or if the GameInfo option "forcedamageeventscripts" is enabled. - Added new actor pointers: AAPTR_DAMAGE_SOURCE, AAPTR_DAMAGE_INFLICTOR, and AAPTR_DAMAGE_TARGET, granting access to the source, inflictor, and target actors that triggered GAMEEVENT_ACTOR_DAMAGED. Note that these actor pointers are only useful in the event script itself. diff -r deaf05345cb3 -r 9c5e95167355 docs/zandronum-history.txt --- a/docs/zandronum-history.txt Sat Sep 11 18:10:29 2021 -0400 +++ b/docs/zandronum-history.txt Sat Sep 11 18:40:06 2021 -0400 @@ -58,7 +58,7 @@ + - Added all of the text colors from "New Text Colors", originally made by FuzzballFox. [Kaminsky] + - Added DMFlags: "sv_shootthroughallies" and "sv_dontpushallies", so a player's attacks can pass through and not push their allies. [Kaminsky] + - Added the EVENT script type: GAMEEVENT_PLAYERCONNECT, indicating when a client or bot joins the server. [Kaminsky] -+ - Added the EVENT script type GAMEEVENT_ACTOR_SPAWNED, which is triggered just before an actor's first tic. Note that for performance reasons, this event only executes if the actor has the USESPAWNEVENTSCRIPT flag or if the GameInfo option "forcespawneventscripts" is enabled. [Kaminsky] ++ - Added the EVENT script type GAMEEVENT_ACTOR_SPAWNED and GAMEVENT_ACTOR_DAMAGED, which are triggered just before an actor's first tic and when an actor takes damage. Note that for performance reasons, these events are disabled by default so modders have to enable them by themselves. [Kaminsky] - - Fixed: Bots tries to jump to reach item when sv_nojump is true. [sleep] - - Fixed: ACS function SetSkyScrollSpeed didn't work online. [Edward-san] - - Fixed: color codes in callvote reasons weren't terminated properly. [Dusk] diff -r deaf05345cb3 -r 9c5e95167355 src/actor.h --- a/src/actor.h Sat Sep 11 18:10:29 2021 -0400 +++ b/src/actor.h Sat Sep 11 18:40:06 2021 -0400 @@ -435,6 +435,10 @@ STFL_USESPAWNEVENTSCRIPT = 0x01000000, STFL_NOSPAWNEVENTSCRIPT = 0x02000000, + // [AK] This actor may (not) trigger the GAMEEVENT_ACTOR_DAMAGED event type. + STFL_USEDAMAGEEVENTSCRIPT = 0x04000000, + STFL_NODAMAGEEVENTSCRIPT = 0x08000000, + // More flags for Skulltag... these having to do with the network. // This object does not have a network ID. diff -r deaf05345cb3 -r 9c5e95167355 src/actorptrselect.cpp --- a/src/actorptrselect.cpp Sat Sep 11 18:10:29 2021 -0400 +++ b/src/actorptrselect.cpp Sat Sep 11 18:40:06 2021 -0400 @@ -2,6 +2,8 @@ #include "actor.h" #include "d_player.h" #include "p_pspr.h" +// [AK] New #includes. +#include "p_acs.h" //========================================================================== // @@ -32,6 +34,12 @@ AActor *COPY_AAPTR(AActor *origin, int selector) { + // [AK] Check if we want to return the source, inflictor, or target actor pointers, which are only + // valid in ACS EVENT scripts in which GAMEEVENT_ACTOR_DAMAGED is the event type. In all other + // cases, a NULL pointer should always be returned. + if ( ACS_IsCalledFromScript( ) && ( selector & AAPTR_DAMAGE_SELECTORS )) + return ACS_GetScriptDamagePointers( selector & AAPTR_DAMAGE_SELECTORS ); + if (origin) { if (origin->player) diff -r deaf05345cb3 -r 9c5e95167355 src/actorptrselect.h --- a/src/actorptrselect.h Sat Sep 11 18:10:29 2021 -0400 +++ b/src/actorptrselect.h Sat Sep 11 18:40:06 2021 -0400 @@ -37,6 +37,15 @@ AAPTR_FRIENDPLAYER = 0x4000, + // [AK] Pointers to an ACS script's source, inflictor, and target actors. These + // are only useful in event scripts triggered by GAMEEVENT_ACTOR_DAMAGED. + AAPTR_DAMAGE_SOURCE = 0x10000000, + AAPTR_DAMAGE_INFLICTOR = 0x40000000, + AAPTR_DAMAGE_TARGET = 0x80000000, + + AAPTR_DAMAGE_SELECTORS = + AAPTR_DAMAGE_SOURCE|AAPTR_DAMAGE_INFLICTOR|AAPTR_DAMAGE_TARGET, + AAPTR_PLAYER_SELECTORS = AAPTR_PLAYER_GETTARGET|AAPTR_PLAYER_GETCONVERSATION, @@ -47,7 +56,6 @@ AAPTR_PLAYER1|AAPTR_PLAYER2|AAPTR_PLAYER3|AAPTR_PLAYER4| AAPTR_PLAYER5|AAPTR_PLAYER6|AAPTR_PLAYER7|AAPTR_PLAYER8| AAPTR_NULL - }; /* diff -r deaf05345cb3 -r 9c5e95167355 src/gamemode.h --- a/src/gamemode.h Sat Sep 11 18:10:29 2021 -0400 +++ b/src/gamemode.h Sat Sep 11 18:40:06 2021 -0400 @@ -115,6 +115,7 @@ GAMEEVENT_CHAT, GAMEEVENT_PLAYERCONNECT, GAMEEVENT_ACTOR_SPAWNED, + GAMEEVENT_ACTOR_DAMAGED, } GAMEEVENT_e; //***************************************************************************** diff -r deaf05345cb3 -r 9c5e95167355 src/gi.cpp --- a/src/gi.cpp Sat Sep 11 18:10:29 2021 -0400 +++ b/src/gi.cpp Sat Sep 11 18:40:06 2021 -0400 @@ -359,8 +359,10 @@ GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass") GAMEINFOKEY_BOOL(forcekillscripts, "forcekillscripts") // [JM] Force kill scripts on thing death. (MF7_NOKILLSCRIPTS overrides.) - // [AK] Forces actors to trigger GAMEEVENT_ACTOR_SPAWNED unless they have STFL_NOSPAWNEVENTSCRIPT enabled. + // [AK] Forces actors to trigger GAMEEVENT_ACTOR_SPAWNED or GAMEVENT_ACTOR_DAMAGED unless they + // enabled the STFL_NOSPAWNEVENTSCRIPT or STFL_NODAMAGEEVENTSCRIPT flags respectively. GAMEINFOKEY_BOOL(bForceSpawnEventScripts, "forcespawneventscripts") + GAMEINFOKEY_BOOL(bForceDamageEventScripts, "forcedamageeventscripts") else { diff -r deaf05345cb3 -r 9c5e95167355 src/gi.h --- a/src/gi.h Sat Sep 11 18:10:29 2021 -0400 +++ b/src/gi.h Sat Sep 11 18:40:06 2021 -0400 @@ -145,8 +145,10 @@ bool norandomplayerclass; bool forcekillscripts; - // [AK] Forces actors to trigger GAMEEVENT_ACTOR_SPAWNED unless they have STFL_NOSPAWNEVENTSCRIPT enabled. + // [AK] Forces actors to trigger GAMEEVENT_ACTOR_SPAWNED or GAMEVENT_ACTOR_DAMAGED unless they + // enabled the STFL_NOSPAWNEVENTSCRIPT or STFL_NODAMAGEEVENTSCRIPT flags respectively. bool bForceSpawnEventScripts; + bool bForceDamageEventScripts; const char *GetFinalePage(unsigned int num) const; }; diff -r deaf05345cb3 -r 9c5e95167355 src/p_acs.cpp --- a/src/p_acs.cpp Sat Sep 11 18:10:29 2021 -0400 +++ b/src/p_acs.cpp Sat Sep 11 18:40:06 2021 -0400 @@ -306,8 +306,9 @@ // [BC] When true, any console commands/line specials were executed via the ConsoleCommand p-code. static bool g_bCalledFromConsoleCommand = false; -// [AK] When true, any action or line specials were executed from an ACS script. -static bool g_bCalledFromACS = false; +// [AK] A pointer to the script currently being run. When it's not equal to NULL, it means that +// any action or line specials are being executed inside an ACS script. +static DLevelScript *g_pCurrentScript = NULL; //============================================================================ @@ -7794,7 +7795,7 @@ int temp; // [AK] Any action or line specials activated at this point are done from ACS so indicate that. - g_bCalledFromACS = true; + g_pCurrentScript = this; while (state == SCRIPT_Running) { @@ -11583,7 +11584,7 @@ } // [AK] We're done running this script so any action or line specials activated now aren't done in ACS. - g_bCalledFromACS = false; + g_pCurrentScript = NULL; // [BB] Stop the net traffic measurement and add the result to this script's traffic. NETTRAFFIC_AddACSScriptTraffic ( script, NETWORK_StopTrafficMeasurement ( ) ); @@ -11640,6 +11641,21 @@ // [TP] We need to store this as activefontname instead. activefontname = "SmallFont"; + // [AK] Check if this is an event script triggered by GAMEEVENT_ACTOR_DAMAGED. This is + // where we initialize the script's target, source, and inflictor pointers by using the + // activator as the target, and the activator's own master and target, which are the + // source and inflictor respectively. + if (( who != NULL ) && ( code->Type == SCRIPT_Event ) && ( args[0] == GAMEEVENT_ACTOR_DAMAGED )) + { + pDamageTarget = who; + pDamageSource = who->master; + pDamageInflictor = who->target; + } + else + { + pDamageTarget = pDamageSource = pDamageInflictor = NULL; + } + hudwidth = hudheight = 0; ClipRectLeft = ClipRectTop = ClipRectWidth = ClipRectHeight = WrapWidth = 0; state = SCRIPT_Running; @@ -12171,7 +12187,7 @@ // bool ACS_IsCalledFromScript( void ) { - return ( g_bCalledFromACS ); + return ( g_pCurrentScript != NULL ); } //***************************************************************************** @@ -12230,6 +12246,28 @@ //***************************************************************************** // +AActor *ACS_GetScriptDamagePointers( int pointer ) +{ + if ( g_pCurrentScript ) + { + switch ( pointer ) + { + case AAPTR_DAMAGE_SOURCE: + return g_pCurrentScript->pDamageSource; + + case AAPTR_DAMAGE_INFLICTOR: + return g_pCurrentScript->pDamageInflictor; + + case AAPTR_DAMAGE_TARGET: + return g_pCurrentScript->pDamageTarget; + } + } + + return NULL; +} + +//***************************************************************************** +// int ACS_GetTranslationIndex( FRemapTable *pTranslation ) { int translationindex; diff -r deaf05345cb3 -r 9c5e95167355 src/p_acs.h --- a/src/p_acs.h Sat Sep 11 18:10:29 2021 -0400 +++ b/src/p_acs.h Sat Sep 11 18:40:06 2021 -0400 @@ -1073,6 +1073,12 @@ FBehavior *activeBehavior; int InModuleScriptNumber; FString activefontname; // [TP] + + // [AK] Pointers to the source, inflictor, and target actors that triggered a GAMEEVENT_ACTOR_DAMAGED event. + // In all other cases, these pointers should be equal to NULL. + TObjPtr pDamageSource; + TObjPtr pDamageInflictor; + TObjPtr pDamageTarget; void Link (); void Unlink (); @@ -1115,6 +1121,8 @@ friend class ServerCommands::ReplaceTextures; // [AK] We need to access protected variables from this class when we tell the clients to print a HUD message. friend void SERVERCOMMANDS_PrintACSHUDMessage( DLevelScript *pScript, const char *pszString, float fX, float fY, LONG lType, LONG lColor, float fHoldTime, float fInTime, float fOutTime, fixed_t Alpha, LONG lID, ULONG ulPlayerExtra, ServerCommandFlags flags ); + // [AK] If the current running script is a GAMEEVENT_ACTOR_DAMAGED event, this will return a pointer to the source, inflictor, or target actor. + friend AActor *ACS_GetScriptDamagePointers( int pointer ); }; class DACSThinker : public DThinker diff -r deaf05345cb3 -r 9c5e95167355 src/p_interaction.cpp --- a/src/p_interaction.cpp Sat Sep 11 18:10:29 2021 -0400 +++ b/src/p_interaction.cpp Sat Sep 11 18:40:06 2021 -0400 @@ -1665,6 +1665,26 @@ source->player->ulUnrewardedDamageDealt += MIN( (int)lOldTargetHealth, damage ); } + // [AK] Trigger an event script indicating that the target actor has taken damage, if we can. + if ((( target->STFlags & STFL_NODAMAGEEVENTSCRIPT ) == false ) && (( target->STFlags & STFL_USEDAMAGEEVENTSCRIPT ) || ( gameinfo.bForceDamageEventScripts ))) + { + // [AK] We somehow need to pass the source and inflictor actor pointers into the script + // itself. A simple way to do this is temporarily changing the target's pointers to the + // source and inflictor, which we'll then use to initialize AAPTR_DAMAGE_SOURCE and + // AAPTR_DAMAGE_INFLICTOR for the script. + // The source actor is the activator, which we'll use to initialize AAPTR_DAMAGE_TARGET. + AActor *tempMaster = target->master; + AActor *tempTarget = target->target; + target->master = source; + target->target = inflictor; + + GAMEMODE_HandleEvent( GAMEEVENT_ACTOR_DAMAGED, target, damage ); + + // [AK] Restore the source actor's old pointers. + target->master = tempMaster; + target->target = tempTarget; + } + // [BC] Tell clients that this thing was damaged. if ( NETWORK_GetState( ) == NETSTATE_SERVER ) { diff -r deaf05345cb3 -r 9c5e95167355 src/thingdef/thingdef_data.cpp --- a/src/thingdef/thingdef_data.cpp Sat Sep 11 18:10:29 2021 -0400 +++ b/src/thingdef/thingdef_data.cpp Sat Sep 11 18:40:06 2021 -0400 @@ -270,6 +270,10 @@ DEFINE_FLAG(STFL, USESPAWNEVENTSCRIPT, AActor, STFlags), DEFINE_FLAG(STFL, NOSPAWNEVENTSCRIPT, AActor, STFlags), + // [AK] Enables/disables GAMEEVENT_ACTOR_DAMAGED for the actor. + DEFINE_FLAG(STFL, USEDAMAGEEVENTSCRIPT, AActor, STFlags), + DEFINE_FLAG(STFL, NODAMAGEEVENTSCRIPT, AActor, STFlags), + // [BB] New DECORATE network related flag defines here. DEFINE_FLAG(NETFL, NONETID, AActor, NetworkFlags), DEFINE_FLAG(NETFL, ALLOWCLIENTSPAWN, AActor, NetworkFlags),