diff --git a/EEex-v2.6.6.0/headers/EEex-v2.6.6.0/EEex.h b/EEex-v2.6.6.0/headers/EEex-v2.6.6.0/EEex.h index edc3203..db7c520 100644 --- a/EEex-v2.6.6.0/headers/EEex-v2.6.6.0/EEex.h +++ b/EEex-v2.6.6.0/headers/EEex-v2.6.6.0/EEex.h @@ -118,6 +118,7 @@ namespace EEex { void Opcode_Hook_OnCopy(CGameEffect* pSrcEffect, CGameEffect* pDstEffect); void Opcode_Hook_OnDestruct(CGameEffect* pEffect); void Opcode_Hook_AfterListsResolved(CGameSprite* pSprite); + void Opcode_Hook_FlushDeferredAfterListsResolved(CGameSprite* pSprite); //////////// // Sprite // diff --git a/EEex-v2.6.6.0/headers/EEex-v2.6.6.0_generated/Baldur-v2.6.6.0_generated.h b/EEex-v2.6.6.0/headers/EEex-v2.6.6.0_generated/Baldur-v2.6.6.0_generated.h index 0b0048d..a5bc1ac 100644 --- a/EEex-v2.6.6.0/headers/EEex-v2.6.6.0_generated/Baldur-v2.6.6.0_generated.h +++ b/EEex-v2.6.6.0/headers/EEex-v2.6.6.0_generated/Baldur-v2.6.6.0_generated.h @@ -4885,6 +4885,7 @@ namespace EEex extern byte CGameSprite_Hit_Roll; extern bool AIBase_LuaHook_OnEventTriggerSet_Enabled; extern bool Opcode_LuaHook_AfterListsResolved_Enabled; + extern bool Opcode_LuaHook_DeferredAfterListsResolved_Enabled; extern bool Projectile_LuaHook_GlobalMutators_Enabled; extern bool StutterDetector_Enabled; extern int UncapFPS_BusyWaitThreshold; diff --git a/EEex-v2.6.6.0/scripts/generate_bindings/in/bindings.txt b/EEex-v2.6.6.0/scripts/generate_bindings/in/bindings.txt index f4bc78e..04831cc 100644 --- a/EEex-v2.6.6.0/scripts/generate_bindings/in/bindings.txt +++ b/EEex-v2.6.6.0/scripts/generate_bindings/in/bindings.txt @@ -116,6 +116,7 @@ namespace EEex // Globals bool AIBase_LuaHook_OnEventTriggerSet_Enabled; bool Opcode_LuaHook_AfterListsResolved_Enabled; + bool Opcode_LuaHook_DeferredAfterListsResolved_Enabled; bool Projectile_LuaHook_GlobalMutators_Enabled; bool StutterDetector_Enabled; int UncapFPS_BusyWaitThreshold; diff --git a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/EEex.cpp b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/EEex.cpp index 9a80717..2f1ee18 100644 --- a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/EEex.cpp +++ b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/EEex.cpp @@ -145,6 +145,7 @@ struct ExSpriteData { EngineVal combatRoundsOverride[5]{}; Array oldDisabledSpellTypes; + bool deferredAfterListsResolvedPending = false; int oldDisableSpells = 0; uint64_t uuid = 0; @@ -3837,6 +3838,13 @@ void EEex::Opcode_Hook_AfterListsResolved(CGameSprite* pSprite) { CDerivedStats& stats = *pSprite->GetActiveStats(); lua_State *const L = luaState(); + if (EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled) { + // The engine can resolve the same sprite's effect lists many times in a + // tick. Defer opt-in Lua listeners to the sprite's real AI pass, where + // this bit is consumed and collapsed to one Lua call. + exData.deferredAfterListsResolvedPending = true; + } + if ( stats.m_disableSpells != exData.oldDisableSpells @@ -3869,6 +3877,37 @@ void EEex::Opcode_Hook_AfterListsResolved(CGameSprite* pSprite) { STUTTER_LOG_END } +void EEex::Opcode_Hook_FlushDeferredAfterListsResolved(CGameSprite* pSprite) { + + STUTTER_LOG_START(void, "EEex::Opcode_Hook_FlushDeferredAfterListsResolved") + + if (!EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled) { + return; + } + + auto itr = exSpriteDataMap.find(pSprite); + if (itr == exSpriteDataMap.end()) { + return; + } + + ExSpriteData& exData = itr->second; + if (!exData.deferredAfterListsResolvedPending) { + return; + } + + // Clear before entering Lua. If the callback causes another list + // resolution, the new pending bit survives for the next ProcessAI() pass. + exData.deferredAfterListsResolvedPending = false; + + lua_State *const L = luaState(); + luaCallProtected(L, 1, 0, [&](int _) { + lua_getglobal(L, "EEex_Opcode_LuaHook_DeferredAfterListsResolved"); // 1 [ ..., EEex_Opcode_LuaHook_DeferredAfterListsResolved ] + tolua_pushusertype(L, pSprite, "CGameSprite"); // 2 [ ..., EEex_Opcode_LuaHook_DeferredAfterListsResolved, pSpriteUD ] + }); + + STUTTER_LOG_END +} + //////////// // Sprite // //////////// @@ -5361,6 +5400,7 @@ void EEex::InitEEex() { initUncapFPS(); EEex::Opcode_LuaHook_AfterListsResolved_Enabled = false; + EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled = false; EEex::Projectile_LuaHook_GlobalMutators_Enabled = false; initProjectileMutator(); EEex::StutterDetector_Enabled = false; diff --git a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/Baldur-v2.6.6.0_generated_internal_pointers.cpp b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/Baldur-v2.6.6.0_generated_internal_pointers.cpp index 4e470c8..25b80cd 100644 --- a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/Baldur-v2.6.6.0_generated_internal_pointers.cpp +++ b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/Baldur-v2.6.6.0_generated_internal_pointers.cpp @@ -10,6 +10,7 @@ bool EEex::bStripUUID; byte EEex::CGameSprite_Hit_Roll; bool EEex::AIBase_LuaHook_OnEventTriggerSet_Enabled; bool EEex::Opcode_LuaHook_AfterListsResolved_Enabled; +bool EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled; bool EEex::Projectile_LuaHook_GlobalMutators_Enabled; bool EEex::StutterDetector_Enabled; int EEex::UncapFPS_BusyWaitThreshold; diff --git a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/EEexLua_generated.cpp b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/EEexLua_generated.cpp index 686f498..fc285ab 100644 --- a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/EEexLua_generated.cpp +++ b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/Generated/EEexLua_generated.cpp @@ -39,6 +39,24 @@ static int tolua_get_EEex_reference_Opcode_LuaHook_AfterListsResolved_Enabled(lu return 1; } +static int tolua_get_EEex_Opcode_LuaHook_DeferredAfterListsResolved_Enabled(lua_State* L) +{ + tolua_pushboolean(L, (bool)EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled); + return 1; +} + +static int tolua_set_EEex_Opcode_LuaHook_DeferredAfterListsResolved_Enabled(lua_State* L) +{ + EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled = tolua_setter_toboolean(L, "Opcode_LuaHook_DeferredAfterListsResolved_Enabled"); + return 0; +} + +static int tolua_get_EEex_reference_Opcode_LuaHook_DeferredAfterListsResolved_Enabled(lua_State* L) +{ + tolua_pushusertype(L, (void*)&EEex::Opcode_LuaHook_DeferredAfterListsResolved_Enabled, "Primitive"); + return 1; +} + static int tolua_get_EEex_Projectile_LuaHook_GlobalMutators_Enabled(lua_State* L) { tolua_pushboolean(L, (bool)EEex::Projectile_LuaHook_GlobalMutators_Enabled); @@ -917,6 +935,8 @@ int OpenBindingsInternal(lua_State* L) tolua_variable(L, "reference_AIBase_LuaHook_OnEventTriggerSet_Enabled", tolua_get_EEex_reference_AIBase_LuaHook_OnEventTriggerSet_Enabled, NULL); tolua_variable(L, "Opcode_LuaHook_AfterListsResolved_Enabled", tolua_get_EEex_Opcode_LuaHook_AfterListsResolved_Enabled, tolua_set_EEex_Opcode_LuaHook_AfterListsResolved_Enabled); tolua_variable(L, "reference_Opcode_LuaHook_AfterListsResolved_Enabled", tolua_get_EEex_reference_Opcode_LuaHook_AfterListsResolved_Enabled, NULL); + tolua_variable(L, "Opcode_LuaHook_DeferredAfterListsResolved_Enabled", tolua_get_EEex_Opcode_LuaHook_DeferredAfterListsResolved_Enabled, tolua_set_EEex_Opcode_LuaHook_DeferredAfterListsResolved_Enabled); + tolua_variable(L, "reference_Opcode_LuaHook_DeferredAfterListsResolved_Enabled", tolua_get_EEex_reference_Opcode_LuaHook_DeferredAfterListsResolved_Enabled, NULL); tolua_variable(L, "Projectile_LuaHook_GlobalMutators_Enabled", tolua_get_EEex_Projectile_LuaHook_GlobalMutators_Enabled, tolua_set_EEex_Projectile_LuaHook_GlobalMutators_Enabled); tolua_variable(L, "reference_Projectile_LuaHook_GlobalMutators_Enabled", tolua_get_EEex_reference_Projectile_LuaHook_GlobalMutators_Enabled, NULL); tolua_variable(L, "StutterDetector_Enabled", tolua_get_EEex_StutterDetector_Enabled, tolua_set_EEex_StutterDetector_Enabled); @@ -961,6 +981,7 @@ int OpenBindingsInternal(lua_State* L) tolua_function(L, "UpdateLastScrollTime", &tolua_function_EEex_UpdateLastScrollTime); tolua_constantstring(L, "usertype_AIBase_LuaHook_OnEventTriggerSet_Enabled", "Primitive"); tolua_constantstring(L, "usertype_Opcode_LuaHook_AfterListsResolved_Enabled", "Primitive"); + tolua_constantstring(L, "usertype_Opcode_LuaHook_DeferredAfterListsResolved_Enabled", "Primitive"); tolua_constantstring(L, "usertype_Projectile_LuaHook_GlobalMutators_Enabled", "Primitive"); tolua_constantstring(L, "usertype_StutterDetector_Enabled", "Primitive"); tolua_constantstring(L, "usertype_UncapFPS_BusyWaitThreshold", "Primitive"); diff --git a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/main.cpp b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/main.cpp index a0cb76e..1cdedfb 100644 --- a/EEex-v2.6.6.0/source/EEex-v2.6.6.0/main.cpp +++ b/EEex-v2.6.6.0/source/EEex-v2.6.6.0/main.cpp @@ -137,6 +137,7 @@ static void exportPatterns() { exportPattern(TEXT("EEex::Opcode_Hook_ApplySpell_ShouldFlipSplprotSourceAndTarget"), EEex::Opcode_Hook_ApplySpell_ShouldFlipSplprotSourceAndTarget); exportPattern(TEXT("EEex::Opcode_Hook_OnCheckAdd"), EEex::Opcode_Hook_OnCheckAdd); exportPattern(TEXT("EEex::Opcode_Hook_AfterListsResolved"), EEex::Opcode_Hook_AfterListsResolved); + exportPattern(TEXT("EEex::Opcode_Hook_FlushDeferredAfterListsResolved"), EEex::Opcode_Hook_FlushDeferredAfterListsResolved); //////////// // Sprite //