From c51d216ac61a2049e3d935862cf719c625e8ac96 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Thu, 29 Oct 2026 00:02:35 +0000 Subject: [PATCH] Decompile fn_12230 (UIMenuWnd::Paint) Batch #1931 by ragnarok-clanker: 0 byte-identical, 1 confirmed by peer review. - fn_12230 UIMenuWnd::Paint: logic confirmed by peer review Reviewed-by: ragnarok-clanker --- Source/Client/Session.h | 4 +- Source/UI/Acceptance/UIChooseSellBuyWnd.cpp | 87 +++++++++++++++++++++ Source/UI/Dialogs/UIMenuWnd.h | 10 +++ Source/UI/Dialogs/UIProhibitListWnd.h | 7 ++ 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/Source/Client/Session.h b/Source/Client/Session.h index c44465e..c4962d5 100644 --- a/Source/Client/Session.h +++ b/Source/Client/Session.h @@ -149,7 +149,9 @@ public: /* 52B0 */ const char* const* m_weaponNamesEnd; /* 52B4 */ unsigned char unknown_52B4[0x04]; /* 52B8 */ std::vector m_accessoryNames; - /* 52C4 */ unsigned char unknown_52C4[0x294]; + /* 52C4 */ unsigned char unknown_52C4[0x278]; + /* 553C */ std::string m_serverName; + /* 5554 */ unsigned char unknown_5554[4]; /* 5558 */ int unknown_5558; /* 555C */ unsigned char unknown_555C[0xC]; /* 5568 */ int unknown_5568; diff --git a/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp b/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp index b8cb578..fe27235 100644 --- a/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp +++ b/Source/UI/Acceptance/UIChooseSellBuyWnd.cpp @@ -66,6 +66,12 @@ namespace { constexpr char prefix[] = "유저인터페이스\\"; } +// STRING: st_16833 +static const char menuSeparatorText[] = "-"; + +// GLOBAL: gl_24749 +const char* g_menuSeparator = menuSeparatorText; + // OFFSET: 0x008C73C0 // FUNCTION: fn_11930 UIChooseSellBuyWnd::UIChooseSellBuyWnd(UIWindowContext& windows, UIFrameContext& frames, UIAcceptanceContext& acceptance) @@ -213,6 +219,47 @@ void UIItemParamChangeDisplayWnd::Paint() { void UILoadingWnd::Paint() { } +// OFFSET: 0x008EED00 +// FUNCTION: fn_12230 +void UIMenuWnd::Paint() { + auto& controls = *this->m_controls; + unsigned red, green, blue; + SkinPaletteChannels(ResourceMgr::Instance(), 6, 6, red, green, blue); + this->ClearSurface(RGB(red, green, blue)); + unsigned fillRed, fillGreen, fillBlue; + SkinPaletteChannels(ResourceMgr::Instance(), 2, 2, fillRed, fillGreen, fillBlue); + this->FillRegion(1, 1, this->geometry.width - 2, this->geometry.height - 2, RGB(fillRed, fillGreen, fillBlue)); + + const auto* leftUp = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\sysboxs_lu.bmp"))); + this->DrawBitmap(0, 0, &leftUp->image, false); + const auto* leftDown = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\sysboxs_ld.bmp"))); + this->DrawBitmap(0, this->geometry.height - leftDown->image.height, &leftDown->image, false); + const auto* rightUp = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\sysboxs_ru.bmp"))); + this->DrawBitmap(this->geometry.width - rightUp->image.width, 0, &rightUp->image, false); + const auto* rightDown = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\sysboxs_rd.bmp"))); + this->DrawBitmap(this->geometry.width - rightDown->image.width, this->geometry.height - rightDown->image.height, &rightDown->image, false); + + SkinPaletteChannels(ResourceMgr::Instance(), 6, 2, red, green, blue); + const int count = static_cast(this->m_items.size()); + for (int index = 0; index < count; ++index) { + const std::string& item = this->m_items[index]; + const bool separator = item == g_menuSeparator; + const bool afterSeparator = index != 0 && this->m_items[index - 1] == item; + if (separator) { + unsigned lineRed, lineGreen, lineBlue; + SkinPaletteChannels(ResourceMgr::Instance(), 14, 6, lineRed, lineGreen, lineBlue); + this->FillRegion(0, this->m_itemHeight * index / 2 + 2, this->geometry.width, 1, RGB(lineRed, lineGreen, lineBlue)); + continue; + } + + const int row = afterSeparator ? index - 1 : index; + if (index == this->m_selected) { + this->FillRegion(3, this->m_itemHeight / 2 * row + 1, this->geometry.width - 6, this->m_itemHeight - 2, RGB(red, green, blue)); + } + this->DrawTextAt(controls.fonts, controls.locale, 3, this->m_itemHeight * row / 2 + 1, item.c_str(), 0, 0, 12, this->m_colors[index], 0, 0); + } +} + // OFFSET: 0x008EF0A0 // FUNCTION: fn_12231 void UIMinimapZoomWnd::Paint() { @@ -285,6 +332,46 @@ void UIPasswordWnd::Paint() { this->DrawBorder(0, 0, 0, 0); } +// OFFSET: 0x008EFCF0 +// FUNCTION: fn_12244 +void UIProhibitListWnd::Paint() { + auto& controls = *this->m_controls; + char text[256]; + + const int titleHeight = this->DrawTitleBar(controls.fonts, controls.locale, true, controls.services.MessageText(714), 0); + this->DrawPanelBackground(titleHeight, 0, ""); + const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\sysboxs_ld.bmp"))); + this->DrawBitmap(0, this->geometry.height - left->image.height, &left->image, false); + const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\sysboxs_rd.bmp"))); + this->DrawBitmap(this->geometry.width - right->image.width, this->geometry.height - right->image.height, &right->image, false); + + int y = 0; + const int count = static_cast(g_session.m_prohibitionLog.size()); + for (int index = 0; index < count; ++index) { + const ProhibitionLogEntry& entry = g_session.m_prohibitionLog[index]; + if (std::strcmp(entry.ownerName, g_session.m_serverName.c_str()) != 0 || entry.aid != this->m_aid) { + continue; + } + + if (y == 0) { + std::sprintf(text, "AID : %d CharacterName : %s", entry.aid, entry.name); + this->DrawTextAt(controls.fonts, controls.locale, 10, 25, text, 0, 0, 12, 0, 0, 0); + std::sprintf(text, "ServerName : %s", g_session.m_prohibitionLog[index].ownerName); + this->DrawTextAt(controls.fonts, controls.locale, 10, 41, text, 0, 0, 12, 0, 0, 0); + } + + const ProhibitionLogEntry& record = g_session.m_prohibitionLog[index]; + const int date = static_cast(record.date); + const int time = static_cast(record.time); + std::sprintf( + text, "ProhibitTime : %d분 LogTime : %d년 %d월 %d일 %d시 %d분 %d초", record.minutes, date >> 16 & 0xFFFF, date >> 8 & 0xFF, date & 0xFF, time >> 16 & 0xFF, + time >> 8 & 0xFF, time & 0xFF + ); + this->DrawTextAt(controls.fonts, controls.locale, 10, y + 65, text, 0, 0, 12, 0, 0, 0); + y += 18; + } +} + // OFFSET: 0x008EFF60 // FUNCTION: fn_12245 void UIQuitWnd::Paint() { diff --git a/Source/UI/Dialogs/UIMenuWnd.h b/Source/UI/Dialogs/UIMenuWnd.h index 11903ac..cc9eacb 100644 --- a/Source/UI/Dialogs/UIMenuWnd.h +++ b/Source/UI/Dialogs/UIMenuWnd.h @@ -3,20 +3,30 @@ #include "UI/Window/UIFrameWnd.h" +#include #include #include +struct UIButtonContext; class UIMenuWnd : public UIFrameWnd { public: /* 00B4 */ int m_menuId; /* 00B8 */ int m_selected; /* 00BC */ int m_itemHeight; /* 00C0 */ std::vector m_items; + /* 00CC */ std::uint32_t unknown_00CC; + /* 00D0 */ std::uint32_t* m_colors; + void Paint() override; void Slot27(int x, int y) override; void Slot28(int x, int y) override; int ItemAt(int x, int y); + +protected: + UIButtonContext* m_controls; }; +extern const char* g_menuSeparator; + #endif diff --git a/Source/UI/Dialogs/UIProhibitListWnd.h b/Source/UI/Dialogs/UIProhibitListWnd.h index f38d690..5fe04f7 100644 --- a/Source/UI/Dialogs/UIProhibitListWnd.h +++ b/Source/UI/Dialogs/UIProhibitListWnd.h @@ -3,11 +3,18 @@ #include "UI/Window/UIFrameWnd.h" +struct UIButtonContext; + class UIProhibitListWnd : public UIFrameWnd { public: /* 00B4 */ int m_count; + /* 00B8 */ std::uint32_t m_aid; + void Paint() override; void Slot19() override; + +protected: + UIButtonContext* m_controls; }; #endif