From ff83912b6b7ed84959b96ad368a4e676b358920c Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Wed, 28 Oct 2026 20:41:46 +0000 Subject: [PATCH] Decompile 9 functions in Source/Contents/Messenger/ClientMessenger.cpp, Source/Client/Session.h, ... Batch #1711 by ragnarok-clanker: 0 byte-identical, 9 confirmed by peer review. - fn_23304 SessionMessengerContext::UpdateRandomStats: logic confirmed by peer review - fn_05603 EquipmentPropertyStore::EquipmentPropertyStore: logic confirmed by peer review - fn_05771 EquipmentPropertyStore::Clear: logic confirmed by peer review - fn_05740 EquipmentPropertyStore::~EquipmentPropertyStore: logic confirmed by peer review - fn_05807 EquipmentPropertyGroup::~EquipmentPropertyGroup: logic confirmed by peer review - fn_06013 EquipmentProperties::CEquipmentPropertiesMgr::CEquipmentPropertiesMgr: logic confirmed by peer review - fn_06170 EquipmentProperties::CEquipmentPropertiesMgr::Clear: logic confirmed by peer review - fn_17276 UIWindowMgr::NotifyItemWindows: logic confirmed by peer review - fn_21290 CGameMode::NotifyItemBounds: logic confirmed by peer review Peer-reviewed-by: eAthena Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Client/Mode/CGameMode.h | 5 +- Source/Client/Session.h | 9 +- Source/Contents/Messenger/ClientMessenger.cpp | 268 ++++++++++++++++++ Source/UI/Window/UIWindowMgr.h | 3 + 4 files changed, 282 insertions(+), 3 deletions(-) diff --git a/Source/Client/Mode/CGameMode.h b/Source/Client/Mode/CGameMode.h index 4a13538..c806159 100644 --- a/Source/Client/Mode/CGameMode.h +++ b/Source/Client/Mode/CGameMode.h @@ -21,7 +21,9 @@ public: /* 00D0 */ CView* camera; /* 00D4 */ unsigned char unknown_00D4[0x8C]; /* 0160 */ CActorNameCardHolder nameCard; - /* 0194 */ unsigned char unknown_0194[0x174]; + /* 0194 */ unsigned char unknown_0194[0x120]; + /* 02B4 */ UIWindow* itemWindow; + /* 02B8 */ unsigned char unknown_02B8[0x50]; /* 0308 */ ModeDragState drag; /* 03C8 */ unsigned char unknown_03C8[0x2A8]; @@ -29,6 +31,7 @@ public: void WorldCell(float x, float z, int& column, int& row) const; void PlayerCell(int* column, int* row) const; void ReceiveActorNameAll(const ActorNameAllPacket* packet); + void NotifyItemBounds(); }; #if defined(_WIN32) && !defined(_WIN64) diff --git a/Source/Client/Session.h b/Source/Client/Session.h index 4e3d4ff..6f3484c 100644 --- a/Source/Client/Session.h +++ b/Source/Client/Session.h @@ -88,7 +88,9 @@ public: /* 156C */ XmlDocument m_petTalkTable; /* 159C */ XmlDocument m_monsterSkillInfo; /* 15CC */ XmlDocument m_monsterTalkTable; - /* 15FC */ unsigned char unknown_15FC[0x10]; + /* 15FC */ unsigned char unknown_15FC[8]; + /* 1604 */ int unknown_1604; + /* 1608 */ unsigned char unknown_1608[4]; /* 160C */ char m_navigationPlayerMap[0x1C]; /* 1628 */ int m_job; /* 162C */ unsigned char unknown_162C[0x24]; @@ -111,7 +113,10 @@ public: /* 52B8 */ std::vector m_accessoryNames; /* 52C4 */ unsigned char unknown_52C4[0x294]; /* 5558 */ int unknown_5558; - /* 555C */ unsigned char unknown_555C[0xD0]; + /* 555C */ unsigned char unknown_555C[0xC]; + /* 5568 */ int unknown_5568; + /* 556C */ int unknown_556C; + /* 5570 */ unsigned char unknown_5570[0xBC]; /* 562C */ char m_mercenaryName[32]; /* 564C */ int m_mercenaryStats[8]; /* 566C */ int m_mercenaryHp; diff --git a/Source/Contents/Messenger/ClientMessenger.cpp b/Source/Contents/Messenger/ClientMessenger.cpp index e483f04..1f5c245 100644 --- a/Source/Contents/Messenger/ClientMessenger.cpp +++ b/Source/Contents/Messenger/ClientMessenger.cpp @@ -1,10 +1,23 @@ #include "Contents/Messenger/ClientMessenger.h" #include "Contents/Effects/PartyMemberEffects.h" +#include "Client/Mode/ActiveGameMode.h" +#include "Client/Mode/CGameMode.h" +#include "Client/Session.h" +#include "Contents/ClientState.h" #include "Contents/Items/ItemInfo.h" +#include "Script/LuaInstance.h" +#include "UI/Window/UIWindow.h" #include "UI/Window/UIWindowMgr.h" +#include +#include #include +#include #include +#include +#include +#include +#include void __fastcall RefreshItemWindows(UIWindowMgr* mgr); @@ -30,6 +43,175 @@ static_assert(offsetof(SessionItemLists, items_1730) == 0x1730); static_assert(offsetof(SessionItemLists, items_1780) == 0x1780); #endif +struct EquipmentProperty { + virtual ~EquipmentProperty() = default; +}; + +struct EquipmentProperty1 : EquipmentProperty {}; + +struct EquipmentProperty2 : EquipmentProperty {}; + +struct EquipmentProperty3 : EquipmentProperty {}; + +struct EquipmentValueA { + /* 0000 */ int value; +}; + +struct EquipmentValueB { + /* 0000 */ int value; +}; + +struct EquipmentValueC { + /* 0000 */ int value; +}; + +struct EquipmentEntryA { + /* 0000 */ int value; +}; + +struct EquipmentEntryB { + /* 0000 */ int value; +}; + +struct EquipmentPropertyDefinition { + /* 0000 */ unsigned char unknown_0000[8]; + /* 0008 */ std::string unknown_0008; + /* 0020 */ std::vector unknown_0020; + /* 002C */ unsigned char unknown_002C[8]; + /* 0034 */ std::vector unknown_0034; + /* 0040 */ int unknown_0040; + /* 0044 */ std::string unknown_0044; + /* 005C */ std::map unknown_005C; + /* 0064 */ std::string unknown_0064; + /* 007C */ int unknown_007C; +}; + +struct EquipmentPropertyGroup { + /* 0000 */ std::string unknown_0000; + /* 0018 */ std::map definitions; + ~EquipmentPropertyGroup(); +}; + +struct EquipmentPropertyStore { + /* 0000 */ std::map> properties; + /* 0008 */ std::unordered_map names; + + EquipmentPropertyStore(); + ~EquipmentPropertyStore(); + void Clear(); +}; + +struct EquipmentPropertyMaps { + /* 0000 */ int unknown_0000; + /* 0004 */ std::unordered_map first; + /* 0024 */ std::unordered_map second; +}; + +namespace EquipmentProperties { + class CEquipmentPropertiesMgr { + public: + /* 0004 */ CLuaInstance script; + /* 000C */ std::uint16_t unknown_000C; + /* 0010 */ int unknown_0010; + /* 0014 */ int unknown_0014; + /* 0018 */ EquipmentPropertyStore* store; + /* 001C */ int unknown_001C; + /* 0020 */ int unknown_0020; + /* 0024 */ std::unordered_map properties1; + /* 0044 */ std::unordered_map properties2; + /* 0064 */ std::unordered_map properties3; + /* 0084 */ std::set unknown_0084; + /* 008C */ std::map unknown_008C; + /* 0094 */ std::unordered_map unknown_0094; + /* 00B4 */ std::unordered_map unknown_00B4; + /* 00D4 */ std::unordered_map> unknown_00D4; + /* 00F4 */ std::unordered_map> unknown_00F4; + /* 0114 */ std::unordered_map> unknown_0114; + /* 0134 */ std::unordered_map unknown_0134; + /* 0154 */ std::unordered_map> unknown_0154; + /* 0174 */ std::unordered_map unknown_0174; + /* 0194 */ std::map unknown_0194; + /* 019C */ std::unordered_map unknown_019C; + /* 01BC */ std::unordered_map> unknown_01BC; + /* 01DC */ std::unordered_map> unknown_01DC; + + CEquipmentPropertiesMgr(); + virtual ~CEquipmentPropertiesMgr(); + void Clear(); + }; +} + +// GLOBAL: gl_24723 +int g_resetMessengerRandomStats = 1; + +// GLOBAL: gl_24724 +EquipmentProperties::CEquipmentPropertiesMgr* g_equipmentPropertiesMgr; + +// OFFSET: 0x0068A340 +// FUNCTION: fn_05603 +EquipmentPropertyStore::EquipmentPropertyStore() = default; + +// OFFSET: 0x00698CE0 +// FUNCTION: fn_05771 +void EquipmentPropertyStore::Clear() { + for (auto& group : this->properties) { + for (auto& property : group.second) { + delete property.second; + } + } + this->properties.clear(); + this->names.clear(); +} + +// OFFSET: 0x006965A0 +// FUNCTION: fn_05740 +EquipmentPropertyStore::~EquipmentPropertyStore() { + this->Clear(); +} + +// OFFSET: 0x0069BB80 +// FUNCTION: fn_05807 +EquipmentPropertyGroup::~EquipmentPropertyGroup() { + for (auto& definition : this->definitions) { + delete definition.second; + } +} + +// OFFSET: 0x006A1AA0 +// FUNCTION: fn_06013 +EquipmentProperties::CEquipmentPropertiesMgr::CEquipmentPropertiesMgr() + : unknown_000C(1), unknown_0010(-1), unknown_0014(-1), store(new EquipmentPropertyStore), unknown_001C(0), unknown_0020(0) { +} + +// OFFSET: 0x006ABE90 +// FUNCTION: fn_06170 +void EquipmentProperties::CEquipmentPropertiesMgr::Clear() { + this->unknown_001C = 0; + this->unknown_0084.clear(); + for (auto& property : this->properties1) { + delete property.second; + } + this->properties1.clear(); + for (auto& property : this->properties2) { + delete property.second; + } + this->properties2.clear(); + for (auto& property : this->properties3) { + delete property.second; + } + this->properties3.clear(); + this->store->Clear(); +} + +// OFFSET: 0x006A56C0 + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(EquipmentPropertyDefinition) == 0x80); +static_assert(sizeof(EquipmentPropertyGroup) == 0x20); +static_assert(sizeof(EquipmentPropertyStore) == 0x28); +static_assert(sizeof(EquipmentProperties::CEquipmentPropertiesMgr) == 0x1FC); +#endif + // OFFSET: 0x00DDFFE0 // FUNCTION: fn_23451 std::int32_t ClientMessenger::MemberColor(int index) { @@ -294,7 +476,93 @@ struct SessionMessengerContext { int GetList5Size() const; }; +struct ItemNotificationWindow : UIWindow { + /* 0080 */ unsigned char unknown_0080[0x34]; + /* 00B4 */ MessengerMember member; +}; + +// OFFSET: 0x00AAAF10 +// FUNCTION: fn_17276 +void UIWindowMgr::NotifyItemWindows(int accountId, int lower, int upper) { + for (UIWindow* window : this->snapExcluded) { + bool matches; + { + MessengerMember member = static_cast(window)->member; + matches = member.accountId == accountId; + } + if (matches) { + window->SendMsg(nullptr, 6, 34, accountId, lower, upper); + break; + } + } +} + +// OFFSET: 0x00CD6E40 +// FUNCTION: fn_21290 +void CGameMode::NotifyItemBounds() { + if (this->itemWindow) { + this->itemWindow->Invalidate(); + } + if (g_windowMgr.window_02C8) { + g_windowMgr.window_02C8->SendMsg(nullptr, 6, 34, g_session.unknown_1604, 0, 0); + } + g_windowMgr.NotifyItemWindows(g_session.unknown_1604, g_session.unknown_5568, g_session.unknown_556C); +} + // OFFSET: 0x00DD80A0 +// FUNCTION: fn_23304 +void SessionMessengerContext::UpdateRandomStats() { + if (g_resetMessengerRandomStats != 0) { + g_resetMessengerRandomStats = 0; + this->stat34 = std::max(std::rand() % 12, 0); + this->stat30 = std::max(std::rand() % 12, 0); + this->stat3C = std::max(std::rand() % 12, 0); + this->stat2C = std::max(std::rand() % 12, 0); + this->stat38 = std::max(std::rand() % 12, 0); + } + + const int bound70 = this->bound70; + const int bound74 = this->bound74; + const int bound68 = this->bound68; + const int bound6C = this->bound6C; + this->stat34 = std::max(std::rand() % 12, 0); + this->stat2C = std::max(std::rand() % 12, 0); + this->stat38 = std::max(std::rand() % 12, 0); + this->stat30 = std::max(std::rand() % 12, 0); + this->stat3C = std::max(std::rand() % 12, 0); + for (int& value : this->stats) { + value = std::max(std::abs(std::rand()) % 1, 0); + } + + const auto notify = [this]() { + if (g_world.ActiveGameMode()) { + if (g_windowMgr.unknown_01DC) { + if (this->bound6C < this->bound68 || this->bound74 < this->bound70) { + return; + } + reinterpret_cast(g_windowMgr.unknown_01DC)->Invalidate(); + reinterpret_cast(g_windowMgr.unknown_01DC)->InvalidateChildren(); + } + static_cast(g_world.ActiveGameMode())->NotifyItemBounds(); + } + }; + if (this->bound68 != bound68) { + this->bound68 = bound68; + notify(); + } + if (this->bound6C != bound6C) { + this->bound6C = bound6C; + notify(); + } + if (this->bound70 != bound70) { + this->bound70 = bound70; + notify(); + } + if (this->bound74 != bound74) { + this->bound74 = bound74; + notify(); + } +} // OFFSET: 0x00DD8380 diff --git a/Source/UI/Window/UIWindowMgr.h b/Source/UI/Window/UIWindowMgr.h index afc23fe..fc3901a 100644 --- a/Source/UI/Window/UIWindowMgr.h +++ b/Source/UI/Window/UIWindowMgr.h @@ -436,6 +436,7 @@ public: char UpdateSnapRectangles(); bool ProcessDialogKey(int unused, int key); void NotifyMode(); + void NotifyItemWindows(int accountId, int lower, int upper); int SendMsg(int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4, std::intptr_t argument5); bool IsOrderFixed(int id); void RemoveOrder(int id); @@ -448,6 +449,8 @@ public: extern UIWindowMgr g_windowMgr; extern int g_dragWindowId; +void __fastcall RefreshItemWindows(UIWindowMgr* mgr); + #if defined(_WIN32) && !defined(_WIN64) static_assert(sizeof(WindowTextEntry) == 0x1C); static_assert(sizeof(WindowTextRecord) == 0x20);