From cb2926158976e93093f6567d055bdbf464cf37fd Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 23:30:01 +0000 Subject: [PATCH] Decompile 3 functions in Source/UI/UIBartermarketWnd.cpp, Source/UI/UIBartermarketWnd.h, ... Batch #6485 by superintelligence: 0 byte-identical, 3 confirmed by peer review. - fn_10552 UIBarterItemPurchaseWnd::Slot15: logic confirmed by peer review - fn_10563 UIBarterItemPurchaseWnd::SendMsg: logic confirmed by peer review - fn_10544 UIBarterItemPurchaseWnd::Purchase: logic confirmed by peer review Peer-reviewed-by: eAthena, willerthal Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/UI/Item/UIItemBaseWnd.h | 2 +- Source/UI/UIBartermarketWnd.cpp | 402 ++++++++++++++++++++++++++++++++ Source/UI/UIBartermarketWnd.h | 15 +- 3 files changed, 417 insertions(+), 2 deletions(-) diff --git a/Source/UI/Item/UIItemBaseWnd.h b/Source/UI/Item/UIItemBaseWnd.h index aaf88835..adace755 100644 --- a/Source/UI/Item/UIItemBaseWnd.h +++ b/Source/UI/Item/UIItemBaseWnd.h @@ -27,7 +27,7 @@ public: /* 00B8 */ int unknown_00B8; /* 00BC */ UIWindow* resizer; /* 00C0 */ UIWindow* scrollBar; - /* 00C4 */ unsigned char unknown_00C4[0x8]; + /* 00C4 */ UIWindow* buttons[2]; protected: UIButtonContext* m_controls; diff --git a/Source/UI/UIBartermarketWnd.cpp b/Source/UI/UIBartermarketWnd.cpp index 89ef08e4..3c6e6007 100644 --- a/Source/UI/UIBartermarketWnd.cpp +++ b/Source/UI/UIBartermarketWnd.cpp @@ -10,12 +10,15 @@ #include "Contents/MessageTable.h" #include "UI/Layout/WindowSnapping.h" #include "UI/Shortcuts/ShortcutVisibility.h" +#include "UI/Window/UIResizer.h" #include "UI/Window/UIWindowMgr.h" #include "Utility/Text/FormatString.h" #include #include #include +#include +#include // OFFSET: 0x00840B30 // FUNCTION: fn_10545 @@ -909,3 +912,402 @@ void UIExpandedBarterPurchaseButton::Slot28(int x, int y) { } } } + +// GLOBAL: gl_25056 +int g_extraInventorySlots; +// GLOBAL: gl_25087 +int g_barterValueA; +// GLOBAL: gl_25088 +int g_barterValueB; + +// OFFSET: 0x00840530 +// FUNCTION: fn_10544 +bool UIBarterItemPurchaseWnd::Purchase() { + std::map totals; + std::list items = *g_barterMarketItemMgr->GetAllItems(); + + int count = reinterpret_cast(&g_session)->GetList0Size(); + count += g_session.CountItems17F0(); + count += g_session.CountItems2B50(); + + for (std::list::iterator it = items.begin(); it != items.end(); ++it) { + std::map::iterator total = totals.find(it->name); + if (total != totals.end()) { + total->second += it->value; + } else { + totals.insert(std::make_pair(it->name, it->value)); + } + + if (g_session.IsEquipItemType(it->field_1c) == true || g_session.IsShadowItemType(it->field_1c) == true) { + ++count; + } else if (this->GetInventoryItemCount(std::atoi(it->name.c_str())) == 0) { + ++count; + } + } + + if (count > g_extraInventorySlots + 100) { + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3568)), 255, 0, 0, 0); + this->SendMsg(nullptr, 6, 185, 0, 0, 0); + return false; + } + + std::map* required = g_barterMarketItemMgr->GetTotals(); + for (std::map::iterator it = required->begin(); it != required->end(); ++it) { + if (this->GetInventoryItemCount(it->first) < it->second) { + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3556)), 255, 0, 0, 0); + this->SendMsg(nullptr, 6, 185, 0, 0, 0); + return false; + } + } + + for (std::map::iterator it = totals.begin(); it != totals.end(); ++it) { + if (it->second + this->GetInventoryItemCount(std::atoi(it->first.c_str())) > 30000) { + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + const std::string text = FormatOwnedString(LookupMessage(3567), 30000); + g_windowMgr.SendNotice(1, reinterpret_cast(text.c_str()), 255, 0, 0, 0); + this->SendMsg(nullptr, 6, 185, 0, 0, 0); + return false; + } + } + + return true; +} + +// OFFSET: 0x00841A10 +// FUNCTION: fn_10552 +void UIBarterItemPurchaseWnd::Slot15(int width, int height) { + UIResizer* resizer = new UIResizer(*this->m_context); + this->resizer = resizer; + resizer->SetSize(16, 16); + resizer->SetDirection(3); + resizer->SetBitmapName("유저인터페이스\\btn_resize.bmp"); + resizer->Move(this->geometry.width - 15, this->geometry.height - 15); + resizer->SetColors(0xFFFF00FF, 0xFFFF00FF); + this->AddChild(resizer); + + UIScrollBar* scrollBar = new UIScrollBar(*this->m_context); + this->scrollBar = scrollBar; + scrollBar->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - 38); + this->AddChild(scrollBar); + + const std::string prefix = "유저인터페이스\\"; + const char* names[2][3] = { + {"btn_buy", "btn_buy_a", "btn_buy_b"}, + {"btn_cancel", "btn_cancel_a", "btn_cancel_b"}, + }; + const int ids[2] = {184, 185}; + const int xs[2] = {this->geometry.width - 106, this->geometry.width - 61}; + const int y = this->geometry.height - 24; + + for (int index = 0; index < 2; ++index) { + UIBitmapButton* button = index == 0 ? static_cast(new UIPurchaseButton()) : new UIBitmapButton(); + this->buttons[index] = button; + button->SetBitmap((prefix + names[index][0] + ".bmp").c_str(), 0, 0); + button->SetBitmap((prefix + names[index][1] + ".bmp").c_str(), 1, 0); + button->SetBitmap((prefix + names[index][2] + ".bmp").c_str(), 2, 0); + button->SetSize(button->BitmapWidth(), button->BitmapHeight()); + button->Move(xs[index], y); + button->SetId(ids[index]); + this->AddChild(button); + } + + this->columns = 1; + this->visibleRows = (height - 38) / 32; + + this->SendMsg(nullptr, 23, 0, 0, 0, 0); +} + +// OFFSET: 0x00843FA0 +// FUNCTION: fn_10563 +int UIBarterItemPurchaseWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + switch (message) { + case 6: { + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + if (!mode) { + return 0; + } + + if (a == 184) { + if (!this->Purchase()) { + return 0; + } + mode->SendMsg(308, 0, 0, 0, 0); + } else if (a != 185) { + return 0; + } + + mode->SendMsg(40, 0, 0, 0, 0); + g_barterMarketItemMgr->Clear(); + return 0; + } + + case 14: { + if (a != 3) { + return 0; + } + + int width = b <= 320 ? static_cast(b) : 320; + int height = c <= 336 ? static_cast(c) : 336; + if (width < 232) { + width = 232; + } + if (height < 120) { + height = 120; + } + width = (width - 280) / 32 * 32 + 280; + height = (height - 120) / 32 * 32 + 120; + + if (width != this->geometry.width || height != this->geometry.height) { + this->Resize(width, height); + this->columns = 1; + const int rowsHeight = this->geometry.height - 38; + this->visibleRows = rowsHeight / 32; + this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); + this->scrollBar->Move(this->geometry.width - 15, 14); + this->scrollBar->Resize(this->scrollBar->geometry.width, rowsHeight); + this->UpdateScrollBar(); + } + + const int xs[2] = {this->geometry.width - 106, this->geometry.width - 61}; + const int y = this->geometry.height - 24; + for (int index = 0; index < 2; ++index) { + this->buttons[index]->Move(xs[index], y); + } + + this->m_frameContext->snapping.Store(this); + return 0; + } + + case 23: { + this->items.clear(); + std::list* items = g_barterMarketItemMgr->GetAllItems(); + for (std::list::iterator it = items->begin(); it != items->end(); ++it) { + this->items.push_back(it->ToItemInfo()); + } + this->Invalidate(); + this->UpdateScrollBar(); + return 0; + } + + case 34: { + this->saved = reinterpret_cast(a); + if (!this->saved) { + return 0; + } + if (!this->saved->IsValid()) { + this->saved->Reset(); + } + this->SendMsg(nullptr, 14, 7, this->saved->width, this->saved->height, 0); + this->Move(this->saved->x, this->saved->y); + return 0; + } + + case 38: { + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + if (!mode) { + return 0; + } + + std::pair found = g_barterMarketItemMgr->FindItem(mode->drag.unknown_03B0); + if (found.first == false) { + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3554)), 255, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + found.second.value = mode->drag.quantity; + if (g_session.HasItemId(found.second.field_2c)) { + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3665)), 255, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + if (g_barterMarketItemMgr->HasItemByName(mode->drag.name)) { + int notice = 0; + if (g_session.IsEquipItemType(mode->drag.type)) { + mode->SendMsg(18, 0, 0, 0, 0); + notice = 119; + } else if (g_session.IsShadowItemType(mode->drag.type)) { + mode->SendMsg(18, 0, 0, 0, 0); + notice = 3569; + } + + if (notice != 0) { + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(notice)), 255, 0, 0, 0); + return 0; + } + } + + if (mode->drag.quantity + g_barterMarketItemMgr->GetAllItemValueByName(mode->drag.name) > 30000) { + char buffer[200] = {}; + StringFormat(buffer, 200, static_cast(-1), LookupMessage(1704), 30000); + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(buffer), 255, 0, 0, 0); + return 0; + } + + const int amountById = g_barterMarketItemMgr->GetAmountById(mode->drag.unknown_03B0); + if (amountById < 0) { + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3554)), 255, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + if (amountById > 0) { + const int available = g_barterValueA - g_barterValueB; + const float remaining = static_cast(available) - g_barterMarketItemMgr->GetTotalAmount(); + if (static_cast(remaining) / amountById < mode->drag.quantity) { + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(56)), 255, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + } + + g_barterMarketItemMgr->AddItem(found.second); + this->SendMsg(nullptr, 23, 0, 0, 0, 0); + if (UIWindow* window = g_windowMgr.LookupWindow(334)) { + window->SendMsg(nullptr, 23, 0, 0, 0, 0); + } + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + default: + break; + } + + return UIFrameWnd::SendMsg(sender, message, a, b, c, d); +} + +// OFFSET: 0x00846FB0 +// FUNCTION: fn_10583 +void UIExpandedBarterItemPurchaseWnd::Slot15(int width, int height) { + UIResizer* resizer = new UIResizer(*this->m_context); + this->resizer = resizer; + resizer->SetSize(16, 16); + resizer->SetDirection(3); + resizer->SetBitmapName("유저인터페이스\\btn_resize.bmp"); + resizer->Move(this->geometry.width - 15, this->geometry.height - 15); + resizer->SetColors(0xFFFF00FF, 0xFFFF00FF); + this->AddChild(resizer); + + UIScrollBar* scrollBar = new UIScrollBar(*this->m_context); + this->scrollBar = scrollBar; + scrollBar->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - 46); + this->AddChild(scrollBar); + + UIExpandedBarterPurchaseButton* buyButton = new UIExpandedBarterPurchaseButton(); + this->buyButton = buyButton; + buyButton->SetBitmap("유저인터페이스\\btn_buy.bmp", 0, 0); + buyButton->SetBitmap("유저인터페이스\\btn_buy_a.bmp", 1, 0); + buyButton->SetBitmap("유저인터페이스\\btn_buy_b.bmp", 2, 0); + buyButton->SetSize(buyButton->BitmapWidth(), buyButton->BitmapHeight()); + buyButton->Move(this->geometry.width - 105, this->geometry.height - 24); + buyButton->SetId(184); + this->AddChild(buyButton); + + UIBitmapButton* cancelButton = new UIBitmapButton(); + this->cancelButton = cancelButton; + cancelButton->SetBitmap("유저인터페이스\\btn_cancel.bmp", 0, 0); + cancelButton->SetBitmap("유저인터페이스\\btn_cancel_a.bmp", 1, 0); + cancelButton->SetBitmap("유저인터페이스\\btn_cancel_b.bmp", 2, 0); + cancelButton->SetSize(cancelButton->BitmapWidth(), cancelButton->BitmapHeight()); + cancelButton->Move(this->geometry.width - 60, this->geometry.height - 24); + cancelButton->SetId(185); + this->AddChild(cancelButton); + + this->rowCount = (height - 46) / 64; + + this->SendMsg(nullptr, 23, 0, 0, 0, 0); +} + +// OFFSET: 0x008446D0 +// FUNCTION: fn_10564 +int UIBartermarketWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { + switch (message) { + case 14: { + if (a == 7) { + int width = b <= 320 ? static_cast(b) : 320; + int height = c <= 336 ? static_cast(c) : 336; + if (width < 232) { + width = 232; + } + if (height < 120) { + height = 120; + } + width = (width - 280) / 32 * 32 + 280; + height = (height - 120) / 32 * 32 + 120; + + if (width != this->geometry.width || height != this->geometry.height) { + this->Resize(width, height); + this->columns = 1; + const int contentHeight = this->geometry.height - this->unknown_0108 - this->unknown_0104 - 17; + this->visibleRows = contentHeight / 32; + this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); + this->scrollBar->Move(this->geometry.width - 15, 14); + this->scrollBar->Resize(this->scrollBar->geometry.width, contentHeight); + this->UpdateScrollBar(); + } + + this->m_frameContext->snapping.Store(this); + } + return 0; + } + + case 23: { + this->items.clear(); + std::list* items = g_barterMarketItemMgr->GetItems(); + for (std::list::iterator it = items->begin(); it != items->end(); ++it) { + this->items.push_back(it->ToItemInfo()); + } + this->Invalidate(); + this->UpdateScrollBar(); + return 0; + } + + case 34: { + this->saved = reinterpret_cast(a); + if (a == 0) { + return 0; + } + if (!this->saved->IsValid()) { + this->saved->Reset(); + } + this->SendMsg(nullptr, 14, 7, this->saved->width, this->saved->height, 0); + this->Move(this->saved->x, this->saved->y); + return 0; + } + + case 38: { + CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); + if (!mode) { + return 0; + } + + std::pair found = g_barterMarketItemMgr->FindAllItem(mode->drag.unknown_03B0); + if (found.first == false) { + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3554)), 255, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + found.second.value = mode->drag.quantity; + g_barterMarketItemMgr->RemoveItem(found.second); + if (UIWindow* window = g_windowMgr.LookupWindow(335)) { + window->SendMsg(nullptr, 23, 0, 0, 0, 0); + } + this->SendMsg(nullptr, 23, 0, 0, 0, 0); + mode->SendMsg(18, 0, 0, 0, 0); + return 0; + } + + default: + break; + } + + return UIFrameWnd::SendMsg(sender, message, a, b, c, d); +} diff --git a/Source/UI/UIBartermarketWnd.h b/Source/UI/UIBartermarketWnd.h index 5d7f12c1..20422129 100644 --- a/Source/UI/UIBartermarketWnd.h +++ b/Source/UI/UIBartermarketWnd.h @@ -12,9 +12,13 @@ #include #include +class UIExpandedBarterPurchaseButton; +class UIResizer; + class UIExpandedBarterItemPurchaseWnd : public UIFrameWnd { public: void Slot10(int x, int y, std::intptr_t value) override; + void Slot15(int width, int height) override; void Slot25(int x, int y) override; void Slot28(int x, int y) override; void Slot32(int x, int y) override; @@ -26,12 +30,14 @@ public: /* 00B4 */ int unknown_00B4; /* 00B8 */ int itemCount; - /* 00BC */ int unknown_00BC; + /* 00BC */ UIResizer* resizer; /* 00C0 */ UIScrollBar* scrollBar; /* 00C4 */ int unknown_00C4; /* 00C8 */ int rowCount; /* 00CC */ int unknown_00CC; /* 00D0 */ unsigned char scrollEnabled; + /* 00D4 */ UIExpandedBarterPurchaseButton* buyButton; + /* 00D8 */ UIBitmapButton* cancelButton; }; class UIExpandedBartermarketWnd : public UIFrameWnd { @@ -60,9 +66,12 @@ public: class UIBarterItemPurchaseWnd : public UIItemPurchaseWnd { public: void Slot10(int x, int y, std::intptr_t value) override; + void Slot15(int width, int height) override; void Slot25(int x, int y) override; void Slot28(int x, int y) override; void Slot32(int x, int y) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; + bool Purchase(); __declspec(noinline) std::pair GetBarterItemOrPriceAt(int x, int y); __declspec(noinline) std::pair GetBarterItemAt(int x, int y); int GetInventoryItemCount(int itemId); @@ -74,8 +83,12 @@ public: void Slot25(int x, int y) override; void Slot28(int x, int y) override; void Slot32(int x, int y) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; __declspec(noinline) std::pair GetBarterItemAt(int x, int y); __declspec(noinline) std::pair GetBarterItemOrPriceAt(int x, int y); + + /* 0104 */ int unknown_0104; + /* 0108 */ int unknown_0108; }; class UIPurchaseButton : public UIBitmapButton {