diff --git a/vendor/gwca/Source/AgentMgr.cpp b/vendor/gwca/Source/AgentMgr.cpp index ef36d43..eb71eca 100644 --- a/vendor/gwca/Source/AgentMgr.cpp +++ b/vendor/gwca/Source/AgentMgr.cpp @@ -221,6 +221,7 @@ namespace { Logger::AssertAddress("SendAgentDialog_Func", (uintptr_t)SendAgentDialog_Func, "Agent Module"); Logger::AssertAddress("SendGadgetDialog_Func", (uintptr_t)SendGadgetDialog_Func, "Agent Module"); Logger::AssertAddress("CallTarget_Func", (uintptr_t)CallTarget_Func, "Agent Module"); + Logger::AssertAddress("DoWorldActon_Func", (uintptr_t)DoWorldActon_Func, "Agent Module"); //Logger::Instance().LogInfo("############ AgentMgr initialization complete ############"); diff --git a/vendor/gwca/Source/ChatMgr.cpp b/vendor/gwca/Source/ChatMgr.cpp index 98d40cb..e3f3b4d 100644 --- a/vendor/gwca/Source/ChatMgr.cpp +++ b/vendor/gwca/Source/ChatMgr.cpp @@ -377,6 +377,7 @@ namespace { if (!block_chat_timestamps.IsValid()) { Logger::Instance().LogError("Failed to patch chat timestamps, address not found."); } + Logger::AssertAddress("block_chat_timestamps", (uintptr_t)block_chat_timestamps.GetAddress(), "Chat Module"); Logger::AssertAddress("GetSenderColor_Func", (uintptr_t)GetSenderColor_Func, "Chat Module"); Logger::AssertAddress("GetMessageColor_Func", (uintptr_t)GetMessageColor_Func, "Chat Module"); Logger::AssertAddress("SendChat_Func", (uintptr_t)SendChat_Func, "Chat Module"); diff --git a/vendor/gwca/Source/GWCA.cpp b/vendor/gwca/Source/GWCA.cpp index e7ec96f..387f794 100644 --- a/vendor/gwca/Source/GWCA.cpp +++ b/vendor/gwca/Source/GWCA.cpp @@ -156,6 +156,44 @@ namespace GW if (module->init_module) module->init_module(); } + + // ===== Scan health summary ===== + // A GW client update can silently break a pattern scan: the resolved + // address simply comes back null and the affected feature dies quietly. + // Every scan that registered itself via Logger::AssertAddress (and every + // hook via Logger::AssertHook) is collected in a central registry; here we + // re-emit a single, easy-to-grep block listing every NULL scan / FAILED + // hook so a broken signature is obvious in Py4GW_injection_log.txt. + { + const auto& scan_results = Logger::GetScanResults(); + const auto& hook_results = Logger::GetHookResults(); + size_t scan_null = 0; + for (const auto& [name, addr] : scan_results) + if (!addr) ++scan_null; + size_t hook_failed = 0; + for (const auto& [name, status] : hook_results) + if (status != 0) ++hook_failed; + + { + std::ostringstream oss; + oss << "[SCAN-HEALTH] " << (scan_results.size() - scan_null) << "/" + << scan_results.size() << " scans resolved, " << scan_null + << " NULL | " << (hook_results.size() - hook_failed) << "/" + << hook_results.size() << " hooks ok, " << hook_failed << " FAILED"; + Logger::Instance().LogInfo(oss.str()); + } + for (const auto& [name, addr] : scan_results) + if (!addr) + Logger::Instance().LogError("[SCAN-HEALTH] NULL scan: " + name); + for (const auto& [name, status] : hook_results) + if (status != 0) { + std::ostringstream oss; + oss << "[SCAN-HEALTH] FAILED hook: " << name << " (MH_STATUS=" << status << ")"; + Logger::Instance().LogError(oss.str()); + } + } + // ===== end scan health summary ===== + _initialized = true; //Logger::Instance().LogInfo("Enabling hooks"); diff --git a/vendor/gwca/Source/ItemMgr.cpp b/vendor/gwca/Source/ItemMgr.cpp index b970a7c..a198d26 100644 --- a/vendor/gwca/Source/ItemMgr.cpp +++ b/vendor/gwca/Source/ItemMgr.cpp @@ -377,6 +377,10 @@ namespace { Logger::AssertAddress("unlocked_pvp_item_upgrade_array.m_size", (uintptr_t)unlocked_pvp_item_upgrade_array.m_size, "Item Module"); Logger::AssertAddress("GetPvPItemUpgradeInfoName_Func", (uintptr_t)GetPvPItemUpgradeInfoName_Func, "Item Module"); Logger::AssertAddress("DestroyItem_Func", (uintptr_t)DestroyItem_Func, "Item Module"); + Logger::AssertAddress("pvp_item_array.m_buffer", (uintptr_t)pvp_item_array.m_buffer, "Item Module"); + Logger::AssertAddress("pvp_item_array.m_size", (uintptr_t)pvp_item_array.m_size, "Item Module"); + Logger::AssertAddress("composite_model_info_array", (uintptr_t)composite_model_info_array, "Item Module"); + Logger::AssertAddress("item_formula_count", (uintptr_t)item_formula_count, "Item Module"); //HookBase::CreateHook((void**)&ItemClick_Func, OnItemClick, (void**)&RetItemClick); diff --git a/vendor/gwca/Source/MapMgr.cpp b/vendor/gwca/Source/MapMgr.cpp index 36c65f0..a625814 100644 --- a/vendor/gwca/Source/MapMgr.cpp +++ b/vendor/gwca/Source/MapMgr.cpp @@ -389,6 +389,8 @@ namespace { Logger::AssertAddress("EnterChallengeMission_Func", (uintptr_t)EnterChallengeMission_Func, "Map Module"); Logger::AssertAddress("CancelEnterChallengeMission_Func", (uintptr_t)CancelEnterChallengeMission_Func, "Map Module"); + Logger::AssertAddress("SkipCinematic_Func", (uintptr_t)SkipCinematic_Func, "Map Module"); + Logger::AssertAddress("instance_info_ptr", (uintptr_t)instance_info_ptr, "Map Module"); if (WorldMap_UICallback_Func) diff --git a/vendor/gwca/Source/MemoryMgr.cpp b/vendor/gwca/Source/MemoryMgr.cpp index 1a090eb..9111c2a 100644 --- a/vendor/gwca/Source/MemoryMgr.cpp +++ b/vendor/gwca/Source/MemoryMgr.cpp @@ -9,6 +9,8 @@ #include +#include + // Used to get precise skill recharge times. DWORD* GW::MemoryMgr::SkillTimerPtr = NULL; @@ -78,6 +80,14 @@ bool GW::MemoryMgr::Scan() { GWCA_INFO("[SCAN] MemReallocHelper_Func = %p", MemReallocHelper_Func); GWCA_INFO("[SCAN] MemFree_Func = %p", MemFree_Func); + Logger::AssertAddress("SkillTimerPtr", (uintptr_t)SkillTimerPtr, "MemoryModule"); + Logger::AssertAddress("WinHandlePtr", (uintptr_t)WinHandlePtr, "MemoryModule"); + Logger::AssertAddress("GetPersonalDirPtr", (uintptr_t)GetPersonalDirPtr, "MemoryModule"); + Logger::AssertAddress("GetGWVersion_Func", (uintptr_t)GetGWVersion_Func, "MemoryModule"); + Logger::AssertAddress("MemAllocHelper_Func", (uintptr_t)MemAllocHelper_Func, "MemoryModule"); + Logger::AssertAddress("MemReallocHelper_Func", (uintptr_t)MemReallocHelper_Func, "MemoryModule"); + Logger::AssertAddress("MemFree_Func", (uintptr_t)MemFree_Func, "MemoryModule"); + #ifdef _DEBUG GWCA_ASSERT(SkillTimerPtr); GWCA_ASSERT(WinHandlePtr); diff --git a/vendor/gwca/Source/SkillbarMgr.cpp b/vendor/gwca/Source/SkillbarMgr.cpp index 76c88b6..b2e23b0 100644 --- a/vendor/gwca/Source/SkillbarMgr.cpp +++ b/vendor/gwca/Source/SkillbarMgr.cpp @@ -182,12 +182,14 @@ namespace { address = Scanner::FindAssertion("TemplatesHelpers.cpp", "targetPrimaryProf == templateData.profPrimary",0,0); if (address) { ChangeSecondary_Func = (ChangeSecondary_pt)Scanner::FunctionFromNearCall(address + 0x20); - Logger::AssertAddress("ChangeSecondary_Func", (uintptr_t)ChangeSecondary_Func, "Skillbar Module"); LoadAttributes_Func = (LoadAttributes_pt)Scanner::FunctionFromNearCall(address + 0x34); - Logger::AssertAddress("LoadAttributes_Func", (uintptr_t)LoadAttributes_Func, "Skillbar Module"); LoadSkills_Func = (LoadSkills_pt)Scanner::FunctionFromNearCall(address + 0x40); - Logger::AssertAddress("LoadSkills_Func", (uintptr_t)LoadSkills_Func, "Skillbar Module"); } + // Assert unconditionally (outside the if): if the TemplatesHelpers.cpp scan + // breaks after a GW update, these stay null and would otherwise fail silently. + Logger::AssertAddress("ChangeSecondary_Func", (uintptr_t)ChangeSecondary_Func, "Skillbar Module"); + Logger::AssertAddress("LoadAttributes_Func", (uintptr_t)LoadAttributes_Func, "Skillbar Module"); + Logger::AssertAddress("LoadSkills_Func", (uintptr_t)LoadSkills_Func, "Skillbar Module"); GWCA_INFO("[SCAN] SkillArray = %p", skill_array_addr); GWCA_INFO("[SCAN] AttributeArray = %p", attribute_array_addr); diff --git a/vendor/gwca/Source/StoCMgr.cpp b/vendor/gwca/Source/StoCMgr.cpp index b9267f1..72be280 100644 --- a/vendor/gwca/Source/StoCMgr.cpp +++ b/vendor/gwca/Source/StoCMgr.cpp @@ -146,7 +146,8 @@ namespace { game_server_handlers = &(*addr)->gs_codec->handlers; } Logger::AssertAddress("StoCHandler_Addr", StoCHandler_Addr, "StoC Module"); - + Logger::AssertAddress("game_server_handlers", (uintptr_t)game_server_handlers, "StoC Module"); + } stoc_handler_count = game_server_handlers->size(); diff --git a/vendor/gwca/Source/UIMgr.cpp b/vendor/gwca/Source/UIMgr.cpp index 5c48704..9427ea3 100644 --- a/vendor/gwca/Source/UIMgr.cpp +++ b/vendor/gwca/Source/UIMgr.cpp @@ -748,8 +748,10 @@ namespace { //CreateUIComponent_Func = (CreateUIComponent_pt)Scanner::ToFunctionStart(GW::Scanner::Find("\x33\xd2\x89\x45\x08\xb9\xac\x01\x00\x00", "xxxxxxxxxx")); CreateUIComponent_Func = (CreateUIComponent_pt)Scanner::ToFunctionStart(GW::Scanner::Find("\x33\xd2\x89\x45\x08\xb9\xc8\x01\x00\x00", "xxxxxxxxxx")); + // FrApi.cpp lives under \Code\Engine\Frame (not \Code\Gw\Ui\Frame); the old path + // never matched, so this scan was silently null. Resolves to FrApi::DestroyFrame. DestroyUIComponent_Func = (DestroyUIComponent_pt)Scanner::ToFunctionStart( - Scanner::FindAssertion("\\Code\\Gw\\Ui\\Frame\\FrApi.cpp", "frame->state.Test(FRAME_STATE_CREATED)", 0, 0)); + Scanner::FindAssertion("\\Code\\Engine\\Frame\\FrApi.cpp", "frame->state.Test(FRAME_STATE_CREATED)", 0, 0)); // Graphics renderer related @@ -880,6 +882,7 @@ namespace { Logger::AssertAddress("SetMasterVolume_Func", (uintptr_t)SetMasterVolume_Func, "UIModule"); Logger::AssertAddress("DrawOnCompass_Func", (uintptr_t)DrawOnCompass_Func, "UIModule"); Logger::AssertAddress("CreateUIComponent_Func", (uintptr_t)CreateUIComponent_Func, "UIModule"); + Logger::AssertAddress("DestroyUIComponent_Func", (uintptr_t)DestroyUIComponent_Func, "UIModule"); Logger::AssertAddress("EnumPreferenceOptions_Addr", (uintptr_t)EnumPreferenceOptions_Addr, "UIModule"); Logger::AssertAddress("NumberPreferenceOptions_Addr", (uintptr_t)NumberPreferenceOptions_Addr, "UIModule"); Logger::AssertAddress("SetInGameStaticPreference_Func", (uintptr_t)SetInGameStaticPreference_Func, "UIModule"); @@ -890,6 +893,7 @@ namespace { Logger::AssertAddress("GetGraphicsRendererValue_Func", (uintptr_t)GetGraphicsRendererValue_Func, "UIModule"); Logger::AssertAddress("SetGraphicsRendererValue_Func", (uintptr_t)SetGraphicsRendererValue_Func, "UIModule"); Logger::AssertAddress("SetGameRendererMode_Func", (uintptr_t)SetGameRendererMode_Func, "UIModule"); + Logger::AssertAddress("GetGameRendererMode_Func", (uintptr_t)GetGameRendererMode_Func, "UIModule"); Logger::AssertAddress("GetGameRendererMetric_Func", (uintptr_t)GetGameRendererMetric_Func, "UIModule"); Logger::AssertAddress("FindRelatedFrame_Func", (uintptr_t)FindRelatedFrame_Func, "UIModule"); Logger::AssertAddress("GetTitle_Func", (uintptr_t)GetTitle_Func, "UIModule"); @@ -1508,6 +1512,20 @@ namespace GW { HookBase::EnableHooks(reinterpret_cast(TypedComponentPassthroughHook_Func)); } } + + Logger::AssertAddress("ButtonFrame_Callback", (uintptr_t)ButtonFrame_Callback, "UIModule"); + Logger::AssertAddress("TextButtonFrame_Callback", (uintptr_t)TextButtonFrame_Callback, "UIModule"); + Logger::AssertAddress("TextLabelFrame_Callback", (uintptr_t)TextLabelFrame_Callback, "UIModule"); + Logger::AssertAddress("ScrollableFrame_Callback", (uintptr_t)ScrollableFrame_Callback, "UIModule"); + Logger::AssertAddress("FrameList_Callback", (uintptr_t)FrameList_Callback, "UIModule"); + Logger::AssertAddress("DropdownFrame_Callback", (uintptr_t)DropdownFrame_Callback, "UIModule"); + Logger::AssertAddress("SliderFrame_Callback", (uintptr_t)SliderFrame_Callback, "UIModule"); + Logger::AssertAddress("SliderFrame_WrapperCallback", (uintptr_t)SliderFrame_WrapperCallback, "UIModule"); + Logger::AssertAddress("EditableTextFrame_Callback", (uintptr_t)EditableTextFrame_Callback, "UIModule"); + Logger::AssertAddress("ProgressBar_Callback", (uintptr_t)ProgressBar_Callback, "UIModule"); + Logger::AssertAddress("TabsFrame_Callback", (uintptr_t)TabsFrame_Callback, "UIModule"); + Logger::AssertAddress("FrameNewSubclass_Func", (uintptr_t)FrameNewSubclass_Func, "UIModule"); + Logger::AssertAddress("TypedComponentPassthroughHook_Func", (uintptr_t)TypedComponentPassthroughHook_Func, "UIModule"); } uint32_t FindAvailableChildIndex(Frame* parent, uint32_t child_index) {