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..96d837e 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 @@ -41,6 +41,10 @@ namespace EEex { void DeepCopyIndex(lua_State* L, int index); void InitEEex(); long MatchObject(lua_State* L, CGameObject* pStartObject, const char* matchChunk, int nNearest, int range, EEex_MatchObjectFlags flags); + int GetMissMeleeEffectCount(CGameSprite* pSprite); + CGameEffect* GetMissMeleeEffect(CGameSprite* pSprite, int index); + int GetMissRangedEffectCount(CGameSprite* pSprite); + CGameEffect* GetMissRangedEffect(CGameSprite* pSprite, int index); //-----------------------------// // Overrides // @@ -87,9 +91,9 @@ namespace EEex { // op101 bool Opcode_Hook_Op101_ShouldEffectBypassImmunity(CGameEffect* pEffect); // op248 - void Opcode_Hook_OnOp248AddTail(CGameEffect* pOp248, CGameEffect* pEffect); + void Opcode_Hook_OnOp248AddTail(CGameEffect* pOp248, CGameEffect* pEffect, CTypedPtrList::CNode* pNode, CGameSprite* pSprite); // op249 - void Opcode_Hook_OnOp249AddTail(CGameEffect* pOp249, CGameEffect* pEffect); + void Opcode_Hook_OnOp249AddTail(CGameEffect* pOp249, CGameEffect* pEffect, CTypedPtrList::CNode* pNode, CGameSprite* pSprite); // op280 void Opcode_Hook_Op280_BeforeApplyEffect(CGameEffect* pEffect, CGameSprite* pSprite); int Opcode_Hook_Op280_GetForcedWildSurgeNumber(CGameSprite* pSprite); @@ -112,6 +116,10 @@ namespace EEex { // New op409 int Opcode_Hook_EnableActionListener_ApplyEffect(CGameEffect* pEffect, CGameSprite* pSprite); void Opcode_Hook_EnableActionListener_OnRemove(CGameEffect* pEffect, CGameSprite* pSprite); + // New op410 + void Opcode_Hook_ApplyMissMeleeEffects(CGameSprite* pAttacker, CGameSprite* pTarget); + // New op411 + void Opcode_Hook_ApplyMissRangedEffects(CGameSprite* pAttacker, CGameSprite* pTarget); int Opcode_Hook_ApplySpell_ShouldFlipSplprotSourceAndTarget(CGameEffect* pEffect); int Opcode_Hook_OnCheckAdd(CGameEffect* pEffect, CGameSprite* pSprite); 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..3cc9fbd 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 @@ -4902,6 +4902,10 @@ namespace EEex void ForceScrollbarRenderForItemName(lua_State* L); const char* FormatPointerAsEngine(uintptr_t ptr); int GetExtendedStatValue(CGameSprite* pSprite, int exStatID); + int GetMissMeleeEffectCount(CGameSprite* pSprite); + CGameEffect* GetMissMeleeEffect(CGameSprite* pSprite, int index); + int GetMissRangedEffectCount(CGameSprite* pSprite); + CGameEffect* GetMissRangedEffect(CGameSprite* pSprite, int index); int GetHighestRefreshRate(); void GetINIString(lua_State* L, const char* iniPath, const char* section, const char* key, const char* def); long long GetMicroseconds(); 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..4a65432 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 @@ -134,6 +134,10 @@ namespace EEex $external_implementation $pass_lua_state void ForceScrollbarRenderForItemName(); $external_implementation primitive const char* FormatPointerAsEngine(uintptr_t ptr); $external_implementation int GetExtendedStatValue(CGameSprite* pSprite, int exStatID); + $external_implementation int GetMissMeleeEffectCount(CGameSprite* pSprite); + $external_implementation CGameEffect* GetMissMeleeEffect(CGameSprite* pSprite, int index); + $external_implementation int GetMissRangedEffectCount(CGameSprite* pSprite); + $external_implementation CGameEffect* GetMissRangedEffect(CGameSprite* pSprite, int index); $external_implementation int GetHighestRefreshRate(); $external_implementation $custom_return_1 GetINIString(primitive const char* iniPath, primitive const char* section, primitive const char* key, primitive const char* def); $external_implementation long long GetMicroseconds(); 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..a68af51 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 @@ -103,6 +103,10 @@ struct ExStatData { std::vector projectileMutatorEffects; // op409 std::vector enableActionListenerEffects; + // op410 + std::vector missMeleeEffects; + // op411 + std::vector missRangedEffects; }; std::unordered_map exStatDataMap{}; @@ -126,7 +130,7 @@ std::unordered_map exScriptDataMap{}; //////////// struct ExEffectInfo { - bool bypassOp120; + bool bypassOp120 = false; }; std::unordered_map exEffectInfoMap{}; @@ -219,6 +223,151 @@ void removeCachedEffect(CDerivedStats& stats, std::vector ExStatDa removeCachedEffect(stats, vectorPtr, compare); } +using CApplyEffectListNode = CTypedPtrList::CNode; + +void destroyOwnedEffect(CGameEffect *const pEffect) { + + if (pEffect != nullptr) { + pEffect->virtual_Destruct(1); + } +} + +void destroyOwnedEffects(std::vector& effects) { + + for (CGameEffect *const pEffect : effects) { + destroyOwnedEffect(pEffect); + } + + effects.clear(); +} + +CGameEffect* copyOwnedEffect(CGameEffect *const pEffect) { + + if (pEffect == nullptr) { + return nullptr; + } + + CGameEffect *const pCopy = pEffect->virtual_Copy(); + + if (pCopy != nullptr) { + exEffectInfoMap[pCopy] = exEffectInfoMap[pEffect]; + } + + return pCopy; +} + +void copyOwnedEffects(std::vector& effects, const std::vector& otherEffects) { + + for (CGameEffect *const pOtherEffect : otherEffects) { + if (CGameEffect *const pCopy = copyOwnedEffect(pOtherEffect)) { + effects.emplace_back(pCopy); + } + } +} + +void replaceOwnedEffects(std::vector& effects, const std::vector& otherEffects) { + destroyOwnedEffects(effects); + copyOwnedEffects(effects, otherEffects); +} + +void destroyOwnedMissEffects(ExStatData& exStatData) { + destroyOwnedEffects(exStatData.missMeleeEffects); + destroyOwnedEffects(exStatData.missRangedEffects); +} + +void transferAddedEffectToMissList(CGameSprite *const pSprite, CApplyEffectList& sourceList, CApplyEffectListNode *const pNode, + CGameEffect *const pEffect, std::vector ExStatData::*const missListPtr) +{ + if (pSprite == nullptr || pEffect == nullptr || pNode == nullptr) { + return; + } + + if (sourceList.m_pNodeTail == pNode && pNode->data == pEffect) { + // op410/op411 reuse the vanilla op248/op249 ApplyEffect() decoders. Those + // decoders append the child effect to the normal on-hit lists; immediately + // detach that exact new node and make EEex responsible for destroying it. + sourceList.RemoveAt(pNode); + (exStatDataMap[&pSprite->m_derivedStats].*missListPtr).emplace_back(pEffect); + } +} + +std::vector* getMissEffectList(CGameSprite *const pSprite, const bool ranged) { + + if (pSprite == nullptr) { + return nullptr; + } + + std::vector ExStatData::*const listPtr = ranged ? &ExStatData::missRangedEffects : &ExStatData::missMeleeEffects; + CDerivedStats *const pActiveStats = pSprite->GetActiveStats(); + + if (pActiveStats != nullptr) { + // Most reads should come from the active derived-stat object, which may be + // m_derivedStats, m_tempStats, or m_bonusStats depending on the caller. + if (auto it = exStatDataMap.find(pActiveStats); it != exStatDataMap.end() && !(it->second.*listPtr).empty()) { + return &(it->second.*listPtr); + } + } + + if (pActiveStats != &pSprite->m_derivedStats) { + // During application, op248/op249 populate m_derivedStats before stat-list + // propagation has copied the EEex-owned children into the active list. + if (auto it = exStatDataMap.find(&pSprite->m_derivedStats); it != exStatDataMap.end() && !(it->second.*listPtr).empty()) { + return &(it->second.*listPtr); + } + } + + return nullptr; +} + +CGameEffect* getMissEffect(CGameSprite *const pSprite, const bool ranged, const int index) { + + if (index < 0) { + return nullptr; + } + + std::vector *const pList = getMissEffectList(pSprite, ranged); + + if (pList == nullptr || static_cast(index) >= pList->size()) { + return nullptr; + } + + return (*pList)[index]; +} + +CGameEffect* copyEffectForMissApplication(CGameSprite *const pAttacker, CGameSprite *const pTarget, CGameEffect *const pEffect) { + + if (pAttacker == nullptr || pTarget == nullptr || pEffect == nullptr) { + return nullptr; + } + + CGameEffect *const pExtraEffect = copyOwnedEffect(pEffect); + + if (pExtraEffect == nullptr) { + return nullptr; + } + + // Match the existing op248/op249 helper behavior: child effects originate + // from the attacker, but their source target / target position is the attack + // target that was missed. + pExtraEffect->m_sourceId = pAttacker->m_id; + pExtraEffect->m_source = pAttacker->m_pos; + pExtraEffect->m_sourceTarget = pTarget->m_id; + pExtraEffect->m_target = pTarget->m_pos; + + return pExtraEffect; +} + +void sendAddEffectMessage(CGameEffect *const pEffect, const int caller, const int target) { + + if (pEffect == nullptr || p_g_pBaldurChitin == nullptr || *p_g_pBaldurChitin == nullptr) { + destroyOwnedEffect(pEffect); + return; + } + + CMessageAddEffect *const pMessage = newEngineObj(pEffect, false, 1, caller, target); + (*p_g_pBaldurChitin)->m_cMessageHandler.AddMessage(pMessage, false); +} + //-----------------------------// // Math Util // //-----------------------------// @@ -1567,6 +1716,26 @@ bool EEex::ShouldEffectBypassOp120(CGameEffect* pEffect) { return exEffectInfoMap[pEffect].bypassOp120; } +int EEex::GetMissMeleeEffectCount(CGameSprite* pSprite) { + + std::vector *const pList = getMissEffectList(pSprite, false); + return pList != nullptr ? static_cast(pList->size()) : 0; +} + +CGameEffect* EEex::GetMissMeleeEffect(CGameSprite* pSprite, int index) { + return getMissEffect(pSprite, false, index); +} + +int EEex::GetMissRangedEffectCount(CGameSprite* pSprite) { + + std::vector *const pList = getMissEffectList(pSprite, true); + return pList != nullptr ? static_cast(pList->size()) : 0; +} + +CGameEffect* EEex::GetMissRangedEffect(CGameSprite* pSprite, int index) { + return getMissEffect(pSprite, true, index); +} + int EEex::GetExtendedStatValue(CGameSprite* pSprite, int exStatId) { auto& exStatValues = exStatDataMap[pSprite->GetActiveStats()].exStatValues; @@ -3224,6 +3393,10 @@ void EEex::Stats_Hook_OnDestruct(CDerivedStats* pStats) { STUTTER_LOG_START(void, "EEex::Stats_Hook_OnDestruct") + if (auto it = exStatDataMap.find(pStats); it != exStatDataMap.end()) { + destroyOwnedMissEffects(it->second); + } + exStatDataMap.erase(pStats); STUTTER_LOG_END @@ -3255,6 +3428,9 @@ void EEex::Stats_Hook_OnReload(CGameSprite* pSprite) { // op409 exStatData.enableActionListenerEffects.clear(); + // op410 / op411 + destroyOwnedMissEffects(exStatData); + STUTTER_LOG_END } @@ -3306,6 +3482,12 @@ void EEex::Stats_Hook_OnEqu(CDerivedStats* pStats, CDerivedStats* pOtherStats) { data.pEffect = otherEnableActionListener.pEffect; } + // op410 / op411 + if (pStats != pOtherStats) { + replaceOwnedEffects(exStatData.missMeleeEffects, otherExStatData.missMeleeEffects); + replaceOwnedEffects(exStatData.missRangedEffects, otherExStatData.missRangedEffects); + } + STUTTER_LOG_END } @@ -3356,6 +3538,12 @@ void EEex::Stats_Hook_OnPlusEqu(CDerivedStats* pStats, CDerivedStats* pOtherStat data.pEffect = otherEnableActionListener.pEffect; } + // op410 / op411 + if (pStats != pOtherStats) { + copyOwnedEffects(exStatData.missMeleeEffects, otherExStatData.missMeleeEffects); + copyOwnedEffects(exStatData.missRangedEffects, otherExStatData.missRangedEffects); + } + STUTTER_LOG_END } @@ -3394,14 +3582,22 @@ bool EEex::Opcode_Hook_Op101_ShouldEffectBypassImmunity(CGameEffect* pEffect) { // op248 // //-------// -void EEex::Opcode_Hook_OnOp248AddTail(CGameEffect* pOp248, CGameEffect* pEffect) { +void EEex::Opcode_Hook_OnOp248AddTail(CGameEffect* pOp248, CGameEffect* pEffect, CApplyEffectListNode* pNode, CGameSprite* pSprite) { STUTTER_LOG_START(void, "EEex::Opcode_Hook_OnOp248AddTail") + if (pOp248 == nullptr || pEffect == nullptr) { + return; + } + if ((pOp248->m_special & 1) != 0) { exEffectInfoMap[pEffect].bypassOp120 = true; } + if (pOp248->m_effectId == 410 && pSprite != nullptr) { + transferAddedEffectToMissList(pSprite, pSprite->m_derivedStats.m_cExtraMeleeEffects, pNode, pEffect, &ExStatData::missMeleeEffects); + } + STUTTER_LOG_END } @@ -3409,14 +3605,22 @@ void EEex::Opcode_Hook_OnOp248AddTail(CGameEffect* pOp248, CGameEffect* pEffect) // op249 // //-------// -void EEex::Opcode_Hook_OnOp249AddTail(CGameEffect* pOp249, CGameEffect* pEffect) { +void EEex::Opcode_Hook_OnOp249AddTail(CGameEffect* pOp249, CGameEffect* pEffect, CApplyEffectListNode* pNode, CGameSprite* pSprite) { STUTTER_LOG_START(void, "EEex::Opcode_Hook_OnOp249AddTail") + if (pOp249 == nullptr || pEffect == nullptr) { + return; + } + if ((pOp249->m_special & 1) != 0) { exEffectInfoMap[pEffect].bypassOp120 = true; } + if (pOp249->m_effectId == 411 && pSprite != nullptr) { + transferAddedEffectToMissList(pSprite, pSprite->m_derivedStats.m_cExtraRangedEffects, pNode, pEffect, &ExStatData::missRangedEffects); + } + STUTTER_LOG_END } @@ -3707,9 +3911,9 @@ void EEex::Opcode_Hook_ProjectileMutator_OnRemove(CGameEffect* pEffect, CGameSpr STUTTER_LOG_END } -//-----------------// -// START New op409 // -//-----------------// +//-----------// +// New op409 // +//-----------// int EEex::Opcode_Hook_EnableActionListener_ApplyEffect(CGameEffect* pEffect, CGameSprite* pSprite) { @@ -3736,8 +3940,164 @@ void EEex::Opcode_Hook_EnableActionListener_OnRemove(CGameEffect* pEffect, CGame STUTTER_LOG_END } +//-----------// +// New op410 // +//-----------// + +void EEex::Opcode_Hook_ApplyMissMeleeEffects(CGameSprite* pAttacker, CGameSprite* pTarget) { + + STUTTER_LOG_START(void, "EEex::Opcode_Hook_ApplyMissMeleeEffects") + + if (pAttacker == nullptr || pTarget == nullptr) { + return; + } + + std::vector *const pMissEffects = getMissEffectList(pAttacker, false); + + if (pMissEffects != nullptr) { + for (CGameEffect *const pEffect : *pMissEffects) { + + if (pEffect == nullptr) { + continue; + } + + if ((pEffect->m_special & 4) != 0 && pAttacker->m_equipment.m_selectedWeapon != 10) { + continue; + } + + sendAddEffectMessage(copyEffectForMissApplication(pAttacker, pTarget, pEffect), pAttacker->m_id, pTarget->m_id); + } + } + + STUTTER_LOG_END +} + +//-----------------// +// START New op411 // +//-----------------// + +void EEex::Opcode_Hook_ApplyMissRangedEffects(CGameSprite* pAttacker, CGameSprite* pTarget) { + + STUTTER_LOG_START(void, "EEex::Opcode_Hook_ApplyMissRangedEffects") + + if (pAttacker == nullptr || pTarget == nullptr) { + return; + } + + std::vector *const pMissEffects = getMissEffectList(pAttacker, true); + + if (pMissEffects == nullptr) { + return; + } + + for (CGameEffect *const pEffect : *pMissEffects) { + + CGameEffect *const pExtraEffect = copyEffectForMissApplication(pAttacker, pTarget, pEffect); + + if (pExtraEffect == nullptr) { + continue; + } + + switch (pExtraEffect->m_targetType) { + case 0: { + // Vanilla op249 only treats target type 1 specially; target type 0 + // normally falls through to projectile delivery. A miss has no later + // projectile hit to resolve against, so deliver preset-target children + // directly to the creature whose attack roll was missed. + sendAddEffectMessage(pExtraEffect, pAttacker->m_id, pTarget->m_id); + break; + } + + case 1: { + sendAddEffectMessage(pExtraEffect, pAttacker->m_id, pAttacker->m_id); + break; + } + + case 3: { + pExtraEffect->m_flags |= 4; + pAttacker->ApplyEffectToParty(pExtraEffect); + destroyOwnedEffect(pExtraEffect); + break; + } + + case 4: { + pExtraEffect->m_flags |= 4; + if (pAttacker->m_pArea != nullptr) { + pAttacker->m_pArea->ApplyEffect(pExtraEffect, false, false, 0, nullptr); + } + destroyOwnedEffect(pExtraEffect); + break; + } + + case 5: { + pExtraEffect->m_flags |= 4; + if (pAttacker->m_pArea != nullptr) { + pAttacker->m_pArea->ApplyEffect(pExtraEffect, true, false, 0, nullptr); + } + destroyOwnedEffect(pExtraEffect); + break; + } + + case 6: { + pExtraEffect->m_flags |= 4; + CInfGame *const pGame = p_g_pBaldurChitin != nullptr && *p_g_pBaldurChitin != nullptr ? (*p_g_pBaldurChitin)->m_pObjectGame : nullptr; + + if (pGame != nullptr && pGame->GetCharacterPortraitNum(pAttacker->m_id) == -1) { + if (pAttacker->m_pArea != nullptr) { + pAttacker->m_pArea->ApplyEffect(pExtraEffect, false, true, pAttacker->m_typeAI.m_Specifics, nullptr); + } + } + else { + pAttacker->ApplyEffectToParty(pExtraEffect); + } + + destroyOwnedEffect(pExtraEffect); + break; + } + + case 7: { + pExtraEffect->m_flags |= 4; + destroyOwnedEffect(pExtraEffect); + break; + } + + case 8: { + pExtraEffect->m_flags |= 4; + if (pAttacker->m_pArea != nullptr) { + pAttacker->m_pArea->ApplyEffect(pExtraEffect, false, false, 0, pAttacker); + } + destroyOwnedEffect(pExtraEffect); + break; + } + + case 9: { + pExtraEffect->m_flags |= 8; + if (pAttacker->m_curProjectile != nullptr) { + pAttacker->m_curProjectile->AddEffect(pExtraEffect); + } + else { + destroyOwnedEffect(pExtraEffect); + } + break; + } + + default: { + if (pAttacker->m_curProjectile != nullptr) { + pAttacker->m_curProjectile->AddEffect(pExtraEffect); + } + else { + destroyOwnedEffect(pExtraEffect); + } + break; + } + } + } + + STUTTER_LOG_END +} + //---------------// -// END New op409 // +// END New op411 // //---------------// int EEex::Opcode_Hook_ApplySpell_ShouldFlipSplprotSourceAndTarget(CGameEffect* pEffect) { 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..4bcf28d 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 @@ -234,6 +234,34 @@ static int tolua_function_EEex_GetExtendedStatValue(lua_State* L) return 1; } +static int tolua_function_EEex_GetMissMeleeEffectCount(lua_State* L) +{ + int returnVal = EEex::GetMissMeleeEffectCount((CGameSprite*)tolua_tousertype_dynamic(L, 1, 0, "CGameSprite")); + lua_pushinteger(L, (lua_Integer)returnVal); + return 1; +} + +static int tolua_function_EEex_GetMissMeleeEffect(lua_State* L) +{ + CGameEffect* returnVal = EEex::GetMissMeleeEffect((CGameSprite*)tolua_tousertype_dynamic(L, 1, 0, "CGameSprite"), tolua_function_tointeger(L, 2, "GetMissMeleeEffect")); + tolua_pushusertype(L, (void*)returnVal, "CGameEffect"); + return 1; +} + +static int tolua_function_EEex_GetMissRangedEffectCount(lua_State* L) +{ + int returnVal = EEex::GetMissRangedEffectCount((CGameSprite*)tolua_tousertype_dynamic(L, 1, 0, "CGameSprite")); + lua_pushinteger(L, (lua_Integer)returnVal); + return 1; +} + +static int tolua_function_EEex_GetMissRangedEffect(lua_State* L) +{ + CGameEffect* returnVal = EEex::GetMissRangedEffect((CGameSprite*)tolua_tousertype_dynamic(L, 1, 0, "CGameSprite"), tolua_function_tointeger(L, 2, "GetMissRangedEffect")); + tolua_pushusertype(L, (void*)returnVal, "CGameEffect"); + return 1; +} + static int tolua_function_EEex_GetHighestRefreshRate(lua_State* L) { int returnVal = EEex::GetHighestRefreshRate(); @@ -941,6 +969,10 @@ int OpenBindingsInternal(lua_State* L) tolua_function(L, "ForceScrollbarRenderForItemName", &tolua_function_EEex_ForceScrollbarRenderForItemName); tolua_function(L, "FormatPointerAsEngine", &tolua_function_EEex_FormatPointerAsEngine); tolua_function(L, "GetExtendedStatValue", &tolua_function_EEex_GetExtendedStatValue); + tolua_function(L, "GetMissMeleeEffectCount", &tolua_function_EEex_GetMissMeleeEffectCount); + tolua_function(L, "GetMissMeleeEffect", &tolua_function_EEex_GetMissMeleeEffect); + tolua_function(L, "GetMissRangedEffectCount", &tolua_function_EEex_GetMissRangedEffectCount); + tolua_function(L, "GetMissRangedEffect", &tolua_function_EEex_GetMissRangedEffect); tolua_function(L, "GetHighestRefreshRate", &tolua_function_EEex_GetHighestRefreshRate); tolua_function(L, "GetINIString", &tolua_function_EEex_GetINIString); tolua_function(L, "GetMicroseconds", &tolua_function_EEex_GetMicroseconds); 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..6c7cf42 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 @@ -131,6 +131,10 @@ static void exportPatterns() { // New op409 exportPattern(TEXT("EEex::Opcode_Hook_EnableActionListener_ApplyEffect"), EEex::Opcode_Hook_EnableActionListener_ApplyEffect); exportPattern(TEXT("EEex::Opcode_Hook_EnableActionListener_OnRemove"), EEex::Opcode_Hook_EnableActionListener_OnRemove); + // New op410 + exportPattern(TEXT("EEex::Opcode_Hook_ApplyMissMeleeEffects"), EEex::Opcode_Hook_ApplyMissMeleeEffects); + // New op411 + exportPattern(TEXT("EEex::Opcode_Hook_ApplyMissRangedEffects"), EEex::Opcode_Hook_ApplyMissRangedEffects); exportPattern(TEXT("EEex::Opcode_Hook_OnCopy"), EEex::Opcode_Hook_OnCopy); exportPattern(TEXT("EEex::Opcode_Hook_OnDestruct"), EEex::Opcode_Hook_OnDestruct);