#include "UI/Window/WindowId.h" #include "Render/Text/FontCache.h" #include "UI/Window/UIEnums.h" #include "Render/Text/TextContext.h" #include "UI/UIChangeMaterialWnd.h" #include "Client/Mode/CMode.h" #include "Client/Input/InputCharset.h" #include "Client/Session.h" #include "Contents/Configuration/ServiceConfiguration.h" #include "Contents/Items/ChangeMaterialMgr.h" #include "Contents/Items/ItemDescription.h" #include "Contents/Items/ItemInfo.h" #include "Contents/Items/ItemNaming.h" #include "Contents/MessageTable.h" #include "Contents/PlayerNameDictionary.h" #include "Network/Connection/Connection.h" #include "Resource/Bitmap/BitmapResource.h" #include "Resource/ResourceMgr.h" #include "Resource/TextureNames.h" #include "UI/Buttons/UIBasicButton.h" #include "UI/Buttons/UIBitmapButton.h" #include "UI/Buttons/UIBmpTextButton.h" #include "UI/Buttons/UIButton.h" #include "UI/Edit/UIEditCtrl.h" #include "UI/Shop/ItemDrawing.h" #include "UI/Text/ColoredText.h" #include "UI/Window/UIWindowMgr.h" #include "UI/Window/UINewSelectCharWnd.h" #include "Utility/StackAlloc.h" #include "Utility/Text/FormatString.h" #include "Client/Mode/ModeMgr.h" #include "Resource/MSGSTRINGID.h" #include #include #include #include #include #include // INLINED inline const MaterialListEntry* UIChangeMaterialWnd_List::GetEntry(unsigned int index) const { if (index >= this->m_items.size()) { return nullptr; } const unsigned int entryIndex = static_cast(this->m_items[index]); if (entryIndex >= this->m_entries.size()) { return nullptr; } return &this->m_entries[entryIndex]; } // OFFSET: 0x005E03B0 // FUNCTION: fn_03861 UIChangeMaterialWnd::UIChangeMaterialWnd() : UIFrameWnd(0), itemList(nullptr), searchEdit(nullptr), m_sortBox(nullptr), m_button(nullptr), m_resultItem(), m_materials(), m_resultAmount(0), m_resultText() { this->m_resultX = 168; this->m_resultY = 131; const MaterialSlotPos positions[6] = {{90, 86}, {246, 86}, {168, 222}, {168, 40}, {90, 176}, {246, 176}}; for (int index = 0; index < 6; ++index) { this->m_materialPos[index] = positions[index]; } } // OFFSET: 0x005E0560 // FUNCTION: fn_03862 UIChangeMaterialWnd_List::UIChangeMaterialWnd_List() : UIFrameWnd(0), rowHeight(27), scrollBarWidth(16), m_selectedIndex(0), m_hoverIndex(0), m_scrollOffset(0), m_previousScrollOffset(0), m_scrollBar(nullptr), m_items(), m_entries() { } // OFFSET: 0x005E0650 // FUNCTION: fn_03863 UIChangeMaterialWnd_ScrollBar::UIChangeMaterialWnd_ScrollBar() : UIScrollBar() { this->thickness = 16; } // OFFSET: 0x005E1B30 // FUNCTION: fn_03877 void UIChangeMaterialWnd_List::OnCreate(int width, int height) { this->m_scrollBar = new UIChangeMaterialWnd_ScrollBar(); this->m_scrollBar->Configure(width - this->scrollBarWidth, 0, 1, height); this->m_scrollBar->Show(0); this->AddChild(this->m_scrollBar); this->m_pageSize = height / this->rowHeight; this->UpdateScrollBar(); } // OFFSET: 0x005E1080 // FUNCTION: fn_03871 void UIChangeMaterialWnd_List::SelectNextItem(int delta) { int64_t newIndex = this->m_selectedIndex + delta; const int count = static_cast(this->m_items.size()); const int maxIndex = count - 1; int targetIndex; if (newIndex < static_cast(maxIndex)) { targetIndex = static_cast(newIndex); } else { targetIndex = maxIndex; } if (!(targetIndex >= this->m_scrollOffset && this->m_scrollOffset + this->m_pageSize > targetIndex)) { int newOffset = this->m_previousScrollOffset; if (!(targetIndex >= newOffset && newOffset + this->m_pageSize > targetIndex)) { const int limit = count - this->m_pageSize; newOffset = static_cast(targetIndex - this->m_pageSize + 1) < static_cast(limit) ? targetIndex - this->m_pageSize + 1 : limit; } this->m_scrollOffset = newOffset; this->UpdateScrollBar(); this->m_previousScrollOffset = this->m_scrollOffset; } this->SetSelectedIndex(targetIndex); } // OFFSET: 0x005E1120 // FUNCTION: fn_03872 ITEM_INFO* UIChangeMaterialWnd::GetItemAt(int x, int y) { if (this->m_resultX <= x && x <= this->m_resultX + 24 && this->m_resultY <= y && y <= this->m_resultY + 24) { return &this->m_resultItem; } for (unsigned int i = 0; i < this->m_materials.size(); ++i) { if (this->m_materialPos[i].x <= x && x <= this->m_materialPos[i].x + 24 && this->m_materialPos[i].y <= y && y <= this->m_materialPos[i].y + 24) { return &this->m_materials[i]; } } return nullptr; } // OFFSET: 0x005E1300 // FUNCTION: fn_03874 bool UIChangeMaterialWnd::IsFrameWnd() { return true; } // OFFSET: 0x005E1310 // FUNCTION: fn_03875 void UIChangeMaterialWnd_List::Move(int x, int y) { UIWindow::Move(x, y); } // OFFSET: 0x005E2590 // FUNCTION: fn_03883 void UIChangeMaterialWnd_List::OnLBtnUp(int, int position) { const int rowHeight = this->rowHeight; const unsigned int last = static_cast(this->m_items.size() - 1); unsigned int index = static_cast(position / rowHeight + this->m_scrollOffset); index = std::min(index, last); this->SetSelectedIndex(static_cast(index)); } // OFFSET: 0x005E25D0 // FUNCTION: fn_03884 void UIChangeMaterialWnd::OnMouseHover(int x, int y) { ITEM_INFO* item = this->GetItemAt(x, y); if (!item) { return; } int screenX = x; int screenY = y; this->ToScreen(screenX, screenY); const int itemId = std::atoi(item->itemId.c_str()); const std::string name = ItemDisplayName(itemId); CMode* const mode = g_modeMgr.gameMode; mode->ShowTooltip(name.c_str(), screenX + 5, screenY - 5, -1, 0, 1); } // OFFSET: 0x005E2840 // FUNCTION: fn_03886 void UIChangeMaterialWnd_List::OnMouseMove(int x, int y) { } // OFFSET: 0x005E2850 // FUNCTION: fn_03887 void UIChangeMaterialWnd::OnProcess() { const std::string text = this->searchEdit->Text(); if (text.compare(LookupMessage(MSI_BO_RESEARCHREPORT_OFF)) != 0) { if (text.empty()) { this->searchEdit->SetText(LookupMessage(MSI_BO_RESEARCHREPORT_OFF)); this->searchEdit->TextColor(0xb1u, 0xb1u, 0xb1u, 0xffffffffu); } else { this->searchEdit->TextColor(0, 0, 0, 0xffffffffu); } } } // OFFSET: 0x005E29F0 // FUNCTION: fn_03888 void UIChangeMaterialWnd::OnRBtnUp(int x, int y) { ITEM_INFO* item = this->GetItemAt(x, y); if (!item) { return; } UIWindow* window = g_windowMgr.EnsureWindow(WID_ITEMCOLLECTIONWND); if (window) { window->SendMsg(nullptr, UM_ITEMEXPLANATION, reinterpret_cast(item), 0, 0, 0); } } // OFFSET: 0x005E2A30 // FUNCTION: fn_03889 void UIChangeMaterialWnd_List::OnWheel(int argument) { if (argument < 0) { this->SendMsg(this->m_scrollBar, UM_SCROLLVERTPAGEDOWN, 0, 0, 0, 0); } else { this->SendMsg(this->m_scrollBar, UM_SCROLLVERTPAGEUP, 0, 0, 0, 0); } } // OFFSET: 0x005E2A70 // FUNCTION: fn_03890 void UIChangeMaterialWnd_List::UpdateScrollBar() { const int count = static_cast(this->m_items.size()); if (count > this->m_pageSize) { this->m_scrollBar->Show(1); this->m_scrollBar->SetRange(count - this->m_pageSize, this->m_pageSize, count); this->m_scrollOffset = std::max(0, this->m_scrollOffset); this->m_scrollOffset = std::min(count - this->m_pageSize, this->m_scrollOffset); this->m_scrollBar->SetPosition(this->m_scrollOffset); } else { this->m_scrollOffset = 0; this->m_scrollBar->Show(0); } this->Invalidate(); if (this->parent) { this->parent->Invalidate(); } } // OFFSET: 0x005E2B20 // FUNCTION: fn_03891 void UIChangeMaterialWnd_List::ApplyFilter(std::string text) { const int rowHeight = this->rowHeight; this->m_pageSize = this->geometry.height / rowHeight; this->m_selectedIndex = 0; this->m_scrollOffset = 0; this->m_previousScrollOffset = 0; this->m_scrollBar->Show(0); this->m_items.clear(); std::string filter = text; std::transform(filter.begin(), filter.end(), filter.begin(), [](unsigned char c) { return static_cast(tolower(c)); }); int index = 0; for (auto entry = this->m_entries.begin(); entry != this->m_entries.end(); ++entry, ++index) { std::string name = ItemDisplayName(entry->results.front().id); std::transform(name.begin(), name.end(), name.begin(), [](unsigned char c) { return static_cast(tolower(c)); }); if (name.find(filter) != std::string::npos) { this->m_items.push_back(index); } } this->UpdateScrollBar(); this->SortItems(true); } // OFFSET: 0x005E30B0 // FUNCTION: fn_03892 void UIChangeMaterialWnd_List::RefreshVisibleEntries() { this->m_entries.clear(); std::map library = g_changeMaterialMgr->m_library; for (const auto& item : library) { std::vector recipes = item.second.m_recipes; for (const ChangeMaterialRecipe& recipe : recipes) { MaterialListEntry entry = {}; if (recipe.materials.empty() || recipe.products.empty()) { continue; } entry.materials.resize(recipe.materials.size()); auto material = entry.materials.begin(); for (auto source = recipe.materials.begin(); source != recipe.materials.end(); ++source, ++material) { material->id = source->itemId; material->quantity = source->count; } entry.results.resize(recipe.products.size()); auto result = entry.results.begin(); for (auto source = recipe.products.begin(); source != recipe.products.end(); ++source, ++result) { result->id = source->itemId; result->quantity = source->count; result->amount = source->rate; } bool available = true; for (auto required = entry.materials.begin(); required != entry.materials.end(); ++required) { const ITEM_INFO item = LookupClientItem(g_session.m_inventoryItems, required->id, 1); if (item.quantity < required->quantity) { available = false; } } entry.state = available; std::sort(entry.results.begin(), entry.results.end(), [](const MaterialResult& left, const MaterialResult& right) { return left.quantity < right.quantity; }); this->m_entries.push_back(entry); } } this->ApplyFilter(std::string()); this->SetSelectedIndex(0); } // OFFSET: 0x005E39A0 // FUNCTION: fn_03893 void UIChangeMaterialWnd::SendChangeMaterial() { const std::int16_t count = static_cast(this->m_materials.size()); const int length = count * 4 + 0xC; auto* packet = static_cast(STACK_ALLOC(static_cast(length))); if (!packet) { return; } *reinterpret_cast(packet) = 0x7E4; *reinterpret_cast(packet + 2) = static_cast(length); *reinterpret_cast(packet + 4) = 0; *reinterpret_cast(packet + 8) = 1; unsigned char* entry = packet + 0xC; for (auto it = this->m_materials.begin(); it != this->m_materials.end(); ++it) { *reinterpret_cast(entry + 2) = static_cast(it->quantity); *reinterpret_cast(entry) = static_cast(it->identity[1]); entry += 4; } GetRagConnection().Send(static_cast(*reinterpret_cast(packet + 2)), packet); UIBitmapButton* const button = this->m_button; button->SetDisabled(1); button->Invalidate(); _freea(packet); } // OFFSET: 0x005E3B80 // FUNCTION: fn_03894 void UIChangeMaterialWnd_List::SetSelectedIndex(int index) { this->m_selectedIndex = index; this->m_previousScrollOffset = this->m_scrollOffset; this->Invalidate(); this->parent->SendMsg(nullptr, UM_REFRESHITEM, reinterpret_cast(this->GetEntry(index)), 0, 0, 0); } // OFFSET: 0x005E3C30 // FUNCTION: fn_03895 int UIChangeMaterialWnd::SendMsg( UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4 ) { switch (message) { case UM_DEFPUSH: if (sender == reinterpret_cast(this->searchEdit) && reinterpret_cast(this->searchEdit) == g_windowMgr.GetHoverWindow()) { this->itemList->SendMsg(nullptr, UM_COMMAND, ID_SEARCH, reinterpret_cast(this->searchEdit->Text()), 0, 0); } break; case UM_COMMAND: switch (argument1) { case ID_OK: this->SendChangeMaterial(); break; case ID_CLOSE: g_windowMgr.CloseWindow(WID_CHANGEMATERIALWND); break; case ID_SEARCH: this->itemList->SendMsg(nullptr, UM_COMMAND, ID_SEARCH, reinterpret_cast(this->searchEdit->Text()), 0, 0); break; case 0x16c: this->itemList->SortItems(argument2 > 0); break; case 0x19f: this->itemList->SendMsg(nullptr, UM_REFRESHITEM, 0, 0, 0, 0); break; default: break; } break; case UM_UPPUSH: this->itemList->SendMsg(nullptr, UM_UPPUSH, 0, 0, 0, 0); break; case UM_DOWNPUSH: this->itemList->SendMsg(nullptr, UM_DOWNPUSH, 0, 0, 0, 0); break; case UM_REFRESHITEM: if (argument1 != 0) { auto* entry = reinterpret_cast(argument1); this->m_materials.clear(); this->m_resultItem.SetItemId(entry->results.front().id); this->m_resultItem.quantity = entry->results.front().quantity; for (auto it = entry->materials.begin(); it != entry->materials.end(); ++it) { ITEM_INFO info; info.SetItemId(it->id); info.quantity = it->quantity; const ITEM_INFO stock = LookupClientItem(g_session.m_inventoryItems, it->id, 1); info.identity[1] = stock.identity[1]; info.identified = it->quantity <= stock.quantity; this->m_materials.push_back(info); } if (entry->results.size() < 2) { this->m_resultAmount = entry->results.front().amount; this->m_resultText = ""; } else { int total = 0; for (const MaterialResult& result : entry->results) { total += result.amount; } this->m_resultAmount = total > 1000 ? total : 1000; const MaterialResult& first = entry->results.front(); const MaterialResult& last = entry->results.back(); const std::string name = ItemDisplayName(first.id); const std::string text = FormatOwnedString(LookupMessage(MSI_IQ_POWERFUL_FAITH_ON), name.c_str(), first.quantity, last.quantity); this->m_resultText = text; } this->m_button->SetDisabled(entry->state != 1); this->m_button->Invalidate(); this->Invalidate(); } break; default: break; } return UIFrameWnd::SendMsg(sender, message, argument1, argument2, argument3, argument4); } // OFFSET: 0x005E4170 // FUNCTION: fn_03896 int UIChangeMaterialWnd_List::SendMsg( UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4 ) { switch (message) { case UM_REFRESHITEM: this->RefreshVisibleEntries(); break; case UM_UPPUSH: this->ShiftSelectedIndex(1); break; case UM_DOWNPUSH: this->SelectNextItem(1); break; case UM_PAGEUPPUSH: this->ShiftSelectedIndex(this->m_pageSize); break; case UM_PAGEDOWNPUSH: this->SelectNextItem(this->m_pageSize); break; case UM_SCROLLVERT: case UM_SCROLLVERTPAGEUP: case UM_SCROLLVERTPAGEDOWN: { const int previous = this->m_scrollOffset; int delta = static_cast(argument1); if (message == UM_SCROLLVERTPAGEUP) { delta = -1; } else if (message == UM_SCROLLVERTPAGEDOWN) { delta = 1; } this->m_scrollOffset = previous + delta; if (previous != this->m_scrollOffset) { this->UpdateScrollBar(); } return this->m_scrollOffset - previous; } case UM_COMMAND: if (argument1 == 0x141 && argument2 != 0) { std::string filter(reinterpret_cast(argument2)); if (filter.compare(LookupMessage(MSI_BO_RESEARCHREPORT_OFF)) == 0) { filter = ""; } this->ApplyFilter(filter); } break; default: break; } return UIWindow::SendMsg(sender, message, argument1, argument2, argument3, argument4); } // OFFSET: 0x005E4330 // FUNCTION: fn_03897 void UIChangeMaterialWnd_List::SortItems(bool ascending) { std::sort(this->m_items.begin(), this->m_items.end(), MaterialNameLess(this->m_entries)); if (!ascending) { std::reverse(this->m_items.begin(), this->m_items.end()); } this->Invalidate(); } // OFFSET: 0x005E44C0 // FUNCTION: fn_03898 void UIChangeMaterialWnd_List::ShiftSelectedIndex(int value) { const int index = static_cast(std::max(0, this->m_selectedIndex - value)); if (index < this->m_scrollOffset || this->m_scrollOffset + this->m_pageSize <= index) { int newOffset = this->m_previousScrollOffset; if (index < newOffset || newOffset + this->m_pageSize <= index) { newOffset = index > 0 ? index : 0; } this->m_scrollOffset = newOffset; this->UpdateScrollBar(); } this->SetSelectedIndex(index); } // OFFSET: 0x005E1C00 // FUNCTION: fn_03878 void UIChangeMaterialWnd::Paint() { this->DrawBitmap(0, 0, static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\bg_ChangeMaterial.bmp"))), true); const std::string mixName = FormatOwnedString("유저인터페이스\\ChangeMaterial\\bg_mix_%d.bmp", static_cast(this->m_materials.size())); this->DrawBitmap(0x50, 0x1E, static_cast(ResourceMgr::Instance().Load(Resolve(mixName.c_str()))), true); int slot = 0; for (auto it = this->m_materials.begin(); it != this->m_materials.end(); ++it, ++slot) { if (it->identified == 1) { DrawItemWithQuantity(*this, ResourceMgr::Instance(), this->m_materialPos[slot].x, this->m_materialPos[slot].y, *it, 1, 0); } else { DrawItemWithQuantityAuxiliary(*this, 1, this->m_materialPos[slot].x, this->m_materialPos[slot].y, *it, 1, 0); } } DrawItemWithQuantity(*this, ResourceMgr::Instance(), this->m_resultX, this->m_resultY, this->m_resultItem, 1, 0); { const std::string amount = FormatOwnedString(LookupMessage(MSI_IQ_POWERFUL_FAITH_OFF), this->m_resultAmount / 10); const char* text = amount.c_str(); const int width = this->TextWidth(text, 0, 0x1D, 0x17, 1, 0); DrawOutlinedText(*this, 0x4F + (0xC8 - width) / 2, 0x64, text, 0, 0x5082DC, 0x643C00, 0x1D, 0x17, 1, 0); } if (!this->m_resultText.empty()) { this->DrawTextAt(0x50, 0x103, this->m_resultText.c_str(), 0, 0, 0xC, 0x1E00E6, 0, 0); } } // OFFSET: 0x005E1F20 // FUNCTION: fn_03880 void UIChangeMaterialWnd_List::Paint() { this->ClearSurface(0xFFFF00FF); for (int row = 0; row < this->m_pageSize; ++row) { const int index = row + this->m_scrollOffset; const MaterialListEntry* entry = this->GetEntry(index); if (entry) { const char* bitmap; if (index == this->m_selectedIndex) { bitmap = "유저인터페이스\\ChangeMaterial\\btn_material_press.bmp"; } else if (index == this->m_hoverIndex) { bitmap = "유저인터페이스\\ChangeMaterial\\btn_material_over.bmp"; } else { bitmap = "유저인터페이스\\ChangeMaterial\\btn_material_out.bmp"; } CRes* background = ResourceMgr::Instance().Load(Resolve(bitmap)); this->DrawBitmap(0, this->rowHeight * row, static_cast(background), true); ITEM_INFO item; item.SetItemId(entry->results[0].id); item.quantity = entry->results[0].quantity; item.identified = 1; std::string name = item.DisplayName(0); if (this->TextWidth(name.c_str(), 0, 0, 12, 0, 0) > 100) { name = this->FitDisplayText(100, name.c_str(), 0, 12, 0); } if (entry->state == 1) { DrawItemWithQuantity(*this, ResourceMgr::Instance(), 0, this->rowHeight * row, item, 1, 0); this->DrawTextAt(30, this->rowHeight * row + 6, name.c_str(), 0, 0, 12, 0, 0, 0); this->DrawRightAlignedText(163, this->rowHeight * row + 6, FormatOwnedString(LookupMessage(MSI_EA), item.quantity).c_str(), 0, 0, 12, 0, 0); } else { DrawItemWithQuantityAuxiliary(*this, 1, 0, this->rowHeight * row, item, 1, 0); this->DrawTextAt(30, this->rowHeight * row + 6, name.c_str(), 0, 0, 12, 0xAAAAAA, 0, 0); this->DrawRightAlignedText(163, this->rowHeight * row + 6, FormatOwnedString(LookupMessage(MSI_EA), item.quantity).c_str(), 0, 0, 12, 0xAAAAAA, 0); } } else { CRes* disabled = ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\btn_material_disable.bmp")); this->DrawBitmap(0, this->rowHeight * row, static_cast(disabled), true); } } } // OFFSET: 0x005E2370 // FUNCTION: fn_03881 void UIChangeMaterialWnd_ScrollBar::Paint() { this->ClearSurface(0xFFFF00FF); if (this->maximum == 0) { return; } switch (this->vertical) { case 1: { CBitmapRes* up = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\scroll_arrow_up_br.bmp"))); CBitmapRes* down = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\scroll_arrow_down_br.bmp"))); CBitmapRes* track = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\scroll_bg_br.bmp"))); this->DrawBitmap(0, 0, up, true); for (std::int64_t index = 0; index < (this->geometry.height - up->image.height - down->image.height) / track->image.height; ++index) { const int y = track->image.height * static_cast(index) + up->image.height; this->DrawBitmap(0, y, track, true); } this->DrawBitmap(0, this->geometry.height - track->image.height - down->image.height, track, true); this->DrawBitmap(0, this->geometry.height - down->image.height, down, true); CBitmapRes* thumb = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\ChangeMaterial\\scroll_btn_br.bmp"))); const int available = this->geometry.height - thumb->image.height - down->image.height - up->image.height; const int maxVal = std::max(0, this->total - this->visible); const int y = static_cast( static_cast(available) / static_cast(maxVal) * static_cast(this->position) + static_cast(up->image.height) ); this->DrawBitmap(0, y, thumb, true); break; } } this->minimumThumb = 0; this->parent->Invalidate(); } // OFFSET: 0x005E26B0 // FUNCTION: fn_03885 void UIChangeMaterialWnd_List::OnMouseHover(int x, int y) { const int rowHeight = this->rowHeight; const int index = y / rowHeight + this->m_scrollOffset; if (static_cast(index) >= this->m_items.size()) { return; } this->m_hoverIndex = index; this->Invalidate(); const MaterialListEntry* entry = this->GetEntry(index); if (!entry) { return; } int screenX = x; int screenY = y; this->ToScreen(screenX, screenY); const std::string text = FormatOwnedString(LookupMessage(MSI_EA2), ItemDisplayName(entry->results.front().id).c_str(), entry->results.front().quantity); CMode* const mode = g_modeMgr.gameMode; mode->ShowTooltip(text.c_str(), screenX + 5, screenY - 5, -1, 0, 1); } // INLINED static __forceinline void SetButtonText(UIBmpTextButton* button, std::string value) { button->text = value; button->Invalidate(); } // INLINED __forceinline void UIChangeMaterialWnd_CheckBox::SetLabels(std::string ascending, std::string descending) { this->ascendingText = ascending; this->descendingText = descending; this->Invalidate(); } // OFFSET: 0x005E1320 // FUNCTION: fn_03876 void UIChangeMaterialWnd::OnCreate(int width, int height) { UIBitmapButton* close = new UIBitmapButton(); close->SetBitmap("유저인터페이스\\basic_interface\\sys_close_off.bmp", 0, 0); close->SetBitmap("유저인터페이스\\basic_interface\\sys_close_on.bmp", 1, 0); close->SetBitmap("유저인터페이스\\basic_interface\\sys_close_on.bmp", 2, 0); close->SetSize(close->BitmapWidth(), close->BitmapHeight()); close->Move(480, 16); close->SetId(201); this->AddChild(close); this->searchEdit = new UIEditCtrl(); this->searchEdit->SetSize(118, 13); this->searchEdit->Move(313, 262); this->searchEdit->maximum = 20; this->searchEdit->preserveInput = 1; this->searchEdit->SetText(LookupMessage(MSI_BO_RESEARCHREPORT_OFF)); this->searchEdit->TextColor(0xB1u, 0xB1u, 0xB1u, 0xFFFFFFFFu); this->searchEdit->Background(255, 236, 207); this->searchEdit->topPadding = -1; this->AddChild(this->searchEdit); UIBmpTextButton* search = new UIBmpTextButton(); search->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_search.bmp", 0, 0); search->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_search_over.bmp", 1, 0); search->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_search_press.bmp", 2, 0); search->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_search_disable.bmp", 3, 0); search->SetSize(search->BitmapWidth(), search->BitmapHeight()); SetButtonText(search, LookupMessage(MSI_BO_BIONIC_PHARMACY_OK)); search->Move(432, 259); search->SetId(321); this->AddChild(search); UIBitmapButton* refresh = new UIBitmapButton(); refresh->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_refresh.bmp", 0, 0); refresh->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_refresh_over.bmp", 1, 0); refresh->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_refresh_press.bmp", 2, 0); refresh->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_refresh_disable.bmp", 3, 0); refresh->SetSize(refresh->BitmapWidth(), refresh->BitmapHeight()); refresh->Move(476, 259); refresh->SetId(415); this->AddChild(refresh); this->m_sortBox = new UIChangeMaterialWnd_CheckBox(); this->m_sortBox->SetSize(74, 14); this->m_sortBox->SetBitmaps("유저인터페이스\\ChangeMaterial\\btn_sort_up.bmp", "유저인터페이스\\ChangeMaterial\\btn_sort_down.bmp"); this->m_sortBox->SetLabels(LookupMessage(MSI_MSG_IS_ILLEGAL_TAG_MSG), LookupMessage(MSI_BO_RESEARCHREPORT_ON)); this->m_sortBox->Move(316, 24); this->m_sortBox->SetId(364); this->m_sortBox->SetChecked(1); this->AddChild(this->m_sortBox); this->m_button = new UIBitmapButton(); this->m_button->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_change_start.bmp", 0, 0); this->m_button->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_change_over.bmp", 1, 0); this->m_button->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_change_press.bmp", 2, 0); this->m_button->SetBitmap("유저인터페이스\\ChangeMaterial\\btn_change_disable.bmp", 3, 0); this->m_button->SetSize(this->m_button->BitmapWidth(), this->m_button->BitmapHeight()); this->m_button->Move(140, 171); this->m_button->SetId(184); this->AddChild(this->m_button); UIBasicButton* cancel = new UIBasicButton(); cancel->Configure(42, LookupMessage(MSI_ZENY_LOTTO_BUY_10)); const int cancelY = height - cancel->geometry.height - 12; cancel->Move(width - cancel->geometry.width - 55, cancelY); cancel->SetId(201); this->AddChild(cancel); this->itemList = new UIChangeMaterialWnd_List(); this->itemList->SetSize(186, 216); this->itemList->Move(310, 41); this->AddChild(this->itemList); this->itemList->SendMsg(nullptr, UM_REFRESHITEM, 0, 0, 0, 0); } // OFFSET: 0x005E1E20 // FUNCTION: fn_03879 void UIChangeMaterialWnd_CheckBox::Paint() { if (this->m_checked.empty() || this->m_unchecked.empty()) { return; } if (this->m_disabled == 1) { this->ClearSurface(0xFFFF00FFu); return; } if (this->m_hidden == 1) { return; } if (this->geometry.state == 0) { this->DrawBitmap(0, 0, static_cast(ResourceMgr::Instance().Load(Resolve(this->m_unchecked.c_str()))), false); if (!this->ascendingText.empty()) { this->DrawTextAt(0xc, 1, this->ascendingText.c_str(), 0, 0, 0xc, 0, 0, 0); } } else if (this->geometry.state == 1) { this->DrawBitmap(0, 0, static_cast(ResourceMgr::Instance().Load(Resolve(this->m_checked.c_str()))), false); if (!this->descendingText.empty()) { this->DrawTextAt(0xc, 1, this->descendingText.c_str(), 0, 0, 0xc, 0, 0, 0); } } } // OFFSET: 0x005E0A20 // FUNCTION: fn_03866 bool MaterialNameLess::operator()(unsigned int first, unsigned int second) const { const std::string left = first < this->entries.size() ? ItemDisplayName(this->entries[first].results[0].id) : std::string(); const std::string right = second < this->entries.size() ? ItemDisplayName(this->entries[second].results[0].id) : std::string(); return left < right; }