#include "Client/Input/InputCharset.h" #include "Client/Input/Language.h" #include "Client/Replay.h" #include "Client/ReplayPacketRecorder.h" #include "File/File.h" #include "Network/TextEncoding.h" #include "Render/DeviceContext/DeviceContext.h" #include "Render/Text/TextContext.h" #include "Resource/SkinPalette.h" #include "Resource/TextureNames.h" #include "Resource/Bitmap/BitmapImage.h" #include "Resource/Bitmap/BitmapResource.h" #include "Contents/Items/ItemDescription.h" #include "Contents/MessageTable.h" #include "UI/Shop/ItemDrawing.h" #include "Utility/Text/FormatString.h" #include "UI/Edit/EditTextState.h" #include "UI/Edit/EditViewport.h" #include "UI/Window/InputFocus.h" #include "UI/Buttons/UIButton.h" #include "UI/Edit/UIEditCtrl.h" #include "UI/Edit/UIEditCtrl_Currency.h" #include "UI/Window/WindowManagerWindows.h" #include "UI/Window/UIWindow.h" #include "UI/Window/UIWindowMgr.h" #include "Render/Renderer.h" #include "Render/ScreenRectangle.h" #include "Render/TextureQuad.h" #include "Render/Textures/Texture.h" #include "Render/Textures/TextureCache.h" #include "Render/Textures/SpritePixels.h" #include "Resource/ResourceMgr.h" #include "Resource/Sprites/ActionResource.h" #include "Resource/Sprites/SpriteResource.h" #include "UI/Buttons/UIBmpTextButton2.h" #include "UI/Buttons/UINaviLinkButton.h" #include "UI/Buttons/UIItemTagButton.h" #include "UI/Buttons/UISpriteButton.h" #include "UI/Buttons/UITextureButton.h" #include "UI/Item/UIItemPurchaseWnd.h" #include "UI/Item/UIParaItemShopWnd.h" #include "UI/Item/UIItemSellWnd.h" #include "UI/Item/UIItemSellWnd2.h" #include "UI/Item/UIItemShopWnd.h" #include "UI/Item/UIItemShopWnd2.h" #include "UI/Item/UIItemStoreFindWnd.h" #include "UI/Item/UIItemStoreSubWnd.h" #include "UI/Item/UIItemStoreWnd.h" #include "UI/Item/UIItemWnd.h" #include "UI/Shop/UIMerchantItemMyShopWnd.h" #include "UI/Shop/UIMerchantItemPurchaseWnd.h" #include "UI/Shop/UIMerchantItemShopWnd.h" #include "UI/Shop/UIMerchantItemWnd.h" #include "UI/Shop/UIMerchantMirrorItemWnd.h" #include "UI/Shop/UIMerchantShopMakeWnd.h" #include "UI/Shop/UINoticeMessageBox_LockSellItem.h" #include "UI/Skill/UISkillListWnd.h" #include "UI/Buttons/UIBasicButton.h" #include "UI/Buttons/UIBitmapButton.h" #include "UI/Window/UIResizer.h" #include "UI/Buttons/UICheckBox.h" #include "UI/Dialogs/UIPasswordWnd.h" #include "Client/Session.h" #include "Client/Mode/CGameMode.h" #include "Client/Mode/CMode.h" #include "Client/Mode/ModeMgr.h" #include "Client/Mode/ModeDragState.h" #include "UI/Shortcuts/ShortcutVisibility.h" #include "UI/Shop/UIMerchantItemPurchaseMSGWnd.h" #include "UI/Lists/UITabControl.h" #include "UI/UIGradeEnchantWnd.h" #include "UI/UIRefiningWnd.h" #include "Network/Connection/Connection.h" #include "Network/Packets/PacketId.h" #include "Network/Packets/PacketLengths.h" #include "UI/Text/UIStaticText.h" #include "UI/Lists/UIScrollBar.h" #include "UI/Layout/WindowSnapping.h" #include "UI/PriceCommission.h" #include "UI/Shop/PriceColor.h" #include "UI/Window/WindowDialogs.h" #include "Utility/Text/GroupedInteger.h" #include "Client/Mode/ModeTooltip.h" #include "Contents/Configuration/ServiceConfiguration.h" #include "Contents/Configuration/ServiceOptions.h" #include "Contents/Items/ItemNaming.h" #include "Contents/PlayerNameDictionary.h" #include "Contents/UserData/CharacterConfigSave.h" #include "UI/Edit/UIItemTagCtrl.h" #include "UI/Window/WindowBorder.h" #include "UI/Window/WindowRegistration.h" #include "UI/Window/UINewSelectCharWnd.h" #include "Contents/TipBoxTitles.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "Contents/Items/ItemLink.h" #include "UI/Chat/ChatSuggestions.h" #include "UI/Dialogs/UINpcEditDialogWnd.h" #include "UI/Rodex/UIRodexComposeWnd.h" // GLOBAL: gl_24862 bool g_vendingSaleAlarm; // GLOBAL: gl_24635 bool g_inputSuggestionsEnabled; // GLOBAL: gl_24653 int g_skillTooltipActive; // GLOBAL: gl_24654 DWORD g_skillTooltipTick; // GLOBAL: gl_24651 static const std::string g_itemLinkOpen = ""; // GLOBAL: gl_24652 static const std::string g_itemLinkClose = ""; // GLOBAL: gl_24647 static const std::string g_editNaviTagBegin = ""; // GLOBAL: gl_24648 static const std::string g_editNaviTagEnd = ""; struct ClientItemLists { void SetItems1750(int count, const short* ids); bool AddItem1750(const ITEM_INFO& item, int type, unsigned char refresh); bool RemoveItem1768(const ITEM_INFO& item, unsigned char alternate); void RemoveItem1760(const ITEM_INFO& item); void AddItem1730(const ITEM_INFO& item); void ReduceItem1718(const ITEM_INFO& item); void ClearItems1760(); void MergeItem1718(const ITEM_INFO& item); void RemoveItem1730(const ITEM_INFO& item); void RemoveItem1720ByName(const ITEM_INFO& item); void CopyItems1740To1750(); void ClearItems1760And1748(); }; struct SessionItemLists { void ClearTradeItems(); }; struct SessionMessengerContext { int GetList1Size() const; int GetList0Size() const; int GetList10Size() const; int GetList4Size() const; int GetList6Size() const; int GetList7Size() const; int GetList8Size() const; }; namespace { #pragma pack(push, 1) struct PACKET_CZ_INVENTORY_TAB { /* 0000 */ short packetType; /* 0002 */ unsigned short index; /* 0004 */ unsigned char favorite; }; #pragma pack(pop) static_assert(sizeof(PACKET_CZ_INVENTORY_TAB) == 5); #pragma pack(push, 1) struct ItemListChunkHeader { /* 0000 */ std::int16_t type; /* 0002 */ std::uint32_t size; }; #pragma pack(pop) static_assert(sizeof(ItemListChunkHeader) == 6); class EditLinkLayout { public: virtual void Update() = 0; protected: ~EditLinkLayout() = default; }; struct EditPainting { std::string& text; const int& anchor; const int& cursor; const int& mask; const int& firstVisible; const int& y; const int& invalidatesParent; const std::uint32_t& color; const std::uint32_t& secondColor; const bool& focused; const bool& chatInputFocused; const bool& caretEnabled; const std::uint32_t& tick; const int& candidateCursor; const int& width; const int& height; const int& screenWidth; const int& screenHeight; CLanguage& input; const InputCharset& charset; EditViewport& viewport; CDC& surface; FontCache& fonts; const TextLocale& locale; const BitmapImage& colorChip; UIWindow* const& parent; UIWindow* const& candidateWindow; UIWindow* const& readingWindow; const int& absoluteX; const int& absoluteY; const std::list& linkWindows; EditLinkLayout& links; bool alternate = false; const std::string* placeholder = nullptr; std::uint32_t placeholderColor = 0; bool placeholderEnabled = false; void Draw(); }; // INLINED void EditPainting::Draw() { TextContext context(this->surface); context.SetFont(0, 12, 0, 0); const auto measure = [&](const char* text, int bytes) { return context.Measure(text, bytes ? bytes : static_cast(std::strlen(text))).cx; }; int x = 3; if (this->invalidatesParent == 0 && this->firstVisible != 0) { x = (3 - measure(this->text.c_str(), this->firstVisible)); } const auto draw = [&](const std::string& value) { const bool placeholder = this->alternate && !this->focused && this->placeholderEnabled && this->secondColor == 0xFFFFFFFFu; context.SetColor(placeholder ? this->placeholderColor : this->color); const std::string& displayed = placeholder && value.empty() ? *this->placeholder : value; context.Draw(x, this->y, displayed.c_str(), static_cast(displayed.size())); if (this->secondColor != 0xFFFFFFFFu) { context.SetColor(this->secondColor); context.Draw((x - 1), this->y, value.c_str(), static_cast(value.size())); } }; const auto highlight = [&](int left, int extent) { const int start = std::max(left, 3); const int adjusted = left < 3 ? (extent + (left - 3)) : extent; if (start < this->width && adjusted > 0) { std::uint32_t pixel = 0x00FF0000u; if (this->colorChip.width > 6 && this->colorChip.height > 2) { pixel = this->colorChip.pixels[2 * this->colorChip.width + 6]; } const std::uint32_t color = ((pixel >> 16) & 255) | (pixel & 0xFF00) | ((pixel & 255) << 16); RECT rectangle{start, 0, std::min((start + adjusted), this->width), this->height}; this->surface.Fill(&rectangle, color); } }; const auto moveCandidate = [&](UIWindow* window, int offset) { if (!window) { return; } int left = (offset + this->absoluteX); int top = ((this->height + 6) + this->absoluteY); if ((window->geometry.width + left) > this->screenWidth) { left = (this->screenWidth - window->geometry.width); } if ((window->geometry.height + top) > this->screenHeight) { top = (((top - 12) - this->height) - window->geometry.height); } window->Move(left, top); }; std::string display; if (this->focused) { this->viewport.Synchronize(); unsigned begin = static_cast(std::min(this->anchor, this->cursor)); unsigned end = static_cast(std::max(this->anchor, this->cursor)); if (this->mask != 0) { display.assign(this->text.size(), static_cast(this->mask)); } else { const char* prefix = this->alternate ? this->input.candidate.c_str() : g_serverLanguage->Prefix(false); display = prefix; display += this->text; const auto prefixBytes = static_cast(std::strlen(prefix)); begin += prefixBytes; end += prefixBytes + static_cast(this->candidateCursor); } const int left = begin == 0 ? 0 : measure(display.c_str(), static_cast(begin)); const int right = end == 0 ? 0 : measure(display.c_str(), static_cast(end)); if (this->input.cursor != this->input.anchor) { highlight((x + left), (right - left)); draw(display); } else if (this->candidateCursor != 0) { moveCandidate(this->candidateWindow, left); moveCandidate(this->readingWindow, right); if (((this->tick / 500u) & 1u) == 0) { highlight((x + left), std::max((right - left), 2)); } draw(display); } else { draw(display); if (((this->tick / 500u) & 1u) == 0 && (this->alternate ? this->caretEnabled : (!this->chatInputFocused || this->caretEnabled))) { context.SetColor(this->color); context.Draw(((x + left) - 2), this->y, "|", 1); } } } else { if (this->mask != 0) { display.assign(this->text.size(), static_cast(this->mask)); } else { display = this->text; } draw(display); if (this->invalidatesParent != 0 && this->parent) { this->parent->Invalidate(); } } if (std::any_of(this->linkWindows.begin(), this->linkWindows.end(), [](const UIWindow* window) { return window->geometry.id == 438; })) { this->links.Update(); } } class LinkLayout : public EditLinkLayout { public: // INLINED explicit LinkLayout(UIEditCtrl& control) : m_control(control) { } // INLINED void Update() override { this->m_control.UpdateLinks(); } private: UIEditCtrl& m_control; }; } // OFFSET: 0x0084F860 // FUNCTION: fn_10662 UIEditCtrl::UIEditCtrl(const UIEditCtrl& other) : UIWindow(*other.m_context, 0), anchor(0), cursor(0), mask(0), maximum(0), flat(0), red(0), green(0), blue(0), borderRed(0), borderGreen(0), borderBlue(0), textColor(0), secondColor(0), firstVisible(0), textY(0), invalidatesParent(0), disabled(0), unknown_00F0(0), topPadding(0), preserveInput(0) { this->tooltip = other.tooltip; this->disabled = other.disabled; this->Invalidate(); this->preserveInput = other.preserveInput; this->maximum = other.maximum; if (this->maximum > 0x169) { this->maximum = 0x169; } this->text.reserve(this->maximum); this->text = other.text; this->anchor = other.anchor; this->cursor = other.cursor; this->mask = static_cast(other.mask); this->flat = other.flat != 0; this->red = other.red; this->green = other.green; this->blue = other.blue; this->Invalidate(); this->borderRed = other.borderRed; this->borderGreen = other.borderGreen; this->borderBlue = other.borderBlue; this->textColor = other.textColor; this->secondColor = other.secondColor; this->firstVisible = other.firstVisible; this->textY = other.textY; this->invalidatesParent = other.invalidatesParent; this->unknown_00F0 = other.unknown_00F0; this->topPadding = other.topPadding; } // OFFSET: 0x0084FAE0 // FUNCTION: fn_10663 UIEditCtrl::UIEditCtrl(UIWindowContext& windows, UIEditContext& edit) : UIWindow(windows, 0), anchor(0), cursor(0), mask(0), maximum(255), flat(1), red(255), green(255), blue(255), borderRed(0), borderGreen(0), borderBlue(0), textColor(0), secondColor(0xFFFFFFFF), firstVisible(0), textY(0), invalidatesParent(0), disabled(0), unknown_00F0(0), topPadding(0), preserveInput(0), m_edit(&edit) { this->text.reserve(255); } // OFFSET: 0x008517E0 // OFFSET: 0x00852980 // FUNCTION: fn_10694 UIEditCtrl::~UIEditCtrl() = default; // OFFSET: 0x005C3210 // FUNCTION: fn_03552 bool UIEditCtrl::Slot05() { return this->disabled == 0; } // OFFSET: 0x0085CCA0 // FUNCTION: fn_10807 void UIEditCtrl::Paint() { const auto component = [&](int value) { return static_cast(this->disabled != 0 && value > 30 ? value - 30 : value); }; const unsigned color = component(this->red) | (component(this->green) << 8) | (component(this->blue) << 16); this->textY = 0; if (this->geometry.surface) { if (this->flat == 0) { RECT rectangle{0, 0, this->geometry.width, this->geometry.height}; const unsigned border = static_cast(this->borderRed) | (static_cast(this->borderGreen) << 8) | (static_cast(this->borderBlue) << 16); this->geometry.surface->Fill(&rectangle, border); rectangle = {1, 1, this->geometry.width - 1, this->geometry.height - 1}; this->geometry.surface->Fill(&rectangle, color); } else { this->geometry.surface->Fill(nullptr, color); } } this->textY = this->topPadding + 2; this->PaintText(); } // OFFSET: 0x0085AAB0 // FUNCTION: fn_10783 void UIEditCtrl::Slot23() { this->m_edit->input.ResetInput(); this->m_edit->input.ResetInput(); this->m_edit->input.Insert(this->text.c_str()); this->m_edit->password = this->mask != 0; this->SelectAll(); } // OFFSET: 0x0085E3B0 // FUNCTION: fn_10826 void UIEditCtrl::Slot24(int) { this->Synchronize(); this->Invalidate(); } // OFFSET: 0x0085E400 // FUNCTION: fn_10828 void UIWhisperEditCtrl::Slot24(int retained) { this->sub_86A060(); this->Synchronize(); this->Invalidate(); } // OFFSET: 0x0085EC20 // FUNCTION: fn_10842 void UIEditCtrl::Slot25(int, int) { if (this->disabled == 0) { this->m_edit->focus.Set(this); } } // OFFSET: 0x0085F390 // FUNCTION: fn_10860 void UIEditCtrl::Slot28(int x, int y) { if (this->disabled != 0) { return; } this->Slot27(x, y); if (!this->tooltip.empty()) { int left = 10, top = -20; for (const UIWindow* window = this; window; window = window->parent) { left += window->geometry.x; top += window->geometry.y; } this->m_edit->buttons.services.Tooltip(this->tooltip.c_str(), left, top, -1, false, true); } } // OFFSET: 0x008641C0 // FUNCTION: fn_10914 int UIEditCtrl::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == 153) { this->InsertLink(reinterpret_cast(a)); } else if (message == 98 && c > 0) { UIWindow* window = this->m_edit->windows.EnsureWindow(12); if (window) { window->SendMsg(nullptr, 24, c, 0, 0, 0); } } UIWindow::SendMsg(sender, message, a, b, c, d); if (message == 0 && this->preserveInput == 0) { this->m_edit->input.ResetInput(); } return 0; } // OFFSET: 0x005C44E0 // FUNCTION: fn_03561 int UIEditCtrl::Slot46() { return 2; } // OFFSET: 0x008680D0 // FUNCTION: fn_10952 void UIEditCtrl::SetText(const char* value) { this->text.assign(value, std::strlen(value)); this->Trim(); if (this->m_edit->focus.window == this) { this->m_edit->input.ResetInput(); this->m_edit->input.ResetInput(); this->m_edit->input.Insert(this->text.c_str()); } this->SelectAll(); if (this->parent) { this->parent->Invalidate(); } } // OFFSET: 0x0085A590 void UIEditCtrl::SelectAll() { const bool focused = this->m_edit->focus.window == this; EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; state.SelectAll(); } // OFFSET: 0x00856980 // FUNCTION: fn_10755 void UIEditCtrl::PaintText() { this->PaintTextWithPolicy(false, nullptr, 0, false); } // INLINED void UIEditCtrl::PaintTextWithPolicy(bool alternate, const std::string* placeholder, std::uint32_t placeholderColor, bool placeholderEnabled) { const bool focused = this->m_edit->focus.window == this; EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; EditViewport viewport{ this->text, this->anchor, this->cursor, this->firstVisible, this->geometry.width, g_textCodePage, this->m_edit->input, state, *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale }; UIWindow* parent = this->parent; int left = 0, top = 0; for (const UIWindow* window = this; window; window = window->parent) { left += window->geometry.x; top += window->geometry.y; } const bool chat = this->m_edit->input.chatInput == this || this->m_edit->otherChatInput == this; const DWORD tick = timeGetTime(); LinkLayout layout(*this); EditPainting painting{ this->text, this->anchor, this->cursor, this->mask, this->firstVisible, this->textY, this->invalidatesParent, this->textColor, this->secondColor, focused, chat, this->m_edit->input.suggestionsEnabled, tick, this->m_edit->candidateCursor, this->geometry.width, this->geometry.height, this->m_edit->screenWidth, this->m_edit->screenHeight, this->m_edit->input, this->m_edit->charset, viewport, *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale, this->m_edit->colorChip, parent, this->m_edit->candidateWindow, this->m_edit->readingWindow, left, top, this->links, layout }; painting.alternate = alternate; painting.placeholder = placeholder; painting.placeholderColor = placeholderColor; painting.placeholderEnabled = placeholderEnabled; painting.Draw(); } // OFFSET: 0x00862FB0 void UIEditCtrl::Synchronize() { const bool focused = this->m_edit->focus.window == this; EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; EditViewport viewport{ this->text, this->anchor, this->cursor, this->firstVisible, this->geometry.width, g_textCodePage, this->m_edit->input, state, *this->geometry.surface, this->m_edit->buttons.fonts, this->m_edit->buttons.locale }; viewport.Synchronize(); } // OFFSET: 0x00868450 void UIEditCtrl::Trim() { const bool focused = this->m_edit->focus.window == this; EditTextState state{this->text, this->anchor, this->cursor, this->maximum, focused, this->m_edit->input, g_textCodePage}; state.Trim(); } // OFFSET: 0x00858D50 // FUNCTION: fn_10768 int UIEditCtrl::Length() const { return static_cast(this->m_edit->focus.window == this ? this->m_edit->input.text.size() : this->text.size()); } // OFFSET: 0x00858D20 // FUNCTION: fn_10767 const char* UIEditCtrl::Text() { if (this->m_edit->focus.window == this) { this->Synchronize(); } return this->text.c_str(); } // OFFSET: 0x00858D80 // FUNCTION: fn_10769 std::string UIEditCtrl::LinkedText() { return std::string(this->linkedText.c_str(), this->linkedText.size()); } // OFFSET: 0x00858F30 // FUNCTION: fn_10771 std::string UIEditCtrl3::TakePendingText() { std::string result; for (std::size_t i = 0; i < this->pendingText.size(); ++i) { result.append(this->pendingText[i]); } this->pendingText.clear(); return result; } // OFFSET: 0x008590E0 // FUNCTION: fn_10772 bool HasItemLinkTag(const std::string& text) { return text.find(g_itemLinkOpen) != std::string::npos || text.find(g_itemLinkClose) != std::string::npos; } // OFFSET: 0x00859170 // FUNCTION: fn_10773 bool HasNaviLinkTag(const std::string& text) { return text.find(g_editNaviTagBegin) != std::string::npos || text.find(g_editNaviTagEnd) != std::string::npos; } // OFFSET: 0x00865DD0 // FUNCTION: fn_10937 void UIEditCtrl::Background(int red, int green, int blue) { this->red = red; this->green = green; this->blue = blue; this->Invalidate(); } // OFFSET: 0x00865E00 // FUNCTION: fn_10938 void UIEditCtrl::Border(int red, int green, int blue) { this->borderRed = red; this->borderGreen = green; this->borderBlue = blue; } // OFFSET: 0x00865E30 // FUNCTION: fn_10939 void UIEditCtrl3::SetTagColor(std::uint32_t color) { for (auto it = this->entries.begin(); it != this->entries.end(); ++it) { for (unsigned index = 0; index < it->size(); ++index) { (*it)[index]->m_normalColor = color; (*it)[index]->m_color = color; (*it)[index]->m_hoverColor = color; } } } // OFFSET: 0x00868570 // FUNCTION: fn_10960 void UIEditCtrl::TextColor(std::uint32_t primary, std::uint32_t secondary) { this->secondColor = secondary; this->textColor = primary; this->Invalidate(); } // OFFSET: 0x00856EB0 // FUNCTION: fn_10756 void UIEditCtrl3::DrawBlinkingCaret(const std::uint32_t& color) { if (timeGetTime() / 500 & 1) { return; } if (g_windowMgr.IsHoverOnWindow01C8Button() && !g_inputSuggestionsEnabled) { return; } this->DrawTextAt(this->m_edit->buttons.fonts, this->m_edit->buttons.locale, 1, 0, "|", 0, 0, 12, color, 0, 0); } // OFFSET: 0x00854130 // OFFSET: 0x00856F10 // FUNCTION: fn_10757 void UIEditCtrl3::PlaceTags(const int& x, const int& y, const int& firstLine, const int& endLine, const int& line, const int&) { for (auto it = this->entries.begin(); it != this->entries.end(); ++it) { for (unsigned index = 0; index < it->size(); ++index) { UIItemTagButton* tag = (*it)[index]; if (tag->line < firstLine || tag->line > endLine - 1) { tag->Move(-100, -100); } else if (line == tag->line) { tag->Move(x - 1 + tag->column, y); } } } } // OFFSET: 0x00856FB0 // FUNCTION: fn_10758 void UIEditCtrl::DrawSelectionAt(int x, int y, int width) { const int extent = x < 3 ? width + (x - 3) : width; const int left = std::max(x, 3); const int right = this->geometry.width; if (left < right && extent > 0) { unsigned red, green, blue; SkinPaletteChannels(this->m_edit->buttons.resources, 6, 2, red, green, blue); this->FillRegion(left, y, left + extent > right ? right - left : extent, 14, RGB(red, green, blue)); } } // OFFSET: 0x00857040 // FUNCTION: fn_10759 void UIEditCtrl::DrawSelection(int x, int width) { const int extent = x < 3 ? width + (x - 3) : width; const int left = std::max(x, 3); const int right = this->geometry.width; if (left < right && extent > 0) { unsigned red, green, blue; SkinPaletteChannels(this->m_edit->buttons.resources, 6, 2, red, green, blue); this->FillRegion(left, 0, left + extent > right ? right - left : extent, this->geometry.height, RGB(red, green, blue)); } } // OFFSET: 0x0096F410 // FUNCTION: fn_13233 UISkillListWnd::UISkillListWnd(UIWindowContext& windows, UIFrameContext& frames) : UIFrameWnd(windows, frames, 0) { this->scrollBar = nullptr; this->unknown_00C0 = 0; this->hovered = -1; this->columns = 1; this->saved = nullptr; } // INLINED UIEditCtrlWheel::UIEditCtrlWheel(UIWindowContext& windows, UIEditContext& edit) : UIEditCtrl(windows, edit) { } // OFFSET: 0x009701B0 UIEditCtrlWheel::~UIEditCtrlWheel() = default; // OFFSET: 0x0098A240 // FUNCTION: fn_13408 void UIEditCtrlWheel::Slot35(int value) { if (this->parent) { this->parent->Slot35(value); } } // OFFSET: 0x0086A550 // FUNCTION: fn_10977 void UIEditCtrl::MoveCandidateWindow(int x) { UIWindow* window = g_windowMgr.window_03A4; if (window == nullptr) { return; } int left = x; int top = this->geometry.height + 6; left += this->geometry.x; top += this->geometry.y; for (const UIWindow* node = this->parent; node != nullptr; node = node->parent) { left += node->geometry.x; top += node->geometry.y; } if (window->geometry.width + left > g_renderer->viewport.width) { left = g_renderer->viewport.width - window->geometry.width; } if (window->geometry.height + top > g_renderer->viewport.height) { top += -12 - this->geometry.height - window->geometry.height; } window->Move(left, top); } // OFFSET: 0x0086A5E0 // FUNCTION: fn_10978 void UIEditCtrl::MoveReadingWindow(int x) { UIWindow* window = g_windowMgr.window_03AC; if (window == nullptr) { return; } int left = x; int top = this->geometry.height + 6; left += this->geometry.x; top += this->geometry.y; for (const UIWindow* node = this->parent; node != nullptr; node = node->parent) { left += node->geometry.x; top += node->geometry.y; } if (window->geometry.width + left > g_renderer->viewport.width) { left = g_renderer->viewport.width - window->geometry.width; } if (window->geometry.height + top > g_renderer->viewport.height) { top += -12 - this->geometry.height - window->geometry.height; } window->Move(left, top); } // OFFSET: 0x008570D0 // FUNCTION: fn_10760 void UIBmpTextButton2::DrawLabels() { for (unsigned index = 0; index < this->labels.size(); ++index) { const BmpTextButtonLabel& label = this->labels[index]; if (label.text.size() == 0) { continue; } int x = label.x; int y = label.y; int shadowX = 0; int shadowY = 0; if (x == -1000) { const int width = this->TextWidth(this->m_buttonContext->fonts, this->m_buttonContext->locale, label.text.c_str(), label.text.size(), 0, label.height, label.bold, 0); x = static_cast((this->geometry.width - width) * 0.5); } if (y == -1000) { const int height = this->TextHeight(this->m_buttonContext->fonts, this->m_buttonContext->locale, label.text.c_str(), label.text.size(), 0, label.height, label.bold, 0); y = static_cast((this->geometry.height - height) * 0.5); } std::uint32_t color = label.color; std::uint32_t shadowColor = 0xE6E6E6; switch (this->geometry.unknown_0030) { case 0: shadowX = x + 1; shadowY = y + 1; shadowColor = 0xD7D7D7; break; case 1: shadowX = x + 1; shadowY = y + 1; shadowColor = 0xC7A796; break; case 2: shadowX = x; shadowY = y; shadowColor = 0xFFFFFF; ++x; ++y; break; case 3: color = 0xADADAD; shadowX = x + 1; shadowY = y + 1; shadowColor = 0xD7D7D7; break; } if (label.shadow == 1) { this->DrawTextAt(this->m_buttonContext->fonts, this->m_buttonContext->locale, shadowX, shadowY, label.text.c_str(), 0, 0, label.height, shadowColor, label.bold, 0); } this->DrawTextAt(this->m_buttonContext->fonts, this->m_buttonContext->locale, x, y, label.text.c_str(), 0, 0, label.height, color, label.bold, 0); } } // OFFSET: 0x008572F0 // FUNCTION: fn_10761 void UITextureButton::VisitChildren() { CTexture* texture = nullptr; switch (this->geometry.unknown_0030) { case 0: texture = g_texMgr.Load( (this->unknown_011C == 1 && this->unknown_011D == 1 ? this->pressedTexture : this->normalTexture).c_str(), 0, false, true, false ); break; case 1: texture = g_texMgr.Load(this->hoverTexture.c_str(), 0, false, true, false); break; case 2: texture = g_texMgr.Load(this->pressedTexture.c_str(), 0, false, true, false); break; } if (this->m_disabled == 1 && this->disabledTexture.size() > 0) { texture = g_texMgr.Load(this->disabledTexture.c_str(), 0, false, true, false); } DrawTextureRegion( g_renderer->primitives, g_renderer->queues, static_cast(this->geometry.x), static_cast(this->geometry.y), static_cast(texture->Width()), static_cast(texture->Height()), 0xFFFFFFFF, texture, g_renderer->fog.supported != 0, g_depthStart, g_depthEnd ); } // OFFSET: 0x00858B80 // FUNCTION: fn_10764 std::string UINaviLinkButton::Link() { return this->link; } // OFFSET: 0x00858BE0 // FUNCTION: fn_10765 int UISpriteButton::FrameHeight(int action, int frame) { auto* sprite = static_cast(ResourceMgr::Instance().Load(this->spriteName.c_str())); auto* actions = static_cast(ResourceMgr::Instance().Load(this->actionName.c_str())); return sprite->images[0][actions->Frame(action, frame).cells[0].image]->height; } // OFFSET: 0x00858C50 // FUNCTION: fn_10766 int UISpriteButton::FrameWidth(int action, int frame) { auto* sprite = static_cast(ResourceMgr::Instance().Load(this->spriteName.c_str())); auto* actions = static_cast(ResourceMgr::Instance().Load(this->actionName.c_str())); return sprite->images[0][actions->Frame(action, frame).cells[0].image]->width; } // OFFSET: 0x0097D220 // FUNCTION: fn_13325 void UINoticeMessageBox_LockSellItem::Slot15(int, int) { auto* button = new UIBitmapButton(*this->m_context, *this->m_controls); button->SetBitmap("유저인터페이스\\inventory\\bt_close.bmp", 0, 0); button->SetBitmap("유저인터페이스\\inventory\\bt_close.bmp", 1, 0); button->SetBitmap("유저인터페이스\\inventory\\bt_close.bmp", 2, 0); button->SetSize(button->BitmapWidth(), button->BitmapHeight()); button->Move(229, 4); button->SetId(201); this->AddChild(button); } // OFFSET: 0x0097E3E0 // FUNCTION: fn_13327 void UIItemWnd::Slot18() { } // OFFSET: 0x00896BC0 // FUNCTION: fn_11518 void UIEditCtrl_Custom::Synchronize() { const int previousCursor = this->cursor; CLanguage& input = this->m_edit->input; input.CopyDisplayText(this->text); input.Selection(this->anchor, this->cursor); this->Trim(); const auto length = static_cast(this->text.size()); bool clamped = false; if (static_cast(this->cursor) > length || static_cast(this->anchor) > length) { this->anchor = std::min(this->anchor, length); this->cursor = std::min(this->cursor, length); input.Select(this->anchor, this->cursor); clamped = true; } if (this->cursor == 0) { this->firstVisible = 0; return; } std::string visible; if (static_cast(std::abs(input.cursor - input.anchor)) >= this->text.size()) { this->firstVisible = 0; } FontCache& fonts = this->m_edit->buttons.fonts; const TextLocale& locale = this->m_edit->buttons.locale; const int available = this->geometry.width - 12; if (this->cursor > previousCursor || clamped) { int before = 0; if (this->firstVisible != 0) { before = this->TextWidth(fonts, locale, this->text.c_str(), this->firstVisible, 0, 12, this->unknown_011C, 0); } const int position = this->TextWidth(fonts, locale, this->text.c_str(), this->cursor, 0, 12, this->unknown_011C, 0); if (position + 3 - before > available) { const char* end = this->text.c_str() + this->text.size(); const char* next = CharNextExA(static_cast(g_textCodePage), this->text.c_str(), 0); while (this->TextWidth(fonts, locale, next, 0, 0, 12, this->unknown_011C, 0) + 3 > available && next < end) { next = CharNextExA(static_cast(g_textCodePage), next, 0); } const auto tail = static_cast(std::strlen(next)); const auto scrolled = static_cast(this->firstVisible + this->cursor - previousCursor); this->firstVisible = std::min(this->cursor - tail, scrolled); } } else if (this->cursor < previousCursor) { if (this->TextWidth(fonts, locale, this->text.c_str(), this->cursor, 0, 12, this->unknown_011C, 0) + 3 < available && this->firstVisible > this->cursor) { this->firstVisible += this->cursor - previousCursor; } this->firstVisible = std::max(this->firstVisible, 0); } } // OFFSET: 0x00972520 // FUNCTION: fn_13272 void UIItemStoreFindWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); } // OFFSET: 0x00972570 // FUNCTION: fn_13273 void UIItemStoreSubWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 1 && drag->source != 9) { mode->SendMsg(18, 0, 0, 0, 0); return; } if (static_cast(mode)->ConfirmDraggedItemUse()) { return; } if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 7, 0, 0, 0); } // OFFSET: 0x00972630 // FUNCTION: fn_13274 void UIItemStoreWnd::Slot10(int x, int y, std::intptr_t value) { char text[256]; if (g_unknown_01738268) { if (g_unknown_01738270 == 1) { std::memset(text, 0, 250); std::sprintf(text, LookupMessage(0x9C2)); g_windowMgr.SendNotice(1, reinterpret_cast(text), 0xFF, 0, 0, 0); return; } if (!g_unknown_0173826C && !g_unknown_01738270) { std::memset(text, 0, 250); std::sprintf(text, LookupMessage(0x9C5)); g_windowMgr.SendNotice(1, reinterpret_cast(text), 0xFF, 0, 0, 0); return; } } if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 1 && drag->source != 9) { mode->SendMsg(18, 0, 0, 0, 0); return; } if (static_cast(mode)->ConfirmDraggedItemUse()) { return; } if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 7, 0, 0, 0); } // OFFSET: 0x009727F0 // FUNCTION: fn_13275 void UIItemWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } const ModeDragState* drag = reinterpret_cast(value); switch (drag->source) { case 1: if (reinterpret_cast(drag->unknown_038C) == this->tabs) { PACKET_CZ_INVENTORY_TAB packet; packet.packetType = ID_CZ_INVENTORY_TAB; packet.index = static_cast(drag->id); packet.favorite = this->tabs->TabAt(x, y) != 3; GetRagConnection().Send(g_packetLengths.FixedLength(packet.packetType), &packet); } break; case 2: case 17: case 18: case 24: this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; case 6: case 9: case 15: if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 6, 0, 0, 0); return; case 14: { UIWindow* target = reinterpret_cast(g_windowMgr.unknown_0378); if (target) { target->SendMsg(nullptr, 75, reinterpret_cast(drag->name.c_str()), 0, 0, 0); } break; } case 28: { UIWindow* window = g_windowMgr.LookupWindow(295); if (window) { static_cast(window)->Reset(); } break; } case 33: { UIWindow* window = g_windowMgr.LookupWindow(343); if (window) { static_cast(window)->ResetItem(); } break; } } g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); } // OFFSET: 0x00989080 // FUNCTION: fn_13396 void UIItemStoreFindWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_01D4) { if (mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(56, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.unknown_02F4 && mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(78, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (HIBYTE(GetAsyncKeyState(VK_SHIFT))) { if (g_windowMgr.unknown_01D4) { mode->SendMsg(333, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989210 // FUNCTION: fn_13397 void UIItemStoreSubWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_01D4) { if (mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(56, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.unknown_02F4 && mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(78, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (HIBYTE(GetAsyncKeyState(VK_SHIFT))) { if (g_windowMgr.unknown_01D4) { mode->SendMsg(333, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x009893A0 // FUNCTION: fn_13398 void UIItemStoreWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_01D4) { if (mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(56, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.unknown_02F4 && mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(78, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (HIBYTE(GetAsyncKeyState(VK_SHIFT))) { mode->SendMsg(333, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989520 // FUNCTION: fn_13399 void UIItemWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_01F0 || g_windowMgr.unknown_01F8) { return; } item = LookupClientItemByIdentity(g_session.m_inventoryItems, item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 1, item, item.quantity, -1); if (mode->ConfirmDraggedItemUse()) { return; } if (g_windowMgr.window_0288) { if (mode->unknown_05CE) { mode->unknown_05CE = 0; mode->SendMsg(55, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.LookupWindow(10011)) { if (mode->unknown_05CE) { mode->unknown_05CE = 0; mode->SendMsg(51, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.unknown_02F4 && mode->unknown_05CE) { mode->unknown_05CE = 0; mode->SendMsg(76, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (HIBYTE(GetAsyncKeyState(VK_SHIFT))) { if (this->tabs) { mode->SendMsg(334, static_cast(item.unknown_0000[1]), this->tabs->unknown_007C == 3, 0, 0); } } else if (HIBYTE(GetAsyncKeyState(VK_CONTROL))) { if (item.unknown_0000[1] > 0 && !g_session.IsPetEgg(item.GetItemId())) { const int magnifiers = LookupClientItem(g_session.m_inventoryItems, 611, 0).quantity + LookupClientItem(g_session.m_inventoryItems, 12325, 0).quantity; if (magnifiers <= 0) { g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(2735)), 255, 0, 0, 0); } if (this->unknown_010C == 1 && !item.identified) { struct { unsigned short packetType; unsigned short index; } packet; packet.packetType = ID_CZ_REQ_ONECLICK_ITEMIDENTIFY; packet.index = static_cast(item.unknown_0000[1]); GetRagConnection().Send(g_packetLengths.FixedLength(packet.packetType), &packet); } } } else { g_windowMgr.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989960 // FUNCTION: fn_13401 void UIMerchantItemPurchaseWnd::Slot32(int x, int y) { const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_0300) { item = g_session.FindItem1760ByItemId(item.itemId.c_str()); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 13, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_0300)->SendMsg(nullptr, 38, 0, 0, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989B00 // FUNCTION: fn_13402 void UIMerchantItemShopWnd::Slot32(int x, int y) { const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_0308) { ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 12, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_0308)->SendMsg(nullptr, 38, 0, 0, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989C40 // FUNCTION: fn_13403 void UIMerchantItemWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (!g_windowMgr.LookupWindow(10011) && !g_windowMgr.unknown_02FC) { if (g_windowMgr.window_0288) { if (mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(79, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else if (g_windowMgr.unknown_01D4 && mode->unknown_05CC[2]) { mode->unknown_05CC[2] = 0; mode->SendMsg(77, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } } else if (HIBYTE(GetAsyncKeyState(VK_SHIFT))) { if (g_windowMgr.unknown_01D4) { mode->SendMsg(335, static_cast(item.unknown_0000[1]), item.quantity, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989DF0 // FUNCTION: fn_13404 void UIMerchantMirrorItemWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_02FC) { item = g_session.FindItem1750(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 11, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_02FC)->SendMsg(nullptr, 38, 0, 0, 0, 0); } else if (g_windowMgr.unknown_040C) { item = g_session.FindItem1750(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 20, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_040C)->SendMsg(nullptr, 38, 0, 0, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x00989FE0 // FUNCTION: fn_13405 void UIMerchantShopMakeWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* gameMode = static_cast(g_modeMgr.GetGameMode()); if (HIBYTE(GetAsyncKeyState(VK_MENU))) { if (g_windowMgr.unknown_02F8) { item = g_session.FindItem1768(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; gameMode->drag.BeginItem(this->m_frameContext->windows, descriptions, 10, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_02F8)->SendMsg(nullptr, 38, 0, 0, 0, 0); InputFocus focus{g_windowMgr.hoverWindow}; focus.Set(nullptr); } else if (g_windowMgr.unknown_0410) { item = g_session.FindItem1768(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; gameMode->drag.BeginItem(this->m_frameContext->windows, descriptions, 19, item, item.quantity, -1); reinterpret_cast(g_windowMgr.unknown_0410)->SendMsg(nullptr, 38, 0, 0, 0, 0); } } else { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } } // OFFSET: 0x0097E790 // FUNCTION: fn_13329 void UIItemDropCntWnd::Paint() { this->DrawBorder(0, 0, 0, 0); } // OFFSET: 0x0097E3F0 // FUNCTION: fn_13328 void UIItemBaseWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; int slots = (this->geometry.height - 38) / 32; for (int y = 17; slots > 0; --slots, y += 32) { for (int column = 0, x = 40; column < columns; ++column, x += 32) { DrawItemSlotBackground(*this, x, y); } } ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int top = visible / this->columns * 32; const int x = visible % this->columns * 32 + 44; if (this->showQuantity != 0) { DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); } else { DrawItemIcon(*this, controls.resources, descriptions, x, top + 21, *it, 0); } if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } if (++visible == this->visibleRows * this->columns) { break; } } } // OFFSET: 0x00981770 // FUNCTION: fn_13339 void UIMerchantItemMyShopWnd::Paint() { UIItemBaseWnd::Paint(); if (this->unknown_011C == 57) { this->DrawButtonBar(3, 0, 1); } if (this->duration > 0) { const int remaining = this->duration - (timeGetTime() - this->startTick); if (remaining > 0) { UIButtonContext& controls = *this->m_controls; const int days = remaining / 86400000; const int hours = remaining / 3600000 % 24; const int minutes = remaining / 60000 % 60; const int seconds = remaining / 1000 % 60; if (this->unknown_0100 == 1) { if (remaining <= 60000) { this->DrawTextAt( controls.fonts, controls.locale, 12, this->geometry.height - 42, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 11, 0xFF, 1, 0 ); } else { this->DrawTextAt( controls.fonts, controls.locale, 12, this->geometry.height - 42, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 11, 0, 1, 0 ); } } else if (remaining <= 60000) { this->DrawTextAt( controls.fonts, controls.locale, 20, this->geometry.height - 50, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 12, 0xFF, 1, 0 ); } else { this->DrawTextAt( controls.fonts, controls.locale, 20, this->geometry.height - 50, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 12, 0, 1, 0 ); } } } } // OFFSET: 0x0097A670 // FUNCTION: fn_13319 void UIMerchantItemPurchaseMSGWnd::Slot15(int, int) { this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(100, 15); this->title->SetTextFitted(LookupMessage(2326)); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->buyButton = new UIBitmapButton(*this->m_context, *this->m_controls); this->buyButton->SetBitmap("유저인터페이스\\btn_buy.bmp", 0, 0); this->buyButton->SetBitmap("유저인터페이스\\btn_buy_a.bmp", 1, 0); this->buyButton->SetBitmap("유저인터페이스\\btn_buy_b.bmp", 2, 0); this->buyButton->SetSize(this->buyButton->BitmapWidth(), this->buyButton->BitmapHeight()); this->buyButton->Move(this->geometry.width - 106, this->geometry.height - 24); this->buyButton->SetId(184); this->AddChild(this->buyButton); this->cancelButton = new UIBitmapButton(*this->m_context, *this->m_controls); this->cancelButton->SetBitmap("유저인터페이스\\btn_cancel.bmp", 0, 0); this->cancelButton->SetBitmap("유저인터페이스\\btn_cancel_a.bmp", 1, 0); this->cancelButton->SetBitmap("유저인터페이스\\btn_cancel_b.bmp", 2, 0); this->cancelButton->SetSize(this->cancelButton->BitmapWidth(), this->cancelButton->BitmapHeight()); this->cancelButton->Move(this->geometry.width - 61, this->geometry.height - 24); this->cancelButton->SetId(185); this->AddChild(this->cancelButton); this->firstLine = new UIStaticText(*this->m_context, *this->m_controls); this->firstLine->SetSize(200, 15); this->firstLine->SetText(LookupMessage(2327), 0); this->firstLine->Move(10, 20); this->AddChild(this->firstLine); this->secondLine = new UIStaticText(*this->m_context, *this->m_controls); this->secondLine->SetSize(200, 15); this->secondLine->Move(10, 40); this->AddChild(this->secondLine); this->thirdLine = new UIStaticText(*this->m_context, *this->m_controls); this->thirdLine->SetSize(200, 15); this->thirdLine->SetText(LookupMessage(2329), 0); this->thirdLine->Move(10, 60); this->AddChild(this->thirdLine); } // OFFSET: 0x00981990 // FUNCTION: fn_13340 void UIMerchantItemPurchaseMSGWnd::Paint() { this->ClearSurface(0xFFFFFFFF); this->DrawTitleBar(this->m_controls->fonts, this->m_controls->locale, false, "", 0); this->DrawButtonBar(2, 0, 1); } // OFFSET: 0x009827C0 // FUNCTION: fn_13343 void UIMerchantItemWnd::Paint() { UIItemBaseWnd::Paint(); UIButtonContext& controls = *this->m_controls; const auto* count = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\inventory\\icon_num.bmp"))); this->DrawBitmap(10, this->geometry.height - 22, &count->image, true); const std::uint32_t countColor = g_session.cartCount >= g_session.cartMaxCount ? 0xFF : 0x232323; this->DrawTextAt( controls.fonts, controls.locale, 23, this->geometry.height - 19, FormatOwnedString("%d", g_session.cartCount).c_str(), 0, 0, 11, countColor, 0, 0 ); const int countWidth = this->TextWidth(controls.fonts, controls.locale, FormatOwnedString("%d", g_session.cartCount).c_str(), 0, 0, 11, 0, 0); this->DrawTextAt( controls.fonts, controls.locale, countWidth + 24, this->geometry.height - 19, FormatOwnedString("/%d", g_session.cartMaxCount).c_str(), 0, 0, 11, 0, 0, 0 ); const auto* weight = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\inventory\\icon_weight.bmp"))); this->DrawBitmap(75, this->geometry.height - 20, &weight->image, true); const std::uint32_t weightColor = g_session.cartWeight >= g_session.cartMaxWeight ? 0xFF : 0x232323; this->DrawTextAt( controls.fonts, controls.locale, 90, this->geometry.height - 19, FormatOwnedString("%d", g_session.cartWeight).c_str(), 0, 0, 11, weightColor, 0, 0 ); const int weightWidth = this->TextWidth(controls.fonts, controls.locale, FormatOwnedString("%d", g_session.cartWeight).c_str(), 0, 0, 11, 0, 0); this->DrawTextAt( controls.fonts, controls.locale, weightWidth + 91, this->geometry.height - 19, FormatOwnedString("/%d", g_session.cartMaxWeight).c_str(), 0, 0, 11, 0, 0, 0 ); } // OFFSET: 0x009834F0 // FUNCTION: fn_13345 void UINoticeMessageBox_LockSellItem::Paint() { const auto* background = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\inventory\\popup_itemDeal_lock.bmp"))); this->DrawBitmap(0, 0, &background->image, false); this->DrawCenteredText(0, 5, LookupMessage(2951), this->geometry.width, 0, 12, 0xFFFFFF, 0); } // OFFSET: 0x00983550 // FUNCTION: fn_13346 void UISkillListWnd::Paint() { CFile file; char text[80]; const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve( g_skillTooltipActive ? "유저인터페이스\\basic_interface\\titlebar_left2.bmp" : "유저인터페이스\\basic_interface\\titlebar_left.bmp" ))); this->DrawBitmap(0, 0, &left->image, false); const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve( g_skillTooltipActive ? "유저인터페이스\\basic_interface\\titlebar_right2.bmp" : "유저인터페이스\\basic_interface\\titlebar_right.bmp" ))); this->DrawBitmap(this->geometry.width - right->image.width, 0, &right->image, false); int count = (this->geometry.width - 24) / 12 + ((this->geometry.width - 24) % 12 != 0); for (int x = 12; count > 0; --count, x += 12) { const auto* middle = static_cast(ResourceMgr::Instance().Load(Resolve( g_skillTooltipActive ? "유저인터페이스\\basic_interface\\titlebar_mid2.bmp" : "유저인터페이스\\basic_interface\\titlebar_mid.bmp" ))); this->DrawBitmap(x, 0, &middle->image, false); } if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* itemLeft = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &itemLeft->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* itemRight = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - itemRight->image.width, y, &itemRight->image, false); } unsigned red, green, blue; SkinPaletteChannels(ResourceMgr::Instance(), 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(2, 0, 1); const int slotColumns = (this->geometry.width - 40) / 32; const int slotRows = (this->geometry.height - 38) / 32; int slots = slotRows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } unsigned fillBlue; SkinPaletteChannels(ResourceMgr::Instance(), 2, 2, red, green, fillBlue); this->FillRegion(72, 17, slotColumns * 32 - 32, slotRows * 32, RGB(red, green, fillBlue)); if (this->skillTab == 0) { this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 17, 4, LookupMessage(0x3A9), 0, 0, 12, 0xFFFFFF, 0, 0); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 16, 3, LookupMessage(0x3A9), 0, 0, 12, 0, 0, 0); std::sprintf(text, LookupMessage(0x11C), *reinterpret_cast(g_session.unknown_1664)); } else if (this->skillTab == 1) { this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 17, 4, LookupMessage(0x4EE), 0, 0, 12, 0xFFFFFF, 0, 0); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 16, 3, LookupMessage(0x4EE), 0, 0, 12, 0, 0, 0); } if (this->skillTab != 1) { this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 16, this->geometry.height - 20, text, 0, 0, 12, 0, 0, 0); } int drawn = 0; int index = 0; int skillLevel; int spLevel; for (auto it = this->skills.begin(); it != this->skills.end(); ++index) { if (index < this->scroll * this->columns) { ++it; continue; } const int top = drawn / this->columns * 32; int x = drawn % this->columns * 32; if (this->hovered == index) { unsigned selectRed, selectGreen, selectBlue; SkinPaletteChannels(ResourceMgr::Instance(), 6, 2, selectRed, selectGreen, selectBlue); if (it->level == 0) { SkinPaletteChannels(ResourceMgr::Instance(), 10, 2, selectRed, selectGreen, selectBlue); } else if (it->unknown_0014 == 0) { SkinPaletteChannels(ResourceMgr::Instance(), 14, 2, selectRed, selectGreen, selectBlue); } this->FillRegion(x + 104, top + 19, 164, 28, RGB(selectRed, selectGreen, selectBlue)); } g_session.ItemBitmapPath(it->name, text); const auto* icon = static_cast(ResourceMgr::Instance().Load(Resolve(text))); this->DrawBitmap(x + 44, top + 21, &icon->image, true); int shade; if (it->level == 0) { shade = 120; } else { const char* format; int levelX; if (CSkillInfo::UsesLevel(*g_session.m_hotkeyScript, static_cast(it->id))) { std::sprintf(text, g_serviceType != 12 ? "Lv :" : "Nv :"); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, x + 124, top + 34, text, 0, 0, 12, 0, 0, 0); if (this->skillTab == 0) { skillLevel = g_session.HomunSkillLevel(static_cast(it->id)); } else if (this->skillTab == 1) { skillLevel = g_session.MercSkillLevel(static_cast(it->id)); } if (skillLevel <= 0 || skillLevel > it->level) { skillLevel = it->level; } std::sprintf(text, "%2d", skillLevel); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, x + 149, top + 34, text, 0, 0, 12, skillLevel != it->level ? 0xFF : 0, 0, 0); format = "/ %2d"; levelX = 168; } else { format = g_serviceType != 12 ? "Lv : %d" : "Nv : %d"; levelX = 113; } std::sprintf(text, format, it->level); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, levelX + x, top + 34, text, 0, 0, 12, 0, 0, 0); if (it->unknown_000C == 0) { std::sprintf(text, LookupMessage(0x11E)); } else { int sp = static_cast(it->unknown_0014); if (CSkillInfo::UsesLevel(*g_session.m_hotkeyScript, static_cast(it->id))) { if (this->skillTab == 0) { spLevel = g_session.HomunSkillLevel(static_cast(it->id)); } else if (this->skillTab == 1) { spLevel = g_session.MercSkillLevel(static_cast(it->id)); } const int amount = it->UseSpAmount(*g_session.m_hotkeyScript, spLevel); if (amount != 0 && spLevel <= it->level) { sp = amount; } } const int ap = it->UseApAmount(*g_session.m_hotkeyScript, it->level); if (ap != 0) { std::sprintf(text, "Sp : %d , Ap : %d", sp, ap); } else { std::sprintf(text, "Sp : %d", sp); } } this->DrawTextAt(this->m_context->fonts, this->m_context->locale, x + 212, top + 34, text, 0, 0, 12, 0, 0, 0); shade = 0; } x += 112; std::string name = this->FitDisplayText(this->geometry.width - x - 20, it->DisplayName(*g_session.m_hotkeyScript), 0, 12, 0); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, x, top + 22, name.c_str(), 0, 0, 12, RGB(shade, shade, shade), 0, 0); if (++drawn == this->visibleRows * this->columns) { break; } ++it; } } // OFFSET: 0x00983F80 // FUNCTION: fn_13347 void UIItemSellWnd2::Slot26(int x, int y) { if (g_windowMgr.unknown_0064 == 0) { return; } UIWindow* target = g_windowMgr.unknown_0254; if (target) { this->Slot25(x, y); CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); this->m_recorder->RecordDrop(x, y, mode->drag, 160); target->Slot10(x, y, reinterpret_cast(&mode->drag)); } } // OFFSET: 0x00983FF0 // FUNCTION: fn_13348 void UIItemSellWnd::Slot26(int x, int y) { if (g_windowMgr.unknown_0064 == 0) { return; } UIWindow* target = g_windowMgr.unknown_0250; if (target) { this->Slot25(x, y); CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); this->m_recorder->RecordDrop(x, y, mode->drag, 22); target->Slot10(x, y, reinterpret_cast(&mode->drag)); } } // OFFSET: 0x00984130 // FUNCTION: fn_13351 void UIItemStoreFindWnd::Slot26(int, int) { this->SendMsg(nullptr, 6, 232, 0, 0, 0); } // OFFSET: 0x00984150 // FUNCTION: fn_13352 void UIItemStoreSubWnd::Slot26(int, int) { this->SendMsg(nullptr, 6, 232, 0, 0, 0); } // OFFSET: 0x00984170 // FUNCTION: fn_13353 void UIItemWnd::Slot26(int x, int y) { if (y < 17) { this->SendMsg(this, 6, 202, 0, 0, 0); return; } if (GetAsyncKeyState(VK_SHIFT)) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { return; } CMode* mode = g_modeMgr.GetGameMode(); switch (item.unknown_0000[0]) { case 0: case 1: case 2: if (item.GetItemId() == 12802 && reinterpret_cast(&g_windowMgr)->Confirm(LookupMessage(2373), 2, false, false, 0, "Message", 280, 120, 0) == 188) { break; } mode->SendMsg(27, static_cast(item.unknown_0000[1]), 0, 0, 0); break; case 4: case 5: case 8: case 9: case 11: case 12: case 13: case 14: case 15: if (!item.identified) { break; } if (item.unknown_0000[1] == 0 || item.unknown_0000[2] == 0 || item.unknown_0000[3] != 0) { if (!g_session.IsPetAccessory(item.GetItemId())) { break; } } if (GetAsyncKeyState(VK_CONTROL) && g_session.m_swapEquipmentMode) { mode->SendMsg(302, static_cast(item.unknown_0000[1]), static_cast(item.unknown_0000[2]), 0, 0); } else if (g_windowMgr.LookupWindow(295)) { g_windowMgr.LookupWindow(295)->SendMsg(this, 23, item.unknown_0000[1], 0, 0, 0); } else if (g_windowMgr.LookupWindow(343)) { g_windowMgr.LookupWindow(343)->SendMsg(this, 23, item.unknown_0000[1], 0, 0, 0); } else { mode->SendMsg(19, static_cast(item.unknown_0000[1]), static_cast(item.unknown_0000[2]), 0, 0); } break; case 6: mode->SendMsg(123, static_cast(item.unknown_0000[1]), 0, 0, 0); break; case 10: case 16: case 17: case 19: if (item.unknown_0000[1] == 0 || item.unknown_0000[3] != 0) { break; } if (GetAsyncKeyState(VK_CONTROL) && g_session.m_swapEquipmentMode) { mode->SendMsg(302, static_cast(item.unknown_0000[1]), static_cast(item.unknown_0000[2]), 0, 0); } else { mode->SendMsg(87, static_cast(item.unknown_0000[1]), static_cast(item.unknown_0000[2]), 0, 0); } break; case 18: if (*reinterpret_cast(&g_session.unknown_16F4[4]) >= 0) { ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (reinterpret_cast(&g_windowMgr) ->Confirm(FormatOwnedString(LookupMessage(1226), naming.DisplayName(item, 0).c_str()).c_str(), 2, false, false, 0, "Message", 280, 120, 0) == 187) { mode->SendMsg(27, static_cast(item.unknown_0000[1]), 0, 0, 0); } } break; } } // OFFSET: 0x00985380 // FUNCTION: fn_13364 void UIMerchantItemMyShopWnd::Slot25(int x, int y) { if (y < 17) { UIItemBaseWnd::Slot25(x, y); } } // OFFSET: 0x009886C0 // FUNCTION: fn_13386 void UIItemWnd::Slot19() { if (this->unknown_0128) { this->unknown_0128->Slot19(); } } // OFFSET: 0x00995780 // FUNCTION: fn_45470 void UIItemWnd::RefreshOptionBox() { UIWindow* optionBox = this->optionBox; optionBox->geometry.unknown_0030 = g_serviceOptions.Get(0x108); optionBox->Invalidate(); this->Invalidate(); } // OFFSET: 0x009886D0 // FUNCTION: fn_13387 void UIMerchantItemMyShopWnd::Slot19() { this->Invalidate(); } // OFFSET: 0x009886E0 // FUNCTION: fn_13388 void UIMerchantItemShopWnd::Slot19() { this->Invalidate(); } // OFFSET: 0x009886F0 // FUNCTION: fn_13389 void UIMerchantShopMakeWnd::Slot19() { if (this->unknown_0128 && this->mode) { std::int64_t total = 0; for (unsigned index = 0; index < this->items.size(); ++index) { char text[24] = {}; StringFormat(text, sizeof(text), static_cast(-1), "%s", this->priceEdits[index]->Text()); if (g_session.IsNumberWithCommas(text) == true) { const std::int64_t price = _atoi64(text); const std::int64_t quantity = _atoi64(this->quantityEdits[index]->Text()); const double rate = PriceCommission(price) * -0.01; total += (price - static_cast(price * rate)) * quantity; } } char buffer[128] = {}; StringFormat(buffer, sizeof(buffer), static_cast(-1), "%lld", total); this->unknown_0128->SetText(buffer); this->InvalidateChildren(); return; } if (!g_windowMgr.modalWindows.empty() && g_windowMgr.modalWindows.back()) { return; } int index = -1; for (int i = 0; i < this->unknown_012C; ++i) { if (this->priceEdits[i] == g_windowMgr.GetHoverWindow()) { index = i; break; } } if (this->editIndex != index) { if (index != -1) { this->unknown_0170 = this->priceEdits[index]->Text(); } this->CommitPrice(index); this->InvalidateChildren(); return; } if (index == -1) { return; } const int length = this->priceEdits[index]->Length(); if (length == this->unknown_016C) { return; } this->unknown_016C = length; if (!length) { return; } UIEditCtrl* edit = this->priceEdits[index]; InputFocus focus{g_windowMgr.hoverWindow}; char text[24]; std::sprintf(text, "%s ", edit->Text()); if (!g_session.IsNumberWithCommas(text)) { reinterpret_cast(g_windowMgr).Confirm(LookupMessage(602), 0, true, false, 0, "Message", 280, 120, 0); edit->SetText(this->unknown_0170.c_str()); focus.Set(edit); return; } std::int64_t price = _atoi64(text); if (price < 0) { price = 0; } else if (price > 1000000000) { const int result = reinterpret_cast(g_windowMgr).Confirm(LookupMessage(2467), 2, true, false, 0, "Message", 280, 120, 0); price = 1000000000; if (result == 187) { edit->SetText(_itoa(1000000000, text, 10)); } else { edit->SetText(_itoa(1000000000, text, 10)); focus.Set(edit); } } const PriceColors colors = PriceColor(price); edit->TextColor(colors.primary, colors.secondary); edit->SetText(FormatGroupedInteger(price, text, sizeof(text))); this->unknown_0170 = this->priceEdits[index]->Text(); this->unknown_016C = this->priceEdits[index]->Length(); edit->SetCursor(edit->Length()); } // OFFSET: 0x00988C20 // FUNCTION: fn_13390 void UINoticeMessageBox_LockSellItem::Slot19() { if (this->startTick + this->duration < timeGetTime()) { this->SendMsg(this, 6, 201, 0, 0, 0); } } // OFFSET: 0x00988D50 // FUNCTION: fn_13392 void UIItemSellWnd2::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x00988E10 // FUNCTION: fn_13393 void UIItemSellWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x00988ED0 // FUNCTION: fn_13394 void UIItemShopWnd2::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { g_modeMgr.GetGameMode(); this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x009898A0 // FUNCTION: fn_13400 void UIMerchantItemMyShopWnd::Slot32(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { g_modeMgr.GetGameMode(); this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x0098A220 // FUNCTION: fn_13407 void UISkillListWnd::Slot33(int, int) { this->SendMsg(nullptr, 49, 0, 0, 0, 0); } // OFFSET: 0x009739A0 // FUNCTION: fn_13291 int UISkillListWnd::SkillAt(int x, int y) { if (x < 40 || y < 17 || y >= this->visibleRows * 32 + 17) { return -1; } const int row = (y - 17) / 32; int visible = 0; int index = 0; for (auto it = this->skills.begin(); it != this->skills.end(); ++it, ++index) { if (index >= this->scroll * this->columns) { if (visible == this->columns * row) { return index; } ++visible; } } return -1; } // OFFSET: 0x0098A1E0 // FUNCTION: fn_13406 void UISkillListWnd::Slot32(int x, int y) { const int previous = this->hovered; this->hovered = this->SkillAt(x, y); if (previous != this->hovered) { this->Invalidate(); } } // OFFSET: 0x00974560 // FUNCTION: fn_13302 bool UISkillListWnd::Slot03() { return true; } // OFFSET: 0x00974900 // FUNCTION: fn_13307 void UIItemBaseWnd::Slot15(int, int) { } // OFFSET: 0x00973A20 // FUNCTION: fn_13292 ITEM_INFO UIItemBaseWnd::GetItemByIndex(int index) { int position = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++position) { if (position == index) { return *it; } } return ITEM_INFO(0); } // OFFSET: 0x00973AB0 // FUNCTION: fn_13293 ITEM_INFO UIItemBaseWnd::GetItemAt(int x, int y) { if (x < 40 || x >= this->geometry.width - 20 || y < 17 || y >= this->visibleRows * 32 + 17) { return ITEM_INFO(0); } const int column = (x - 40) / 32; const int row = (y - 17) / 32; if (column > this->columns - 1) { return ITEM_INFO(0); } int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->columns * this->scroll) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * row + column) { return *it; } ++visible; } } } return ITEM_INFO(0); } // OFFSET: 0x00973C20 // FUNCTION: fn_13294 ITEM_INFO UIItemStoreFindWnd::GetItemAt(int x, int y) { if (x >= 20 && x < 52 && y > 16 && y < this->visibleRows * 32 + 17) { int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->columns * this->scroll) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * ((y - 17) / 32) + (x - 20) / 32) { return *it; } ++visible; } } } return ITEM_INFO(0); } return ITEM_INFO(0); } // OFFSET: 0x00973D60 // FUNCTION: fn_13295 ITEM_INFO UIItemStoreSubWnd::GetItemAt(int x, int y) { if (x >= 20 && x < 52 && y > 16 && y < this->visibleRows * 32 + 17) { int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->columns * this->scroll) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * ((y - 17) / 32) + (x - 20) / 32) { return *it; } ++visible; } } } return ITEM_INFO(0); } return ITEM_INFO(0); } // OFFSET: 0x00973EA0 // FUNCTION: fn_13296 ITEM_INFO UIItemStoreWnd::GetItemAt(int x, int y) { if (x >= 40 && x < 72 && y > 16 && y < this->visibleRows * 32 + 17) { int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->columns * this->scroll) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * ((y - 17) / 32) + (x - 40) / 32) { return *it; } ++visible; } } } return ITEM_INFO(0); } return ITEM_INFO(0); } // OFFSET: 0x00973FE0 // FUNCTION: fn_13297 ITEM_INFO UIItemWnd::GetItemAt(int x, int y) { if (x < 40 || x >= this->geometry.width - 20 || y < 17 || y >= this->visibleRows * 32 + 17) { return ITEM_INFO(0); } const int offset = x - 40; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->columns * this->scroll) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * ((y - 17) / 32) + offset / 32) { return *it; } ++visible; } } } return ITEM_INFO(0); } // OFFSET: 0x00974130 // FUNCTION: fn_13298 ITEM_INFO UIMerchantShopMakeWnd::GetItemAt(int x, int y) { if (x < 1 || x >= this->geometry.width - 20 || y < 27 || y >= this->visibleRows * 42 + 44) { return ITEM_INFO(0); } const int offset = y - 44; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->scroll * this->columns) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * (offset / 42)) { if (x < 35) { return *it; } return ITEM_INFO(0); } ++visible; } } } return ITEM_INFO(0); } // OFFSET: 0x00974290 // FUNCTION: fn_13299 CSkillInfo UISkillListWnd::GetSkillByIndex(int index) { CSkillInfo result(0); int position = 0; for (auto it = this->skills.begin(); it != this->skills.end(); ++it, ++position) { if (index == position) { result = *it; break; } } return result; } // OFFSET: 0x00974320 // FUNCTION: fn_13300 CSkillInfo UISkillListWnd::GetSkillAt(int x, int y) { if (x >= 40 && x < 72 && y > 16 && y < this->visibleRows * 32 + 17) { int visible = 0; int index = 0; for (auto it = this->skills.begin(); it != this->skills.end(); ++it, ++index) { if (index >= this->scroll * this->columns) { if (visible == this->columns * ((y - 17) / 32)) { return *it; } ++visible; } } return CSkillInfo(0); } return CSkillInfo(0); } // OFFSET: 0x00974410 // FUNCTION: fn_13301 CSkillInfo UISkillListWnd::GetVisibleSkill(int row) { int index = 0; for (auto it = this->skills.begin(); it != this->skills.end(); ++it, ++index) { if (row + this->scroll == index) { return *it; } } return CSkillInfo(0); } // OFFSET: 0x00974570 // FUNCTION: fn_13303 bool UIMerchantShopMakeWnd::HasSelection() const { return this->unknown_018A >= 0 && this->unknown_018C >= 0; } // OFFSET: 0x00974590 // FUNCTION: fn_13304 void UIMerchantShopMakeWnd::SendShopRequest() { if (this->mode == 1) { g_modeMgr.GetGameMode()->SendMsg(298, reinterpret_cast(this->unknown_00CC->Text()), std::atoi(this->unknown_0128->Text()), 0, 0); return; } g_modeMgr.GetGameMode()->SendMsg(296, reinterpret_cast(this->unknown_00CC->Text()), 0, 0, 0); } // OFFSET: 0x00974820 // FUNCTION: fn_13306 void UIMerchantShopMakeWnd::AddActionButton() { this->unknown_0168 = new UIBasicButton(*this->m_context, *this->m_controls); this->unknown_0168->Configure(60, LookupMessage(3637)); this->unknown_0168->Move(this->geometry.width - 156, this->geometry.height - 24); this->unknown_0168->SetTooltip(LookupMessage(3638)); this->unknown_0168->SetId(560); this->AddChild(this->unknown_0168); } // OFFSET: 0x00994800 // FUNCTION: fn_13436 void UIMerchantShopMakeWnd::SetSelection(short row, short column) { this->unknown_018A = row; this->unknown_018C = column; } // OFFSET: 0x00995320 // FUNCTION: fn_13444 void UIItemBaseWnd::Slot11() { } // OFFSET: 0x00995330 // FUNCTION: fn_13445 void UIItemPurchaseWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x00995370 // FUNCTION: fn_13446 void UIItemSellWnd2::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x009953B0 // FUNCTION: fn_13447 void UIItemSellWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x009953F0 // FUNCTION: fn_13448 void UIItemShopWnd2::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x00995430 // FUNCTION: fn_13449 void UIItemShopWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x00995470 // FUNCTION: fn_13450 void UIItemStoreFindWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x009954B0 // FUNCTION: fn_13451 void UIItemStoreSubWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x009954F0 // FUNCTION: fn_13452 void UIItemStoreWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; } } // OFFSET: 0x00995530 // FUNCTION: fn_13453 void UIItemWnd::Slot11() { if (this->saved) { this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->unknown_0010 = this->unknown_0110; this->saved->unknown_0014 = this->unknown_010C; this->saved->unknown_0018 = this->unknown_0100; this->saved->unknown_001C = this->unknown_0104; this->saved->unknown_0020 = this->unknown_0108; } } // OFFSET: 0x009955C0 // FUNCTION: fn_13454 void UIMerchantItemMyShopWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00995600 // FUNCTION: fn_13455 void UIMerchantItemPurchaseWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00995640 // FUNCTION: fn_13456 void UIMerchantItemShopWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00995680 // FUNCTION: fn_13457 void UIMerchantItemWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x009956C0 // FUNCTION: fn_13458 void UIMerchantMirrorItemWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00995700 // FUNCTION: fn_13459 void UIMerchantShopMakeWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00995740 // FUNCTION: fn_13460 void UISkillListWnd::Slot11() { if (this->saved) { this->saved->x = this->geometry.x; this->saved->y = this->geometry.y; this->saved->width = this->geometry.width; this->saved->height = this->geometry.height; } } // OFFSET: 0x00994840 // FUNCTION: fn_13437 void UIMerchantShopMakeWnd::SetSuspended(unsigned char suspend) { UIWindow* window = reinterpret_cast(this->mode == 1 ? g_windowMgr.unknown_0410 : g_windowMgr.unknown_02F8); if (!window) { return; } if (suspend == 1) { this->suspended = 1; this->Show(0); window->Show(0); g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(2930)), 0xFFFF, 0, 0, 0); return; } this->suspended = 0; this->Show(1); window->Show(1); this->unknown_018A = -1; this->unknown_018C = -1; } // OFFSET: 0x00994CC0 // FUNCTION: fn_13440 void UIMerchantShopMakeWnd::SetItems(int count, const short* ids) { this->unknown_0188 = 1; UIWindow* window; if (this->mode == 1) { window = reinterpret_cast(g_windowMgr.unknown_0410); } else { reinterpret_cast(&g_session)->SetItems1750(count, ids); window = reinterpret_cast(g_windowMgr.unknown_02F8); } if (window) { window->SendMsg(nullptr, 23, 0, 0, 0, 0); } } // OFFSET: 0x00994B90 // FUNCTION: fn_13439 void UIMerchantItemMyShopWnd::OpenShop() { this->shopOpen = 1; if (!this->actionButton) { this->actionButton = new UIBasicButton(*this->m_context, *this->m_controls); this->actionButton->Configure(42, LookupMessage(2925)); this->actionButton->Move(this->geometry.width - this->actionButton->geometry.width - 66, this->geometry.height - 24); this->actionButton->SetId(506); this->AddChild(this->actionButton); } g_vendingSaleAlarm = false; this->saleAlarm->Show(0); const int previousHeight = this->unknown_011C; this->unknown_011C = 57; this->Resize(this->geometry.width, this->geometry.height - previousHeight + 57); this->SendMsg(nullptr, 14, 7, this->geometry.width, this->geometry.height, 0); this->Invalidate(); } // OFFSET: 0x00994D10 // FUNCTION: fn_13441 void UIItemWnd::ReleaseSelection(unsigned char keep) { if (keep) { return; } for (auto it = this->items.begin(); it != this->items.end(); ++it) { g_session.ClearItemSelection(); it->unknown_0074[1] = 0; } if (UIWindow* window = g_windowMgr.LookupWindow(307)) { window->SendMsg(nullptr, 6, 286, 194, 0, 0); } } // OFFSET: 0x009967F0 // FUNCTION: fn_13469 int ItemTypeSortRank(int type) { switch (type) { case 0: case 1: case 2: return 0; case 18: return 1; case 4: case 11: case 12: case 13: case 14: return 2; case 5: case 8: case 9: case 15: return 3; case 10: case 16: case 17: case 19: return 4; case 6: return 5; case 3: case 7: return 6; default: return 10; } } struct ItemTypeNameLess { bool operator()(const ITEM_INFO& left, const ITEM_INFO& right) const; }; // OFFSET: 0x009700C0 // FUNCTION: fn_13240 bool ItemTypeNameLess::operator()(const ITEM_INFO& left, const ITEM_INFO& right) const { const int leftRank = ItemTypeSortRank(left.unknown_0000[0]); const int rightRank = ItemTypeSortRank(right.unknown_0000[0]); if (leftRank != rightRank) { return leftRank < rightRank; } ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; return naming.DisplayName(left, 0) < naming.DisplayName(right, 0); } extern "C" void sub_96E320(void* head, size_t size, ...); // OFFSET: 0x00996870 // FUNCTION: fn_13470 bool UIItemStoreSubWnd::Sort1() { if (!this->sub_996950()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); return true; } // OFFSET: 0x009968B0 // FUNCTION: fn_13471 bool UIItemStoreSubWnd::Sort2() { if (!this->sub_996AF0()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); return true; } // OFFSET: 0x009968F0 // FUNCTION: fn_13472 bool UIItemStoreSubWnd::Sort3() { if (!this->sub_996C90()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); return true; } // OFFSET: 0x00995CF0 // FUNCTION: fn_13463 bool UIItemStoreSubWnd::SortReversed1() { if (!this->sub_996950()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); this->items.reverse(); return true; } // OFFSET: 0x00995D50 // FUNCTION: fn_13464 bool UIItemStoreSubWnd::SortReversed2() { if (!this->sub_996AF0()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); this->items.reverse(); return true; } // OFFSET: 0x00995DB0 // FUNCTION: fn_13465 bool UIItemStoreSubWnd::SortReversed3() { if (!this->sub_996C90()) { return false; } struct Flag { char val; } flag{0}; void* head = *reinterpret_cast(reinterpret_cast(this) + 0xe8); size_t size = *reinterpret_cast(reinterpret_cast(this) + 0xec); sub_96E320(head, size, flag); this->items.reverse(); return true; } // OFFSET: 0x00996940 // FUNCTION: fn_13473 void UIItemStoreSubWnd::SetTabIndex(int index) { this->tabIndex = index; } // OFFSET: 0x00997080 // FUNCTION: fn_13478 void UIItemStoreWnd::SetTabChecked(int index, bool checked) { this->tabs[index]->SetChecked(checked); } // OFFSET: 0x00997160 // FUNCTION: fn_13481 void UIMerchantItemMyShopWnd::SetDuration(std::uint32_t value) { this->startTick = timeGetTime(); this->duration = value; } // OFFSET: 0x00997180 // FUNCTION: fn_13482 void UIMerchantItemShopWnd::StartTimer(std::uint32_t value) { this->startTick = timeGetTime(); this->duration = value; const int previousHeight = this->unknown_0118; this->unknown_0118 = 57; this->Resize(this->geometry.width, this->geometry.height - previousHeight + 57); this->SendMsg(nullptr, 14, 3, this->geometry.width, this->geometry.height, 0); } // OFFSET: 0x009970A0 // FUNCTION: fn_13479 void UIItemStoreFindWnd::SetTitle(std::string title) { this->title->SetTextFitted(title.c_str()); } // OFFSET: 0x00997100 // FUNCTION: fn_13480 void UIItemStoreSubWnd::SetTitle(std::string title) { this->title->SetTextFitted(title.c_str()); } // OFFSET: 0x009971E0 // FUNCTION: fn_13483 void UIItemStoreFindWnd::SetSearchText(std::string text) { this->searchText = text; } // OFFSET: 0x00971490 // FUNCTION: fn_13263 int UIMerchantShopMakeWnd::CommitPrice(int next) { if (this->editIndex == -1 || g_session.unknown_5C00[1] == 0) { this->editIndex = next; return 1; } UIEditCtrl* edit = this->priceEdits[this->editIndex]; WindowDialogs& dialogs = reinterpret_cast(g_windowMgr); InputFocus focus{g_windowMgr.hoverWindow}; char text[24]; std::sprintf(text, "%s ", edit->Text()); if (!g_session.IsNumberWithCommas(text)) { dialogs.Confirm(LookupMessage(602), 0, true, false, 0, "Message", 280, 120, 0); edit->SetText("0"); focus.Set(edit); edit->SelectAll(); return 0; } std::int64_t price = _atoi64(text); if (price <= 0x7FFFFFFF && price < 0) { price = 0; } else if (price > 0x7FFFFFFF || price > 1000000000) { if (dialogs.Confirm(LookupMessage(2467), 2, true, false, 0, "Message", 280, 120, 0) != 187) { edit->SetText("0"); focus.Set(edit); edit->SelectAll(); return 0; } price = 1000000000; edit->SetText(_itoa(1000000000, text, 10)); this->Invalidate(); } if (price >= std::atoi(LookupMessage(2476))) { ITEM_INFO item = g_session.GetItem1768At(this->editIndex); char name[128]; int capacity = 128; ItemDescriptions descriptions{g_itemDescriptions}; descriptions.Name(item, name, capacity, 0); std::string message = FormatOwnedString(LookupMessage(2473), name); const int high = static_cast(price / std::atoi(LookupMessage(2474))); if (high > 0) { message += FormatOwnedString(LookupMessage(2475), high); } const int low = static_cast(price % std::atoi(LookupMessage(2474))) / std::atoi(LookupMessage(2476)); if (low > 0) { message += FormatOwnedString(LookupMessage(2477), low); } message += std::string(LookupMessage(2478)); if (dialogs.Confirm(message.c_str(), 2, true, false, 0, "Message", 280, 120, 0) != 187) { edit->SetText("0"); focus.Set(edit); edit->SelectAll(); return 0; } } const PriceColors colors = PriceColor(price); edit->TextColor(colors.primary, colors.secondary); FormatGroupedInteger(price, text, sizeof(text)); edit->SetText(text); this->editIndex = next; if (next == -1) { focus.Set(nullptr); return 1; } this->priceEdits[next]->TextColor(0, 0xFFFFFFFF); focus.Set(this->priceEdits[next]); this->priceEdits[next]->SelectAll(); return 1; } // OFFSET: 0x009719C0 // FUNCTION: fn_13264 void UIMerchantShopMakeWnd::PrintBuyList() { auto it = this->items.begin(); char line[256]; char name[256]; char text[24]; char price[32]; char quantity[32]; char grouped[32]; std::sprintf(line, "====================== BUY LIST ======================"); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x96FFFF, 0, 0, 0); for (unsigned index = 0; index < this->items.size(); ++index, ++it) { int capacity = 256; ItemDescriptions descriptions{g_itemDescriptions}; descriptions.Name(*it, name, capacity, 0); std::sprintf(text, "%s ", this->priceEdits[index]->Text()); g_session.IsNumberWithCommas(text); if (std::atoi(text) > 99990000) { std::sprintf(price, "99,990,000"); } else { std::sprintf(price, "%s", FormatGroupedInteger(std::atoi(text), grouped, 32)); } const double rate = PriceCommission(_atoi64(text)) * 0.01; const std::int64_t commission = static_cast(_atoi64(text) * rate); std::sprintf(text, "%s ", this->quantityEdits[index]->Text()); g_session.IsNumberWithCommas(text); if (std::atoi(text) > 9999) { std::sprintf(quantity, "9,999"); } else { std::sprintf(quantity, "%s", FormatGroupedInteger(std::atoi(text), grouped, 32)); } std::sprintf(line, LookupMessage(1732), name, price, quantity); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x5AFFFF, 0, 0, 0); const std::string notice = FormatOwnedString("Commission : 1 EA = %s Zeny", FormatGroupedInteger(commission, line, 256)); g_windowMgr.SendNotice(1, reinterpret_cast(notice.c_str()), 0x5AFFFF, 0, 0, 0); } std::sprintf(price, "%s", FormatGroupedInteger(g_session.m_zeny, grouped, 32)); std::sprintf(line, " Current Zeny : %s Z", price); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x78FFFF, 0, 0, 0); std::sprintf(line, "============================ ============================"); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x96FFFF, 0, 0, 0); } // OFFSET: 0x00972100 // FUNCTION: fn_13266 void UIItemBaseWnd::Slot10(int, int, std::intptr_t) { g_modeMgr.gameMode->SendMsg(18, 0, 0, 0, 0); } // OFFSET: 0x00972120 // FUNCTION: fn_13267 void UIItemPurchaseWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 3) { mode->SendMsg(18, 0, 0, 0, 0); return; } switch (drag->type) { case 4: case 5: case 8: case 9: case 11: case 12: case 13: case 14: case 15: this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; default: reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 1, 0, 0, 0); return; } } // OFFSET: 0x009721F0 // FUNCTION: fn_13268 void UIItemSellWnd2::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 3) { mode->SendMsg(18, 0, 0, 0, 0); return; } if (drag->quantity == 1 || g_windowMgr.unknown_0064 != 0) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 16, 0, 0, 0); } // OFFSET: 0x009722A0 // FUNCTION: fn_13269 void UIItemSellWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 3) { mode->SendMsg(18, 0, 0, 0, 0); return; } if (drag->quantity == 1 || g_windowMgr.unknown_0064 != 0) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 2, 0, 0, 0); } // OFFSET: 0x00972B50 // FUNCTION: fn_13277 void UIMerchantItemShopWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 13) { g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); return; } if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 11, 0, 0, 0); } // OFFSET: 0x00972C00 // FUNCTION: fn_13278 void UIMerchantItemWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011) || g_windowMgr.unknown_01F0 || g_windowMgr.unknown_01F8) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source != 1 && drag->source != 6) { mode->SendMsg(18, 0, 0, 0, 0); return; } if (static_cast(mode)->ConfirmDraggedItemUse()) { return; } if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 8, 0, 0, 0); } // OFFSET: 0x0097BC00 // FUNCTION: fn_13321 void UIMerchantItemShopWnd::Slot15(int width, int height) { if (this->unknown_010C) { this->notice = new UIStaticText(*this->m_context, *this->m_controls); this->notice->SetSize(160, 15); char text[80]; std::sprintf(text, LookupMessage(1735), 0); this->notice->SetTextAutoWidth(text); this->notice->Move(12, this->geometry.height - 21); this->AddChild(this->notice); } const unsigned rows = static_cast(height - this->unknown_0118 - 17) / 32; this->visibleRows = rows; this->columns = 1; this->unknown_00F0 = this->geometry.height - rows * 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x00854130 // FUNCTION: fn_10746 int UIEditCtrl3::DecodeLinkNumber(std::string text) { char digits[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; const int length = static_cast(text.size()); int value = 0; char* characters = new char[length + 1]; strcpy_s(characters, length + 1, text.c_str()); for (int position = 0; position < length; ++position) { for (int digit = 0; digit < 62; ++digit) { if (characters[position] != digits[digit]) { continue; } int weight = 1; for (int power = 1; power < length - position; ++power) { weight *= 62; } value += weight * digit; break; } } if (characters) { delete[] characters; } return value; } // OFFSET: 0x008603D0 // FUNCTION: fn_10899 void UIEditCtrl3::DecodeLinkOptions(std::vector& options, const char* text, int& position, const int& length, const char& separator, const char& alternate) { std::string value; while (++position < length + 1) { const char byte = text[position]; if (byte >= '0') { value += byte; } else if (separator != byte && alternate != byte) { --position; options.push_back(this->DecodeLinkNumber(std::move(value))); break; } else { options.push_back(this->DecodeLinkNumber(std::move(value))); value.clear(); } } } // OFFSET: 0x00860790 // FUNCTION: fn_10900 int UIEditCtrl3::DecodeLinkCards(std::vector& fields, const char* text, int& position, const char& separator, const int& length, int index) { std::string value; std::vector cards; int count = 1; while (++position < length + 1) { const char byte = text[position]; if (byte >= '0') { value += byte; } else if (separator == byte) { ++count; cards.push_back(this->DecodeLinkNumber(std::move(value))); value.clear(); } else { --position; cards.push_back(this->DecodeLinkNumber(std::move(value))); fields[index] = count; for (unsigned int i = 0; i < cards.size(); ++i) { fields[index + 1 + i] = cards[i]; } break; } } return count; } // OFFSET: 0x00975CD0 // FUNCTION: fn_13310 void UIItemSellWnd2::Slot15(int width, int height) { this->total = new UIStaticText(*this->m_context, *this->m_controls); this->total->SetSize(160, 15); this->total->SetTextAutoWidth(""); this->total->Move(12, this->geometry.height - 21); this->AddChild(this->total); UIStaticText* title = new UIStaticText(*this->m_context, *this->m_controls); title->SetSize(90, 15); title->SetText(LookupMessage(1569), 0); title->Move(16, 2); title->shadow = 1; this->AddChild(title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(3); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->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(this->scrollBar); const std::string prefix("유저인터페이스\\"); const char* names[2][3] = {{"btn_exchange", "btn_exchange_a", "btn_exchange_b"}, {"btn_cancel", "btn_cancel_a", "btn_cancel_b"}}; int positions[2][2] = {{this->geometry.width - 106, this->geometry.height - 24}, {this->geometry.width - 61, this->geometry.height - 24}}; int ids[2] = {184, 185}; for (int index = 0; index < 2; ++index) { this->buttons[index] = new UIBitmapButton(*this->m_context, *this->m_controls); UIBitmapButton* button = static_cast(this->buttons[index]); 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); this->buttons[index]->SetSize(button->BitmapWidth(), button->BitmapHeight()); this->buttons[index]->Move(positions[index][0], positions[index][1]); this->buttons[index]->SetId(ids[index]); this->AddChild(this->buttons[index]); } this->columns = 1; this->visibleRows = (height - 38) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x009768A0 // FUNCTION: fn_13311 void UIItemSellWnd::Slot15(int width, int height) { this->total = new UIStaticText(*this->m_context, *this->m_controls); this->total->SetSize(160, 15); char text[80]; std::sprintf(text, "Total : %d Zeny", 0); this->total->SetTextAutoWidth(text); this->total->Move(12, this->geometry.height - 21); this->AddChild(this->total); UIStaticText* title = new UIStaticText(*this->m_context, *this->m_controls); title->SetSize(90, 15); title->SetText(LookupMessage(168), 0); title->Move(16, 2); title->shadow = 1; this->AddChild(title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(3); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->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(this->scrollBar); const std::string prefix("유저인터페이스\\"); const char* names[2][3] = {{"btn_sell", "btn_sell_a", "btn_sell_b"}, {"btn_cancel", "btn_cancel_a", "btn_cancel_b"}}; int positions[2][2] = {{this->geometry.width - 106, this->geometry.height - 24}, {this->geometry.width - 61, this->geometry.height - 24}}; int ids[2] = {184, 185}; for (int index = 0; index < 2; ++index) { this->buttons[index] = new UIBitmapButton(*this->m_context, *this->m_controls); UIBitmapButton* button = static_cast(this->buttons[index]); 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); this->buttons[index]->SetSize(button->BitmapWidth(), button->BitmapHeight()); this->buttons[index]->Move(positions[index][0], positions[index][1]); this->buttons[index]->SetId(ids[index]); this->AddChild(this->buttons[index]); } this->columns = 1; this->visibleRows = (height - 38) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x00977510 // FUNCTION: fn_13312 void UIItemShopWnd2::Slot15(int width, int height) { this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(70, 15); this->title->SetText(LookupMessage(167), 0); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(7); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->resizer); this->checkBox = new UICheckBox(*this->m_context, *this->m_controls); this->checkBox->SetSize(200, 12); this->checkBox->SetImages("유저인터페이스\\checkbox_1.bmp", "유저인터페이스\\checkbox_0.bmp", LookupMessage(295)); this->checkBox->Move(12, this->geometry.height - 20); this->checkBox->SetChecked(g_windowMgr.unknown_0064); this->AddChild(this->checkBox); UIScrollBar* scrollBar = new UIScrollBar(*this->m_context); this->scrollBar = scrollBar; scrollBar->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - this->unknown_0108 - this->unknown_0104 - 17); this->AddChild(this->scrollBar); this->columns = 1; this->visibleRows = (height - this->unknown_0108 - this->unknown_0104 - 17) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x009777B0 // FUNCTION: fn_13313 void UIItemShopWnd::Slot15(int width, int height) { this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(70, 15); this->title->SetText(LookupMessage(167), 0); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(7); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->resizer); this->checkBox = new UICheckBox(*this->m_context, *this->m_controls); this->checkBox->SetSize(200, 12); this->checkBox->SetImages("유저인터페이스\\checkbox_1.bmp", "유저인터페이스\\checkbox_0.bmp", LookupMessage(295)); this->checkBox->Move(12, this->geometry.height - 20); this->checkBox->SetChecked(g_windowMgr.unknown_0064); this->AddChild(this->checkBox); UIScrollBar* scrollBar = new UIScrollBar(*this->m_context); this->scrollBar = scrollBar; scrollBar->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - this->unknown_0108 - this->unknown_0104 - 17); this->AddChild(this->scrollBar); this->columns = 1; this->visibleRows = (height - this->unknown_0108 - this->unknown_0104 - 17) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x00977A50 // FUNCTION: fn_13314 void UIItemStoreFindWnd::Slot15(int width, int height) { this->scrollBar = new UIScrollBar(*this->m_context); static_cast(this->scrollBar)->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - 38); this->AddChild(this->scrollBar); char text[64]; std::sprintf(text, "서브창고"); this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(this->geometry.width - 32, 15); this->title->SetTextFitted(text); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->resizeHandle = new UIResizer(*this->m_context); this->resizeHandle->SetSize(16, 16); this->resizeHandle->SetDirection(7); this->resizeHandle->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizeHandle->Move(this->geometry.width - 15, this->geometry.height - 15); this->resizeHandle->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->resizeHandle); this->closeButton = this->AddCloseButton(*this->m_controls, "", 0); this->closeButton->Move(width - 16, 3); } // OFFSET: 0x00977C40 // FUNCTION: fn_13315 void UIItemStoreSubWnd::Slot15(int width, int height) { this->scrollBar = new UIScrollBar(*this->m_context); static_cast(this->scrollBar)->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - 38); this->AddChild(this->scrollBar); char text[64]; std::sprintf(text, "서브창고"); this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(this->geometry.width - 32, 15); this->title->SetTextFitted(text); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->resizeHandle = new UIResizer(*this->m_context); this->resizeHandle->SetSize(16, 16); this->resizeHandle->SetDirection(7); this->resizeHandle->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizeHandle->Move(this->geometry.width - 15, this->geometry.height - 15); this->resizeHandle->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->resizeHandle); } // OFFSET: 0x0097BD30 // FUNCTION: fn_13322 void UIMerchantItemWnd::Slot15(int width, int height) { UIStaticText* title = new UIStaticText(*this->m_context, *this->m_controls); title->SetSize(90, 15); title->SetText(LookupMessage(222), 0); title->Move(16, 2); title->shadow = 1; this->AddChild(title); this->info = new UIStaticText(*this->m_context, *this->m_controls); this->info->SetSize(220, 15); char text[128]; std::sprintf(text, "Num: %d/%d Weight: %d/%d", g_session.cartCount, g_session.cartMaxCount, g_session.cartWeight, g_session.cartMaxWeight); this->info->SetText(text, 0); this->info->Move(16, this->geometry.height - 19); this->AddChild(this->info); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(7); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->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(this->scrollBar); this->closeButton = this->AddCloseButton(*this->m_controls, "Alt+W", 0); this->columns = (width - 40) / 32; this->visibleRows = (height - 38) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); this->info->Show(0); } // OFFSET: 0x0097BFF0 // FUNCTION: fn_13323 void UIMerchantMirrorItemWnd::Slot15(int width, int height) { UIStaticText* title = new UIStaticText(*this->m_context, *this->m_controls); title->SetSize(150, 15); int messageId; if (this->unknown_00F4 == 1) { messageId = 1733; } else if (this->unknown_00F4 == 2) { messageId = 1738; } else { messageId = 232; } title->SetText(LookupMessage(messageId), 0); title->Move(16, 2); title->shadow = 1; this->AddChild(title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(7); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->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(this->scrollBar); this->columns = (width - 40) / 32; this->visibleRows = (height - 38) / 32; if (this->unknown_00F4 == 1) { g_session.CollectItems1750(); } else if (this->unknown_00F4 == 2) { g_session.RefreshItems1750(); } else if (Replay::Instance().state != 6) { reinterpret_cast(&g_session)->CopyItems1740To1750(); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x0098A7A0 // FUNCTION: fn_13417 void UISkillListWnd::UpdateRowButtons() { for (int row = 0, y = 34; y < 258; ++row, y += 32) { CSkillInfo skill = this->GetVisibleSkill(row); int points = 0; if (this->skillTab == 0) { points = reinterpret_cast(g_session.unknown_1664)[0]; } else if (this->skillTab == 1) { points = reinterpret_cast(g_session.unknown_1664)[1]; } if (row < this->visibleRows && this->scroll + row < this->skills.size() && points != 0 && skill.available != 0 && skill.unknown_0018 != 0) { this->upgradeButtons[row]->Move(78, y - 13); } else { this->upgradeButtons[row]->Move(-200, y - 17); } if (row < this->visibleRows && this->scroll + row < this->skills.size() && skill.available != 0 && skill.level != 0 && CSkillInfo::UsesLevel(*g_session.m_hotkeyScript, static_cast(skill.id))) { this->levelButtons[row]->Move(112, y); this->levelLabels[row]->Move(192, y); } else { this->levelButtons[row]->Move(-200, y); this->levelLabels[row]->Move(-200, y); } } } struct ThreadFormatBuffer { char text[0x800]; }; // OFFSET: 0x00974630 // FUNCTION: fn_13305 const char* FormatThreadText(const char* format, ...) { // GLOBAL: gl_25164 static std::map buffers; char* buffer = buffers[reinterpret_cast(GetCurrentThread())].text; va_list arguments; va_start(arguments, format); _vsnprintf(buffer, 0x800, format, arguments); va_end(arguments); return buffer; } // OFFSET: 0x00994D80 // FUNCTION: fn_13442 bool __stdcall ReturnTrue(int) { return true; } // OFFSET: 0x0089CAE0 // FUNCTION: fn_11591 void UIEditCtrl_Custom::Trim() { const auto length = this->text.size(); if (static_cast(length) <= this->maximum) { return; } const auto codePage = static_cast(g_textCodePage); const char* next = CharNextExA(codePage, this->text.c_str(), 0); while (length - std::strlen(next) <= static_cast(this->maximum)) { next = CharNextExA(codePage, next, 0); } const char* previous = CharPrevExA(codePage, this->text.c_str(), next, 0); this->text.resize(length - std::strlen(previous)); CLanguage& input = this->m_edit->input; input.ResetInput(); input.ResetInput(); input.Insert(this->text.c_str()); while (this->text.size() < static_cast(this->maximum)) { this->text.append(" ", 1); } } // OFFSET: 0x00972350 // FUNCTION: fn_13270 void UIItemShopWnd2::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } const ModeDragState* drag = reinterpret_cast(value); switch (drag->source) { case 4: case 5: if (this->unknown_00F8 == 0) { return; } if (drag->quantity == 1 || g_windowMgr.unknown_0064 != 0) { this->SendMsg(nullptr, 38, 1, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 15, 0, 0, 0); return; default: g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); return; } } // OFFSET: 0x00972410 // FUNCTION: fn_13271 void UIItemShopWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } const ModeDragState* drag = reinterpret_cast(value); switch (drag->source) { case 4: if (this->unknown_00F8 != 0) { return; } if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 3, 0, 0, 0); return; case 5: if (this->unknown_00F8 == 0) { return; } if (drag->quantity == 1 || g_windowMgr.unknown_0064 != 0) { this->SendMsg(nullptr, 38, 1, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 4, 0, 0, 0); return; default: g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); return; } } // OFFSET: 0x009729C0 // FUNCTION: fn_13276 void UIMerchantItemPurchaseWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); if (drag->source == 12) { switch (drag->type) { case 4: case 5: case 8: case 9: case 11: case 12: case 13: case 14: case 15: if (g_session.GetItem1760Quantity(drag->id)) { mode->SendMsg(18, 0, 0, 0, 0); g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(119)), 0xFF, 0, 0, 0); return; } this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; default: reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 12, 0, 0, 0); return; } } if (drag->source == 22) { if (drag->quantity > 1) { reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 17, 0, 0, 0); return; } this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } mode->SendMsg(18, 0, 0, 0, 0); } // OFFSET: 0x00972CE0 // FUNCTION: fn_13279 void UIMerchantMirrorItemWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } CMode* mode = g_modeMgr.GetGameMode(); const ModeDragState* drag = reinterpret_cast(value); switch (drag->source) { case 10: case 21: if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); if (this->unknown_00F4 == 2) { g_windowMgr.window_01EC->SendMsg(nullptr, 13, 18, 0, 0, 0); return; } g_windowMgr.window_01EC->SendMsg(nullptr, 13, 10, 0, 0, 0); return; case 19: this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; default: mode->SendMsg(18, 0, 0, 0, 0); return; } } // OFFSET: 0x00972DB0 // FUNCTION: fn_13280 void UIMerchantShopMakeWnd::Slot10(int x, int y, std::intptr_t value) { if (g_windowMgr.LookupWindow(10011)) { UIWindow::Slot10(x, y, value); return; } const ModeDragState* drag = reinterpret_cast(value); switch (drag->source) { case 11: if (drag->quantity == 1) { this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; } reinterpret_cast(g_windowMgr).Show(15, 1); g_windowMgr.window_01EC->SendMsg(nullptr, 13, 9, 0, 0, 0); return; case 20: this->SendMsg(nullptr, 38, 0, 0, 0, 0); return; default: g_modeMgr.GetGameMode()->SendMsg(18, 0, 0, 0, 0); return; } } // OFFSET: 0x00972E60 // FUNCTION: fn_13281 std::vector* sub_972E60(std::vector* result) { new (result) std::vector(); const auto first = BuildReplayTaggedRecord(0x50DC, nullptr, 0); result->insert(result->end(), first.begin(), first.end()); const auto second = BuildReplayTaggedRecord(0x50DD, nullptr, 0); result->insert(result->end(), second.begin(), second.end()); return result; } // OFFSET: 0x00972F50 // FUNCTION: fn_13282 std::vector UIItemSellWnd2::BuildReplayRecords() { std::vector records; { const auto record = BuildReplayTaggedRecord(20800, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(20802, &this->unknown_00FC, 4); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(20801, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } return records; } // OFFSET: 0x00973080 // FUNCTION: fn_13283 std::vector* sub_973080(std::vector* result) { new (result) std::vector(); const auto first = BuildReplayTaggedRecord(0x510E, nullptr, 0); result->insert(result->end(), first.begin(), first.end()); const auto second = BuildReplayTaggedRecord(0x510F, nullptr, 0); result->insert(result->end(), second.begin(), second.end()); return result; } // OFFSET: 0x00973170 // FUNCTION: fn_13284 std::vector* sub_973170(std::vector* result) { new (result) std::vector(); const auto first = BuildReplayTaggedRecord(0x51A4, nullptr, 0); result->insert(result->end(), first.begin(), first.end()); const auto second = BuildReplayTaggedRecord(0x51A5, nullptr, 0); result->insert(result->end(), second.begin(), second.end()); return result; } // OFFSET: 0x00973260 // FUNCTION: fn_13285 std::vector UIItemShopWnd::BuildReplayRecords() { std::vector records; if (this->hovered != 0) { { const auto record = BuildReplayTaggedRecord(21050, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21051, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } else { { const auto record = BuildReplayTaggedRecord(21000, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21001, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } return records; } // OFFSET: 0x009733A0 // FUNCTION: fn_13286 std::vector UIParaItemShopWnd::BuildReplayRecords() { std::vector records; if (this->unknown_0108 != 0) { { const auto record = BuildReplayTaggedRecord(21100, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21101, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } else { { const auto record = BuildReplayTaggedRecord(21150, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21151, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } return records; } // OFFSET: 0x009734E0 // FUNCTION: fn_13287 std::vector UIMerchantItemShopWnd::BuildReplayRecords() { std::vector records; if (this->unknown_010C != 0) { { const auto record = BuildReplayTaggedRecord(21250, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21253, &this->unknown_0108, 4); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21251, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } else { { const auto record = BuildReplayTaggedRecord(21200, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21201, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } return records; } // OFFSET: 0x00973670 // FUNCTION: fn_13288 std::vector* sub_973670(std::vector* result) { new (result) std::vector(); const auto first = BuildReplayTaggedRecord(0x5398, nullptr, 0); result->insert(result->end(), first.begin(), first.end()); const auto second = BuildReplayTaggedRecord(0x5399, nullptr, 0); result->insert(result->end(), second.begin(), second.end()); return result; } // OFFSET: 0x00973760 // FUNCTION: fn_13289 std::vector UIMerchantShopMakeWnd::BuildReplayRecords() { std::vector records; if (this->mode != 0) { { const auto record = BuildReplayTaggedRecord(21350, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21351, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } else { { const auto record = BuildReplayTaggedRecord(21300, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } { const auto record = BuildReplayTaggedRecord(21301, nullptr, 0); records.insert(records.end(), record.begin(), record.end()); } } return records; } // OFFSET: 0x009738A0 // FUNCTION: fn_13290 int UIItemBaseWnd::GetItemIndexAt(int x, int y) { if (x < 40 || y < 17 || y >= this->visibleRows * 32 + 17) { return -1; } int column = (x - 40) / 32; const int row = (y - 17) / 32; if (column > this->columns - 1) { column = this->columns - 1; } int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index >= this->scroll * this->columns) { if (!g_session.IsPetEgg(std::atoi(it->itemId.c_str())) || !it->unknown_005D) { if (visible == this->columns * row + column) { return index; } ++visible; } } } return -1; } // OFFSET: 0x00984050 // FUNCTION: fn_13349 void UIItemShopWnd2::Slot26(int x, int y) { if (this->unknown_00F8 == 0 || g_windowMgr.unknown_0064 == 0) { return; } UIWindow* target = reinterpret_cast(g_windowMgr.unknown_0260); if (target) { this->Slot25(x, y); CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); this->m_recorder->RecordDrop(x, y, mode->drag, 161); target->Slot10(x, y, reinterpret_cast(&mode->drag)); } } // OFFSET: 0x009840C0 // FUNCTION: fn_13350 void UIItemShopWnd::Slot26(int x, int y) { if (this->unknown_00F8 == 0 || g_windowMgr.unknown_0064 == 0) { return; } UIWindow* target = reinterpret_cast(g_windowMgr.unknown_025C); if (target) { this->Slot25(x, y); CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); this->m_recorder->RecordDrop(x, y, mode->drag, 24); target->Slot10(x, y, reinterpret_cast(&mode->drag)); } } // OFFSET: 0x00985AA0 // FUNCTION: fn_13370 void UISkillListWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); return; } const int previous = this->hovered; this->hovered = this->SkillAt(x, y); if (previous != this->hovered) { this->Invalidate(); } CSkillInfo skill = this->GetSkillAt(x, y); if (skill.available && skill.level && skill.unknown_000C) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (mode) { mode->drag.BeginSkill( reinterpret_cast(g_windowMgr), ResourceMgr::Instance(), 8, skill.id, skill.name, reinterpret_cast(&g_session)->SkillLevel(skill.id), -1 ); } } } // OFFSET: 0x009844E0 // FUNCTION: fn_13354 void UISkillListWnd::Slot26(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); return; } if (this->hovered != -1) { CSkillInfo skill = this->GetSkillByIndex(this->hovered); if (skill.available && skill.level && skill.unknown_0014) { this->SendMsg(nullptr, 58, reinterpret_cast(&skill), 0, 0, 0); } } } // OFFSET: 0x00985510 // FUNCTION: fn_13366 void UIMerchantItemShopWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } if (this->unknown_010C == 0) { const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { ItemDescriptions descriptions{g_itemDescriptions}; static_cast(g_modeMgr.GetGameMode())->drag.BeginItem(this->m_frameContext->windows, descriptions, 12, item, 1, -1); } } } // OFFSET: 0x00988C60 // FUNCTION: fn_13391 void UIItemPurchaseWnd::Slot32(int x, int y) { const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { g_modeMgr.GetGameMode(); this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x00988F90 // FUNCTION: fn_13395 void UIItemShopWnd::Slot32(int x, int y) { const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { g_modeMgr.GetGameMode(); this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 0, 0, 0); } } // OFFSET: 0x0098A260 // FUNCTION: fn_13409 void UIItemBaseWnd::Slot35(int value) { if (this->unknown_00E4) { int step = this->visibleRows - 1; if (step > 3) { step = 3; } this->SendMsg(this->scrollBar, 7, value < 0 ? step : -step, 0, 0, 0); } } // OFFSET: 0x0098A3A0 // FUNCTION: fn_13413 void UISkillListWnd::Slot35(int value) { if (this->unknown_0128) { int step = this->visibleRows - 1; if (step > 3) { step = 3; } this->SendMsg(this->scrollBar, 7, value < 0 ? step : -step, 0, 0, 0); } } // OFFSET: 0x0098A6F0 // FUNCTION: fn_13416 void UISkillListWnd::UpdateScrollBar() { UIScrollBar* bar = static_cast(this->scrollBar); if (!bar) { return; } const int visible = this->visibleRows; const int rows = (this->skills.size() % this->columns != 0) + this->skills.size() / this->columns; int overflow = rows - visible; if (overflow < 0) { overflow = 0; } this->unknown_0128 = overflow != 0; if (overflow != 0) { bar->SetRange(overflow, visible, rows); int position = this->scroll; if (position < 0) { this->scroll = 0; position = 0; } const int last = rows - this->visibleRows; if (position > last) { this->scroll = last; position = last; } static_cast(this->scrollBar)->SetPosition(position); } else { this->scroll = 0; bar->SetRange(0, visible, rows); } this->scrollBar->Invalidate(); } // OFFSET: 0x0098A3F0 // FUNCTION: fn_13414 void UIMerchantShopMakeWnd::UpdateLayout() { if (!this->scrollBar) { return; } const int top = this->unknown_0154 - this->unknown_0140 * 42; int rows = (g_renderer->viewport.height - top) / 42; this->unknown_0158 = rows; if (rows > this->unknown_012C) { this->unknown_0158 = this->unknown_012C; rows = this->unknown_012C; } const int count = static_cast(this->items.size()); if (count >= this->unknown_0140) { UIScrollBar* bar = static_cast(this->scrollBar); if (count > rows) { this->unknown_0144 = 1; bar->SetRange(count - rows, rows, count); int position = this->scroll; if (position < 0) { this->scroll = 0; position = 0; } const int last = count - this->unknown_0158; if (position > last) { this->scroll = last; position = last; } static_cast(this->scrollBar)->SetPosition(position); } else { this->unknown_0144 = 0; this->scroll = 0; bar->SetRange(0, rows, count); rows = count; } this->Resize(this->geometry.width, rows * 42 + top); if (this->mode == 0) { this->notice->Move(12, this->geometry.height - 20); } for (UIWindow* button : this->actionButtons) { button->Move(button->geometry.x, this->geometry.height - 24); } if (this->unknown_0168) { this->unknown_0168->Move(this->unknown_0168->geometry.x, this->geometry.height - 24); } this->scrollBar->Resize(1, this->geometry.height - 58); } int visible = (this->geometry.height - top) / 42; if (visible < this->unknown_0140) { visible = this->unknown_0140; } this->visibleRows = visible; this->scrollBar->Invalidate(); } // OFFSET: 0x0098A2B0 // FUNCTION: fn_13410 void UIItemStoreFindWnd::Slot35(int value) { if (this->unknown_00E4) { int step = this->visibleRows - 1; if (step > 3) { step = 3; } this->SendMsg(this->scrollBar, 7, value < 0 ? step : -step, 0, 0, 0); } } // OFFSET: 0x0098A300 // FUNCTION: fn_13411 void UIItemStoreSubWnd::Slot35(int value) { if (this->unknown_00E4) { int step = this->visibleRows - 1; if (step > 3) { step = 3; } this->SendMsg(this->scrollBar, 7, value < 0 ? step : -step, 0, 0, 0); } } // OFFSET: 0x0098A350 // FUNCTION: fn_13412 void UIMerchantShopMakeWnd::Slot35(int value) { if (this->unknown_0144) { int step = this->unknown_0140 - 1; if (step > 3) { step = 3; } this->SendMsg(this->scrollBar, 7, value < 0 ? step : -step, 0, 0, 0); } } // OFFSET: 0x0098A5A0 // FUNCTION: fn_13415 void UIItemBaseWnd::UpdateScrollBar() { UIScrollBar* bar = static_cast(this->scrollBar); if (!bar) { return; } const int visible = this->visibleRows; const int rows = (this->items.size() % this->columns != 0) + this->items.size() / this->columns; int overflow = rows - visible; if (overflow < 0) { overflow = 0; } this->unknown_00E4 = overflow != 0; if (overflow != 0) { bar->SetRange(overflow, visible, rows); int position = this->scroll; if (position < 0) { this->scroll = 0; position = 0; } const int last = rows - this->visibleRows; if (position > last) { this->scroll = last; position = last; } static_cast(this->scrollBar)->SetPosition(position); } else { this->scroll = 0; bar->SetRange(0, visible, rows); } this->scrollBar->Invalidate(); } // OFFSET: 0x0098A920 // FUNCTION: fn_13418 int UIItemBaseWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { switch (message) { case 3: if (this->unknown_00E4 == 1) { this->SendMsg(this->scrollBar, 7, -this->visibleRows, 0, 0, 0); } break; case 4: if (this->unknown_00E4 == 1) { this->SendMsg(this->scrollBar, 7, this->visibleRows, 0, 0, 0); return 0; } break; case 6: case 23: break; case 7: case 9: case 10: { const int previous = this->scroll; if (message == 9) { this->scroll = previous - this->visibleRows + 1; } else if (message == 10) { this->scroll = this->visibleRows - 1 + previous; } else { this->scroll = a + previous; } if (previous != this->scroll) { this->UpdateScrollBar(); this->Invalidate(); } return this->scroll - previous; } case 14: if (a == 7) { int width = b <= 320 ? b : 320; int height = c <= 240 ? c : 240; if (width < 232) { width = 232; } if (height < 102) { height = 102; } const int rowsHeight = (height - 38) / 32 * 32; const int columnsWidth = (width - 280) / 32 * 32; const int newWidth = columnsWidth + 280; const int newHeight = rowsHeight + 38; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = (newWidth - 40) / 32; this->visibleRows = rowsHeight / 32; this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); this->scrollBar->Move(this->geometry.width - 15, 17); this->scrollBar->Resize(this->scrollBar->geometry.width, this->geometry.height - 38); this->UpdateScrollBar(); } this->m_frameContext->snapping.Store(this); return 0; } break; default: return UIFrameWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x00991880 // FUNCTION: fn_13431 int UIMerchantItemWnd::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: if (a == 201) { g_windowMgr.CloseWindow(40); return 0; } break; case 14: if (a == 7) { int width = b <= 320 ? b : 320; int height = c <= 240 ? c : 240; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = (newWidth - 40) / 32; this->visibleRows = (newHeight - 38) / 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, this->geometry.height - 38); this->UpdateScrollBar(); } this->info->Move(16, this->geometry.height - 19); this->closeButton->Move(this->geometry.width - 14, 3); this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { this->items.erase(this->items.begin(), this->items.end()); const int size = reinterpret_cast(&g_session)->GetList6Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1740At(i); if (item.unknown_0000[1] != 0) { this->items.push_back(item); } } this->Invalidate(); this->UpdateScrollBar(); return 0; } case 34: this->saved = reinterpret_cast(a); 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->drag.source == 1) { mode->SendMsg(76, mode->drag.id, mode->drag.quantity, 0, 0); } else if (mode->drag.source == 6) { mode->SendMsg(78, mode->drag.id, mode->drag.quantity, 0, 0); } mode->SendMsg(18, 0, 0, 0, 0); return 0; } case 55: { char text[128]; std::sprintf(text, "Num: %d/%d Weight: %d/%d", g_session.cartCount, g_session.cartMaxCount, g_session.cartWeight, g_session.cartMaxWeight); this->info->SetText(text, 0); this->Invalidate(); break; } default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x00991C40 // FUNCTION: fn_13432 int UIMerchantMirrorItemWnd::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: break; case 14: if (a == 7) { int width = b <= 320 ? b : 320; int height = c <= 240 ? c : 240; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = (newWidth - 40) / 32; this->visibleRows = (newHeight - 38) / 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, this->geometry.height - 38); this->UpdateScrollBar(); } this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { this->items.erase(this->items.begin(), this->items.end()); const int size = reinterpret_cast(&g_session)->GetList8Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1750At(i); if (item.unknown_0000[1] != 0) { this->items.push_back(item); } } this->Invalidate(); this->UpdateScrollBar(); return 0; } case 34: this->saved = reinterpret_cast(a); 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()); ModeDragState& drag = mode->drag; ITEM_INFO item; item.Assign(reinterpret_cast(drag)); ClientItemLists* lists = reinterpret_cast(&g_session); switch (drag.source) { case 10: if (g_session.GetItem1768Quantity(drag.id)) { lists->AddItem1750(item, 0, 1); lists->RemoveItem1768(item, 0); } break; case 19: if (lists->AddItem1750(item, this->unknown_00F4, 1)) { lists->RemoveItem1768(item, this->unknown_00F4 != 0); } break; case 21: lists->AddItem1750(item, this->unknown_00F4, 1); lists->RemoveItem1760(item); if (g_windowMgr.unknown_041C) { reinterpret_cast(g_windowMgr.unknown_041C)->SendMsg(nullptr, 23, 0, 0, 0, 0); } break; } mode->SendMsg(18, 0, 0, 0, 0); return 0; } case 123: { const auto* bytes = reinterpret_cast(a); ItemListChunkHeader header = *reinterpret_cast(bytes); unsigned offset = 6; if (header.type == 21400) { while (static_cast(b) > offset) { header = *reinterpret_cast(bytes + offset); offset += 6; if (header.type == 21401) { this->SendMsg(nullptr, 23, 0, 0, 0, 0); break; } offset += header.size; } } break; } default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x0098C5A0 // FUNCTION: fn_13421 int UIItemSellWnd2::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: { const int count = reinterpret_cast(&g_session)->GetList4Size(); CMode* mode = g_modeMgr.gameMode; if (a == 184) { if (count > 0) { WindowDialogs& dialogs = reinterpret_cast(g_windowMgr); const int result = dialogs.Confirm(LookupMessage(1584), 2, true, false, 0, "Message", 280, 120, 0); mode->SendMsg(result == 187 ? 266 : 267, this->unknown_00FC, 0, 0, 0); g_windowMgr.CloseWindow(160); g_windowMgr.CloseWindow(161); reinterpret_cast(&g_session)->ClearTradeItems(); return 0; } } else if (a == 185) { mode->SendMsg(267, this->unknown_00FC, 0, 0, 0); g_windowMgr.CloseWindow(160); g_windowMgr.CloseWindow(161); reinterpret_cast(&g_session)->ClearTradeItems(); return 0; } break; } case 14: if (a == 3) { int width = b <= 320 ? b : 320; int height = c <= 336 ? c : 336; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = 1; this->visibleRows = (newHeight - 38) / 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, this->geometry.height - 38); this->UpdateScrollBar(); } const int positions[2][2] = { {this->geometry.width - 106, this->geometry.height - 24}, {this->geometry.width - 61, this->geometry.height - 24}, }; for (int i = 0; i < 2; ++i) { this->buttons[i]->Move(positions[i][0], positions[i][1]); } this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { if (a) { this->unknown_00FC = a; } this->items.erase(this->items.begin(), this->items.end()); const int size = reinterpret_cast(&g_session)->GetList4Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1730At(i); if (item.unknown_0000[1] != 0) { this->items.push_back(item); } } this->Invalidate(); this->UpdateScrollBar(); return 0; } case 34: this->saved = reinterpret_cast(a); if (!this->saved->IsValid()) { this->saved->Reset(); } this->SendMsg(nullptr, 14, 3, 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()); ModeDragState& drag = mode->drag; ITEM_INFO item; item.Assign(reinterpret_cast(drag)); if (g_session.HasItem1718(drag.id)) { ClientItemLists* lists = reinterpret_cast(&g_session); lists->AddItem1730(item); lists->ReduceItem1718(item); if (g_windowMgr.unknown_0254) { g_windowMgr.unknown_0254->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); } mode->SendMsg(18, 0, 0, 0, 0); return 0; } case 123: { const auto* bytes = reinterpret_cast(a); ItemListChunkHeader header = *reinterpret_cast(bytes); unsigned offset = 6; if (header.type == 20800) { UIWindow* window = g_windowMgr.EnsureWindow(160); if (window) { window->SendMsg(nullptr, 36, 1, 0, 0, 0); window->SendMsg(nullptr, 23, 0, 0, 0, 0); } while (static_cast(b) > offset) { header = *reinterpret_cast(bytes + offset); offset += 6; if (header.type == 20801) { break; } if (header.type == 20802) { std::memcpy(&this->unknown_00FC, bytes + offset, header.size); offset += header.size; window->SendMsg(nullptr, 23, this->unknown_00FC, 0, 0, 0); } else { offset += header.size; } } } break; } default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x00991370 // FUNCTION: fn_13430 int UIMerchantItemShopWnd::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 == 3) { int width; if (this->unknown_010C) { width = b <= 426 ? b : 426; } else { width = b <= 320 ? b : 320; } int height = c <= 336 ? c : 336; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->visibleRows = static_cast(newHeight - this->unknown_0118 - 17) / 32; } this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { this->items.erase(this->items.begin(), this->items.end()); const int size = reinterpret_cast(&g_session)->GetList7Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1748At(i); if (item.unknown_0000[1] != 0) { this->items.push_back(item); } } this->visibleRows = std::max(this->items.size(), 4u); this->Resize(this->geometry.width, this->visibleRows * 32 + this->unknown_00F0); this->Invalidate(); return 0; } case 28: this->unknown_0100 = a; return 0; case 34: this->saved = reinterpret_cast(a); if (!this->saved->IsValid(this->unknown_010C != 0)) { this->saved->Reset(this->unknown_010C != 0); } this->SendMsg(nullptr, 14, 3, this->saved->width, this->saved->height, 0); this->Move(this->saved->x, this->saved->y); return 0; case 36: this->unknown_00F4->SetTextAutoWidth(LookupMessage(186)); return 0; case 38: { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); if (this->unknown_010C == 0) { ITEM_INFO item; item.Assign(reinterpret_cast(mode->drag)); reinterpret_cast(&g_session)->RemoveItem1760(item); if (g_windowMgr.unknown_0308) { reinterpret_cast(g_windowMgr.unknown_0308)->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); } mode->SendMsg(18, 0, 0, 0, 0); return 0; } case 119: { this->unknown_0108 = a; char grouped[80]; char text[80]; std::sprintf(text, LookupMessage(1735), FormatGroupedInteger(static_cast(a), grouped, 80)); this->notice->SetTextAutoWidth(text); this->notice->Move(12, this->geometry.height - 21); return 0; } case 123: { const auto* bytes = reinterpret_cast(a); ItemListChunkHeader header = *reinterpret_cast(bytes); unsigned offset = 6; if (header.type == 21200 || header.type == 21250) { while (static_cast(b) > offset) { header = *reinterpret_cast(bytes + offset); offset += 6; if (header.type == 21200 || header.type == 21250) { break; } if (header.type == 21253) { std::memcpy(&this->unknown_0108, bytes + offset, header.size); offset += header.size; } else { offset += header.size; } } } break; } default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x0097AA00 // FUNCTION: fn_13320 void UIMerchantItemPurchaseWnd::Slot15(int width, int height) { this->total = new UIStaticText(*this->m_context, *this->m_controls); this->total->SetSize(160, 15); char text[80]; std::sprintf(text, "Total : %d Zeny", 0); this->total->SetTextAutoWidth(text); this->total->Move(12, this->geometry.height - 21); this->AddChild(this->total); UIStaticText* title = new UIStaticText(*this->m_context, *this->m_controls); title->SetSize(160, 15); title->SetText(LookupMessage(this->unknown_0108 ? 168 : 228), 0); title->Move(16, 2); title->shadow = 1; this->AddChild(title); const std::string prefix("유저인터페이스\\"); int positions[2][2] = {{this->geometry.width - 106, this->geometry.height - 24}, {this->geometry.width - 61, this->geometry.height - 24}}; int ids[2] = {184, 185}; if (this->unknown_0108) { const char* names[2][3] = {{"btn_sell", "btn_sell_a", "btn_sell_b"}, {"btn_cancel", "btn_cancel_a", "btn_cancel_b"}}; for (int index = 0; index < 2; ++index) { this->buttons[index] = new UIBitmapButton(*this->m_context, *this->m_controls); UIBitmapButton* button = static_cast(this->buttons[index]); 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); this->buttons[index]->SetSize(button->BitmapWidth(), button->BitmapHeight()); this->buttons[index]->Move(positions[index][0], positions[index][1]); this->buttons[index]->SetId(ids[index]); this->AddChild(this->buttons[index]); } } else { const char* names[2][3] = {{"btn_buy", "btn_buy_a", "btn_buy_b"}, {"btn_cancel", "btn_cancel_a", "btn_cancel_b"}}; for (int index = 0; index < 2; ++index) { this->buttons[index] = new UIBitmapButton(*this->m_context, *this->m_controls); UIBitmapButton* button = static_cast(this->buttons[index]); 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); this->buttons[index]->SetSize(button->BitmapWidth(), button->BitmapHeight()); this->buttons[index]->Move(positions[index][0], positions[index][1]); this->buttons[index]->SetId(ids[index]); this->AddChild(this->buttons[index]); } } this->visibleRows = (height - 38) / 32; this->columns = 1; this->unknown_00F0 = this->geometry.height - this->visibleRows * 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x00979920 // FUNCTION: fn_13318 void UIMerchantItemMyShopWnd::Slot15(int width, int height) { if (this->unknown_0100) { this->notice = new UIStaticText(*this->m_context, *this->m_controls); this->notice->SetSize(160, 15); char text[80]; std::sprintf(text, LookupMessage(1735), 0); this->notice->SetTextAutoWidth(text); this->notice->Move(12, this->geometry.height - 26); this->AddChild(this->notice); } this->title = new UIStaticText(*this->m_context, *this->m_controls); this->title->SetSize(240, 15); this->title->SetText(LookupMessage(this->unknown_0100 ? 1734 : 3237), 0); this->title->Move(16, 2); this->title->shadow = 1; this->AddChild(this->title); this->resizer = new UIResizer(*this->m_context); this->resizer->SetSize(16, 16); static_cast(this->resizer)->SetDirection(7); static_cast(this->resizer)->SetBitmapName("유저인터페이스\\btn_resize.bmp"); this->resizer->Move(this->geometry.width - 15, this->geometry.height - 15); static_cast(this->resizer)->SetColors(0xFFFF00FF, 0xFFFF00FF); this->AddChild(this->resizer); UIScrollBar* scrollBar = new UIScrollBar(*this->m_context); this->scrollBar = scrollBar; scrollBar->Configure(this->geometry.width - 15, 14, 1, this->geometry.height - this->unknown_011C - 17); this->AddChild(this->scrollBar); this->saleAlarm = new UICheckBox(*this->m_context, *this->m_controls); this->saleAlarm->SetSize(240, 12); this->saleAlarm->SetImages("유저인터페이스\\checkbox_1.bmp", "유저인터페이스\\checkbox_0.bmp", LookupMessage(this->unknown_0100 ? 2698 : 2642)); this->saleAlarm->FitToText(); this->saleAlarm->Move(12, this->unknown_0100 ? this->geometry.height - 12 : this->geometry.height - 18); this->saleAlarm->SetChecked(g_vendingSaleAlarm); this->AddChild(this->saleAlarm); const std::string prefix("유저인터페이스\\"); const char* names[1][3] = {{"btn_close", "btn_close_a", "btn_close_b"}}; int positions[1][2] = {{this->geometry.width - 61, this->geometry.height - 24}}; int ids[1] = {201}; for (int index = 0; index < 1; ++index) { this->buttons[index] = new UIBitmapButton(*this->m_context, *this->m_controls); UIBitmapButton* button = static_cast(this->buttons[index]); 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); this->buttons[index]->SetSize(button->BitmapWidth(), button->BitmapHeight()); this->buttons[index]->Move(positions[index][0], positions[index][1]); this->buttons[index]->SetId(ids[index]); this->AddChild(this->buttons[index]); } this->columns = (width - 40) / 32; this->visibleRows = static_cast(height - this->unknown_011C - 17) / 32; this->SendMsg(nullptr, 23, 0, 0, 0, 0); } // OFFSET: 0x00993A20 // FUNCTION: fn_13434 int UINoticeMessageBox_LockSellItem::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message != 6) { UIFrameWnd::SendMsg(sender, message, a, b, c, d); return 0; } if (a == 201 && this->parent) { this->parent->SendMsg(this, 6, 201, 0, 0, 0); } return 0; } // OFFSET: 0x00898650 // FUNCTION: fn_11549 int UIEditCtrl_Currency::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message == WM_KEYDOWN) { if (a == VK_BACK) { int anchor; int cursor; this->m_edit->input.Selection(anchor, cursor); if (anchor == cursor) { if (cursor <= 2) { if (this->text[1] == ',') { this->m_edit->input.Select(0, 2); } } else if (this->text[cursor - 1] == ',') { this->m_edit->input.Select(cursor - 1, cursor - 1); } } } else if (a == VK_DELETE) { int anchor; int cursor; this->m_edit->input.Selection(anchor, cursor); if (anchor == cursor) { if (cursor == 0) { if (this->text[1] == ',') { this->m_edit->input.Select(0, 2); } } else if (this->text[cursor] == ',') { this->m_edit->input.Select(cursor + 1, cursor + 1); } } } } return UIEditCtrl2::SendMsg(sender, message, a, b, c, d); } // OFFSET: 0x009845A0 // FUNCTION: fn_13355 void UIItemPurchaseWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1720ByItemId(item.itemId.c_str()); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 4, item, item.quantity, -1); } } // OFFSET: 0x00984700 // FUNCTION: fn_13356 void UIItemSellWnd2::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 1, 0, 0); } } if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1730(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 5, item, item.quantity, -1); } } // OFFSET: 0x009848E0 // FUNCTION: fn_13357 void UIItemSellWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 1, 0, 0); } } if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1730(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 5, item, item.quantity, -1); } } // OFFSET: 0x00984AC0 // FUNCTION: fn_13358 void UIItemShopWnd2::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { this->m_frameContext->windows.EnsureWindow(12)->SendMsg(nullptr, 24, reinterpret_cast(&item), 1, 0, 0); } } if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); const ITEM_INFO owned = LookupClientItemByIdentity(g_session.m_inventoryItems, item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 3, item, owned.unknown_0000[1] > 0 ? item.quantity : 1, -1); } } // OFFSET: 0x00984CA0 // FUNCTION: fn_13359 void UIItemShopWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); const ITEM_INFO owned = LookupClientItemByIdentity(g_session.m_inventoryItems, item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 3, item, owned.unknown_0000[1] > 0 ? item.quantity : 1, -1); } } // OFFSET: 0x00984DF0 // FUNCTION: fn_13360 void UIItemStoreFindWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0 && item.unknown_0074[2] == 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1738(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 6, item, item.quantity, -1); } } // OFFSET: 0x00984F10 // FUNCTION: fn_13361 void UIItemStoreSubWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0 && item.unknown_0074[2] == 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1738(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 6, item, item.quantity, -1); } } // OFFSET: 0x00985030 // FUNCTION: fn_13362 void UIItemStoreWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0 && item.unknown_0074[2] == 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1738(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, 6, item, item.quantity, -1); } } // OFFSET: 0x009853A0 // FUNCTION: fn_13365 void UIMerchantItemPurchaseWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } const int previous = this->hovered; this->hovered = this->GetItemIndexAt(x, y); if (previous != this->hovered) { this->Invalidate(); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemByIndex(this->hovered); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1760ByItemId(item.itemId.c_str()); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem(this->m_frameContext->windows, descriptions, this->unknown_0108 != 0 ? 21 : 13, item, item.quantity, -1); } } // OFFSET: 0x00985830 // FUNCTION: fn_13368 void UIMerchantMirrorItemWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1750(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; mode->drag.BeginItem( this->m_frameContext->windows, descriptions, this->unknown_00F4 == 1 ? 20 : this->unknown_00F4 == 2 ? 22 : 11, item, item.quantity, -1 ); } } // OFFSET: 0x00985970 // FUNCTION: fn_13369 void UIMerchantShopMakeWnd::Slot25(int x, int y) { if (y < 17) { UIFrameWnd::Slot25(x, y); return; } if (g_replayAnimationScaling != 0) { return; } ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { CGameMode* gameMode = static_cast(g_modeMgr.GetGameMode()); item = g_session.FindItem1768(item.unknown_0000[1]); ItemDescriptions descriptions{g_itemDescriptions}; gameMode->drag.BeginItem(this->m_frameContext->windows, descriptions, this->mode != 0 ? 19 : 10, item, item.quantity, -1); } } // OFFSET: 0x00985B90 // FUNCTION: fn_13371 void UIItemPurchaseWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); std::string text; char currency[12]; sprintf(currency, "Zeny"); if (this->unknown_00FC) { if (g_serviceType == 6) { sprintf(currency, "Koin"); } else if (g_serviceType == 0) { if (*reinterpret_cast(&g_session.unknown_59DC[0x198]) == 1) { sprintf(currency, "한코인"); } else { sprintf(currency, LookupMessage(1307)); } } else { sprintf(currency, "Point"); } } char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.unknown_0014[0] != item.unknown_0014[1]) { text = FormatOwnedString("%s %d %s %d -> %s %s", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64), currency); } else { text = FormatOwnedString("%s %d %s %s %s", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64), currency); } reinterpret_cast(g_modeMgr.gameMode)->Show(text.c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } // OFFSET: 0x00985ED0 // FUNCTION: fn_13372 void UIItemSellWnd2::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); std::string text; char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.unknown_0014[0] != item.unknown_0014[1]) { text = FormatOwnedString("%s %d %s %d -> %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } else { text = FormatOwnedString("%s %d %s %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } reinterpret_cast(g_modeMgr.gameMode)->Show(text.c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } // OFFSET: 0x00986190 // FUNCTION: fn_13373 void UIItemSellWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { return; } int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); std::string text; char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.unknown_0014[0] != item.unknown_0014[1]) { if (item.identified == 1 && item.unknown_0098 != 0) { text = FormatOwnedString(LookupMessage(2758), naming.DisplayName(item, 0).c_str(), item.unknown_0098, item.quantity, LookupMessage(588), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64), "Zeny"); } else { text = FormatOwnedString("%s %d %s %d -> %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } } else { if (item.identified == 1 && item.unknown_0098 != 0) { text = FormatOwnedString(LookupMessage(2759), naming.DisplayName(item, 0).c_str(), item.unknown_0098, item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64), "Zeny"); } else { text = FormatOwnedString("%s %d %s %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } } reinterpret_cast(g_modeMgr.gameMode)->Show(text.c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } // OFFSET: 0x009865C0 // FUNCTION: fn_13374 void UIItemShopWnd2::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] == 0) { return; } int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); std::string text; char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (this->unknown_00F8 == 0) { if (item.unknown_0014[0] == item.unknown_0014[1]) { text = FormatOwnedString("%s %s Zeny", naming.DisplayName(item, 0).c_str(), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } else { text = FormatOwnedString("%s %d -> %s Zeny", naming.DisplayName(item, 0).c_str(), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } } else { if (item.unknown_0014[0] == item.unknown_0014[1]) { text = FormatOwnedString("%s %d %s %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } else { text = FormatOwnedString("%s %d %s %d -> %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), item.unknown_0014[0], FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } } reinterpret_cast(g_modeMgr.gameMode)->Show(text.c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } // OFFSET: 0x00986970 // OFFSET: 0x00987000 // FUNCTION: fn_13376 void UIItemStoreFindWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2600), naming.DisplayName(item, 0).c_str(), item.unknown_0098).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode)->Show(naming.DisplayName(item, 0).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00987200 // FUNCTION: fn_13377 void UIItemStoreSubWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2600), naming.DisplayName(item, 0).c_str(), item.unknown_0098).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode)->Show(naming.DisplayName(item, 0).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00987400 // FUNCTION: fn_13378 void UIItemStoreWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2600), naming.DisplayName(item, 0).c_str(), item.unknown_0098).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode)->Show(naming.DisplayName(item, 0).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00987600 // FUNCTION: fn_13379 void UIItemWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2551), naming.DisplayName(item, 0).c_str(), item.unknown_0098, item.quantity).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(183), naming.DisplayName(item, 0).c_str(), item.quantity).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00987850 // FUNCTION: fn_13380 void UIMerchantItemMyShopWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); std::string text; char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (this->unknown_0100 == 0) { if (item.identified == 1 && item.unknown_0098 != 0) { text = FormatOwnedString(LookupMessage(2757), naming.DisplayName(item, 0).c_str(), item.unknown_0098, FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } else { text = FormatOwnedString("%s %s Zeny", naming.DisplayName(item, 0).c_str(), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)); } } else { text = FormatOwnedString(LookupMessage(1736), naming.DisplayName(item, 0).c_str(), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64), item.quantity); } reinterpret_cast(g_modeMgr.gameMode)->Show(text.c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } // OFFSET: 0x00987B90 // FUNCTION: fn_13381 void UIMerchantItemPurchaseWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); char price[64]; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString("%s %d %s %s Zeny", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588), FormatGroupedInteger(static_cast(item.unknown_0014[1]), price, 64)) .c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } // OFFSET: 0x00987D40 // FUNCTION: fn_13382 void UIMerchantItemShopWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2600), naming.DisplayName(item, 0).c_str(), item.unknown_0098).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode)->Show(naming.DisplayName(item, 0).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } return; } item = this->GetItemByIndex(this->GetItemIndexAt(x, y)); if (item.unknown_0000[1] == 0) { return; } int tooltipX = 72; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2600), naming.DisplayName(item, 0).c_str(), item.unknown_0098).c_str(), tooltipX - 2, tooltipY + 24, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode)->Show(naming.DisplayName(item, 0).c_str(), tooltipX - 2, tooltipY + 24, g_session.GetItemNameColor(item), 0, 1); } } // OFFSET: 0x009880F0 // FUNCTION: fn_13383 void UIMerchantItemWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2551), naming.DisplayName(item, 0).c_str(), item.unknown_0098, item.quantity).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString("%s %d %s", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588)).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00988340 // FUNCTION: fn_13384 void UIMerchantMirrorItemWnd::Slot28(int x, int y) { ITEM_INFO item = this->GetItemAt(x, y); if (item.unknown_0000[1] > 0) { int tooltipX = (x - 40) / 32 * 32 + 40; int tooltipY = (y - 17) / 32 * 32 + 1; this->ToScreen(tooltipX, tooltipY); ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (item.identified == 1 && item.unknown_0098 != 0) { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString(LookupMessage(2756), naming.DisplayName(item, 0).c_str(), item.unknown_0098, item.quantity).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } else { reinterpret_cast(g_modeMgr.gameMode) ->Show(FormatOwnedString("%s %d %s", naming.DisplayName(item, 0).c_str(), item.quantity, LookupMessage(588)).c_str(), tooltipX, tooltipY, g_session.GetItemNameColor(item), 0, 1); } } } // OFFSET: 0x00859200 // FUNCTION: fn_10774 bool IsInputSuggestionAllowed() { if (g_windowMgr.IsHoverOnWindow01C8Button() && !g_inputSuggestionsEnabled) { return false; } return true; } // OFFSET: 0x00860080 // FUNCTION: fn_10898 bool UIEditCtrl::DecodeItemLink(const std::vector& values, ITEM_INFO& item) { if (values.empty()) { return false; } ITEM_DESC description = FindItemDescription(values[2]); item.SetName(description.identifiedName); std::string name(description.identifiedName); LowercaseText(name); if (name.find("unknown item") != std::string::npos) { return false; } item.unknown_0000[2] = values[0]; item.SetItemId(values[2]); if (values[1] != 0) { item.unknown_0000[0] = 4; } if (values.size() > 3) { item.unknown_0060 = values[3]; } item.unknown_0070 = values[4]; int cardCount = 0; item.unknown_0088 = static_cast(values[5]); if (values.size() > 6) { cardCount = values[6]; for (int i = 1; i < cardCount + 1; ++i) { int index = i - 1; item.SetCard(values[6 + i], index); } } if (static_cast(cardCount + 8) < values.size()) { item.unknown_0098 = values[cardCount + 8]; int optionCount = item.unknown_0098 + 1; for (int i = 1; i < optionCount; ++i) { const int base = cardCount + 9 + (i - 1) * 3; ItemOption option; option.id = static_cast(values[base]); option.value = static_cast(values[base + 2]); option.parameter = static_cast(values[base + 1]); int index = i - 1; item.SetOption(option, index); } } item.identified = 1; return true; } // OFFSET: 0x0096E650 // FUNCTION: fn_13214 UIItemBaseWnd::UIItemBaseWnd(UIWindowContext& windowContext, UIFrameContext& frameContext) : UIFrameWnd(windowContext, frameContext, 0), resizer(nullptr), scrollBar(nullptr), scroll(0), unknown_00E4(0) { this->showQuantity = 1; this->unknown_00B8 = 0; this->buttons[0] = nullptr; this->buttons[1] = nullptr; this->m_controls = nullptr; this->scroll = 0; } // OFFSET: 0x0096E750 // FUNCTION: fn_13215 UIItemDropCntWnd::UIItemDropCntWnd(UIWindowContext& windows, UIFrameContext& frames) : UIFrameWnd(windows, frames, 0) { } // OFFSET: 0x0096E7B0 // FUNCTION: fn_13216 UIItemPurchaseWnd::UIItemPurchaseWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->hovered = -1; this->unknown_00B8 = 1; this->unknown_00FC = 0; this->saved = nullptr; } // OFFSET: 0x0096E830 // FUNCTION: fn_13217 UIItemSellWnd2::UIItemSellWnd2(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->hovered = -1; this->unknown_00B8 = 1; this->saved = nullptr; this->unknown_00FC = 0; } // OFFSET: 0x0096E8B0 // FUNCTION: fn_13218 UIItemSellWnd::UIItemSellWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->hovered = -1; this->unknown_00B8 = 1; this->saved = nullptr; } // OFFSET: 0x0096E930 // FUNCTION: fn_13219 UIItemShopWnd2::UIItemShopWnd2(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->hovered = -1; this->showQuantity = 0; this->unknown_00F8 = 0; this->unknown_00B8 = 1; this->saved = nullptr; this->unknown_0104 = 29; this->unknown_0108 = 0; } // OFFSET: 0x0096E9D0 // FUNCTION: fn_13220 UIItemShopWnd::UIItemShopWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->hovered = -1; this->showQuantity = 0; this->unknown_00F8 = 0; this->unknown_00B8 = 1; this->saved = nullptr; this->unknown_0104 = 29; this->unknown_0108 = 0; this->unknown_010C = 0; } // OFFSET: 0x0096EA80 // FUNCTION: fn_13221 UIItemStoreFindWnd::UIItemStoreFindWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->saved = nullptr; this->scrollBar = nullptr; this->scroll = 0; this->columns = 1; this->visibleRows = 3; this->unknown_00E4 = 0; this->unknown_0120 = 18; } // OFFSET: 0x0096EB70 // FUNCTION: fn_13222 UIItemStoreSubWnd::UIItemStoreSubWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->saved = nullptr; this->scrollBar = nullptr; this->scroll = 0; this->columns = 1; this->visibleRows = 3; this->unknown_00E4 = 0; this->unknown_011C = 18; } // OFFSET: 0x0096EC60 // FUNCTION: fn_13223 UIItemStoreWnd::UIItemStoreWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->unknown_016C = 0; this->unknown_0170 = 0; this->unknown_0174 = 0; this->unknown_0180 = 0; this->showQuantity = 1; this->unknown_00B8 = 1; this->saved = nullptr; this->unknown_0178 = 0; this->unknown_017C = 0; this->unknown_00F0 = 0; for (int i = 0; i < 8; ++i) { this->unknown_00F8[i] = 0; this->tabs[i] = nullptr; this->unknown_0120[i] = 0; } this->unknown_0140 = 0; this->unknown_0188 = 0; this->unknown_018C = 0; this->unknown_0190 = 0; } // OFFSET: 0x0096ED90 // FUNCTION: fn_13224 UIItemWnd::UIItemWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->unknown_0124 = 0; this->unknown_0128 = nullptr; this->unknown_012C = 0; this->resizer = nullptr; this->scrollBar = nullptr; this->saved = nullptr; this->unknown_0100 = 0; this->unknown_0104 = 0; this->unknown_0108 = 0; this->unknown_010C = 0; this->scroll = 0; this->unknown_00E4 = 0; } // OFFSET: 0x0096EE60 // FUNCTION: fn_13225 UIMerchantItemMyShopWnd::UIMerchantItemMyShopWnd(UIWindowContext& windows, UIFrameContext& frames, int value) : UIItemBaseWnd(windows, frames) { this->unknown_0100 = value; this->startTick = 0; this->duration = 0; this->actionButton = nullptr; this->unknown_011C = 21; this->unknown_00B8 = 1; this->saved = nullptr; this->shopOpen = 0; this->unknown_010C = 0; } // OFFSET: 0x0096EF10 // FUNCTION: fn_13226 UIMerchantItemPurchaseMSGWnd::UIMerchantItemPurchaseMSGWnd(UIWindowContext& windowContext, UIFrameContext& frameContext) : UIFrameWnd(windowContext, frameContext, 0) { this->title = nullptr; this->firstLine = nullptr; this->thirdLine = nullptr; this->secondLine = nullptr; this->buyButton = nullptr; this->cancelButton = nullptr; this->m_controls = nullptr; this->unknown_00D0 = 0; } // OFFSET: 0x0096EFC0 // FUNCTION: fn_13227 UIMerchantItemPurchaseWnd::UIMerchantItemPurchaseWnd(UIWindowContext& windows, UIFrameContext& frames, int value) : UIItemBaseWnd(windows, frames) { this->unknown_0108 = value; this->unknown_00B8 = 1; this->unknown_00F8 = 0; this->saved = nullptr; this->hovered = -1; reinterpret_cast(&g_session)->ClearItems1760(); this->unknown_00F0 = 0; } // OFFSET: 0x0096F060 // FUNCTION: fn_13228 UIMerchantItemShopWnd::UIMerchantItemShopWnd(UIWindowContext& windows, UIFrameContext& frames, int value) : UIItemBaseWnd(windows, frames) { this->unknown_0108 = 0; this->unknown_010C = value; this->startTick = 0; this->duration = 0; this->unknown_00B8 = 1; this->hovered = -1; this->saved = nullptr; this->unknown_00F0 = 0; this->unknown_0118 = 21; } // OFFSET: 0x0096F110 // FUNCTION: fn_13229 UIMerchantItemWnd::UIMerchantItemWnd(UIWindowContext& windows, UIFrameContext& frames) : UIItemBaseWnd(windows, frames) { this->unknown_00B8 = 1; this->saved = nullptr; } // OFFSET: 0x0096F180 // FUNCTION: fn_13230 UIMerchantMirrorItemWnd::UIMerchantMirrorItemWnd(UIWindowContext& windows, UIFrameContext& frames, int value) : UIItemBaseWnd(windows, frames) { this->unknown_00F4 = value; this->unknown_00B8 = 1; this->saved = nullptr; } // OFFSET: 0x0096F3A0 // FUNCTION: fn_13232 UINoticeMessageBox_LockSellItem::UINoticeMessageBox_LockSellItem(UIWindowContext& windows, UIFrameContext& frames) : UIFrameWnd(windows, frames, 0) { this->startTick = timeGetTime(); this->duration = 2000; } // OFFSET: 0x0096FB70 // FUNCTION: fn_13238 UIItemStoreWnd::~UIItemStoreWnd() { g_unknown_01738268 = 0; } // OFFSET: 0x0096FC10 // FUNCTION: fn_13239 UIItemWnd::~UIItemWnd() = default; // OFFSET: 0x0098D1F0 // FUNCTION: fn_13423 int UIItemShopWnd2::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: if (a == 213) { g_windowMgr.unknown_0064 = b; return 0; } break; case 14: if (a == 7) { int width = b <= 320 ? b : 320; int height = c <= 336 ? c : 336; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = 1; this->visibleRows = (newHeight - this->unknown_0108 - this->unknown_0104 - 17) / 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, this->geometry.height - this->unknown_0108 - this->unknown_0104 - 17); this->checkBox->Move(12, this->geometry.height - 20); this->UpdateScrollBar(); } this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { this->items.erase(this->items.begin(), this->items.end()); const int size = reinterpret_cast(&g_session)->GetList1Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1718At(i); if (item.unknown_0000[1] != 0) { this->items.push_back(item); } } this->Invalidate(); this->UpdateScrollBar(); break; } case 34: this->saved = reinterpret_cast(a); if (!static_cast(this->saved)->IsValid()) { static_cast(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 36: this->unknown_00F8 = 1; this->showQuantity = 1; this->title->SetTextAutoWidth(LookupMessage(1568)); this->checkBox->m_disabled = 0; return 0; case 38: if (a == 0) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); ITEM_INFO item; item.Assign(reinterpret_cast(mode->drag)); reinterpret_cast(&g_session)->RemoveItem1720ByName(item); if (g_windowMgr.unknown_0258) { g_windowMgr.unknown_0258->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); mode->SendMsg(18, 0, 0, 0, 0); return 0; } if (a == 1) { CGameMode* mode = static_cast(g_modeMgr.GetGameMode()); ITEM_INFO item; item.Assign(reinterpret_cast(mode->drag)); ClientItemLists* lists = reinterpret_cast(&g_session); lists->MergeItem1718(item); lists->RemoveItem1730(item); if (g_windowMgr.unknown_0260) { g_windowMgr.unknown_0260->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); mode->SendMsg(18, 0, 0, 0, 0); return 0; } break; default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; } // OFFSET: 0x00859470 // FUNCTION: fn_10776 void UIChatEditCtrl::InsertItemLink(const ITEM_INFO& item) { if (!this->unknown_0144) { this->unknown_0144 = new (std::nothrow) UIItemTagOnChat(); if (!this->unknown_0144) { return; } } ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNaming naming{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}; if (!this->unknown_0144->CanInsertTag(naming.DisplayName(item, 0), this->geometry.width)) { return; } this->unknown_0144->taggedText = this->text; const std::string name = naming.DisplayName(item, 0); const std::string tag = this->unknown_0144->AppendTag(name); this->m_edit->input.ResetInput(); this->m_edit->input.Insert(tag.c_str()); this->unknown_0144->sub_89CFE0(item, 0x12B8A4); } // OFFSET: 0x00980340 // FUNCTION: fn_13335 void UIItemStoreFindWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, true, "", 0); unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(0, 17, this->geometry.width, this->geometry.height - 38, RGB(red, green, blue)); this->DrawButtonBar(0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const int rows = (this->geometry.height - 38) / 32; int slots = rows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 10, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, rows * 32, RGB(fillRed, fillGreen, fillBlue)); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int top = visible / this->columns * 32; const int left = visible % this->columns * 32 + 10; const int width = this->geometry.width - left - 66; const int x = left + 4; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); this->DrawWrappedItemName(left + 40, top + 29, width, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } if (++visible == this->visibleRows * this->columns) { break; } } this->DrawTextAt(controls.fonts, controls.locale, 16, this->geometry.height - 20, this->unknown_0124.c_str(), 0, 0, 12, 0, 0, 0); } // OFFSET: 0x00980610 // FUNCTION: fn_13336 void UIItemStoreSubWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, true, "", 0); unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(0, 17, this->geometry.width, this->geometry.height - 38, RGB(red, green, blue)); this->DrawButtonBar(0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const int rows = (this->geometry.height - 38) / 32; int slots = rows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 10, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, rows * 32, RGB(fillRed, fillGreen, fillBlue)); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int top = visible / this->columns * 32; const int left = visible % this->columns * 32 + 10; const int width = this->geometry.width - left - 66; const int x = left + 4; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); this->DrawWrappedItemName(left + 40, top + 29, width, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } if (++visible == this->visibleRows * this->columns) { break; } } this->DrawTextAt(controls.fonts, controls.locale, 16, this->geometry.height - 20, this->unknown_0120.c_str(), 0, 0, 12, 0, 0, 0); } // OFFSET: 0x0097E7A0 // FUNCTION: fn_13330 void UIItemPurchaseWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int height = this->geometry.height; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(40, 17, this->geometry.width - 50, (height - 38) / 32 * 32, RGB(red, green, blue)); int slots = (height - 58) / 32; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int column = visible % this->columns * 32; const int top = visible / this->columns * 32; if (this->hovered == index) { unsigned hoverRed, hoverGreen, hoverBlue; SkinPaletteChannels(controls.resources, 6, 2, hoverRed, hoverGreen, hoverBlue); this->FillRegion(column + 72, top + 19, 191, 28, RGB(hoverRed, hoverGreen, hoverBlue)); } const int x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); int nameWidth = 110; const int amount = static_cast(it->unknown_0014[0]); if (amount != static_cast(it->unknown_0014[1])) { if (amount >= 10000) { nameWidth = 45; } else if (amount >= 1000) { nameWidth = 55; } else if (amount >= 100) { nameWidth = 70; } else if (amount >= 10) { nameWidth = 80; } } this->DrawWrappedItemName(column + 76, top + 29, nameWidth, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } char currency[10]; StringFormat(currency, 10, static_cast(-1), "Z"); if (this->unknown_00FC != 0) { const char* name; if (g_serviceType == 6) { name = "Koin"; } else if (g_serviceType == 0) { if (*reinterpret_cast(&g_session.unknown_59DC[0x198]) == 1) { name = "한코인"; } else { name = LookupMessage(1307); } } else { name = "Point"; } sprintf(currency, name); } char price[64]; char text[64]; int length; if (it->unknown_0014[0] != it->unknown_0014[1]) { length = sprintf(text, " %d -> %s %s", it->unknown_0014[0], FormatGroupedInteger(static_cast(it->unknown_0014[1]), price, 64), currency); } else { length = sprintf(text, " %s %s", FormatGroupedInteger(static_cast(it->unknown_0014[0]), price, 64), currency); } this->DrawRightAlignedText(this->geometry.width - 18, top + 29, text, length, 0, 12, 0, 0); if (++visible == this->visibleRows * this->columns) { break; } } if (this->unknown_00FC != 0) { this->DrawTextAt(controls.fonts, controls.locale, 12, this->geometry.height - 48, LookupMessage(1306), 0, 0, 12, 0, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 179, this->geometry.height - 48, LookupMessage(1307), 0, 0, 12, 0, 0, 0); this->FillRegion(109, this->geometry.height - 51, 66, 18, 0x8E8E8E); } } // OFFSET: 0x0097F220 // FUNCTION: fn_13332 void UIItemSellWnd::Paint() { UIButtonContext& controls = *this->m_controls; char price[64]; char text[64]; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const int slotRows = (this->geometry.height - 38) / 32; int slots = slotRows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, slotRows * 32, RGB(fillRed, fillGreen, fillBlue)); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int column = visible % this->columns * 32; const int top = visible / this->columns * 32; if (this->hovered == index) { unsigned hoverRed, hoverGreen, hoverBlue; SkinPaletteChannels(controls.resources, 6, 2, hoverRed, hoverGreen, hoverBlue); this->FillRegion(column + 72, top + 19, 191, 28, RGB(hoverRed, hoverGreen, hoverBlue)); } const int x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); int nameWidth = 100; const int amount = static_cast(it->unknown_0014[0]); if (amount != static_cast(it->unknown_0014[1])) { if (amount >= 10000) { nameWidth = 45; } else if (amount >= 1000) { nameWidth = 55; } else if (amount >= 100) { nameWidth = 70; } else if (amount >= 10) { nameWidth = 80; } } this->DrawWrappedItemName(column + 76, top + 29, nameWidth, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } int length; if (it->unknown_0014[0] == it->unknown_0014[1]) { length = sprintf(text, " %s Zeny", FormatGroupedInteger(static_cast(it->unknown_0014[0]), price, 64)); } else { length = sprintf(text, " %d -> %s Zeny", it->unknown_0014[0], FormatGroupedInteger(static_cast(it->unknown_0014[1]), price, 64)); } this->DrawRightAlignedText(this->geometry.width - 18, top + 29, text, length, 0, 12, 0, 0); if (++visible == this->visibleRows * this->columns) { break; } } } // OFFSET: 0x0097FBF0 // FUNCTION: fn_13334 void UIItemShopWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - this->unknown_0104 - 17) / 8 + ((this->geometry.height - this->unknown_0104 - 17) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - this->unknown_0104 - 17) / 8 + ((this->geometry.height - this->unknown_0104 - 17) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - this->unknown_0104 - 17, RGB(red, green, blue)); this->FillRegion( 20, (this->geometry.height - this->unknown_0104 - 17) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - this->unknown_0104 - 17) % 32, RGB(red, green, blue) ); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; int slotRows = (this->geometry.height - this->unknown_0108 - this->unknown_0104 - 17) / 32; int slots = slotRows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } if (this->unknown_010C != 0) { slotRows = (this->geometry.height - this->unknown_0104 - 17) / 32; } SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(72, 17, columns * 32 - 32, slotRows * 32, RGB(red, green, blue)); if (this->unknown_010C != 0) { this->FillRegion(40, slotRows * 32 - 15, 32, 32, RGB(red, green, blue)); } ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int column = visible % this->columns * 32; const int top = visible / this->columns * 32; if (this->hovered == index) { unsigned hoverRed, hoverGreen, hoverBlue; SkinPaletteChannels(controls.resources, 6, 2, hoverRed, hoverGreen, hoverBlue); this->FillRegion(column + 72, top + 19, 191, 28, RGB(hoverRed, hoverGreen, hoverBlue)); } const int x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); int nameWidth = 100; const int amount = static_cast(it->unknown_0014[0]); if (amount != static_cast(it->unknown_0014[1])) { if (amount >= 10000) { nameWidth = 45; } else if (amount >= 1000) { nameWidth = 55; } else if (amount >= 100) { nameWidth = 70; } else if (amount >= 10) { nameWidth = 80; } } this->DrawWrappedItemName(column + 76, top + 29, nameWidth, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } char currency[8]; sprintf(currency, "Z"); if (this->unknown_010C != 0) { const char* name; if (g_serviceType == 6) { name = "K"; } else if (g_serviceType == 0) { name = *reinterpret_cast(&g_session.unknown_59DC[0x198]) != 1 ? "C" : "H"; } else { name = "P"; } sprintf(currency, name); } char price[64]; char text[64]; int length; if (it->unknown_0014[0] != it->unknown_0014[1]) { length = sprintf(text, " %d -> %s %s", it->unknown_0014[0], FormatGroupedInteger(static_cast(it->unknown_0014[1]), price, 64), currency); } else { length = sprintf(text, " %s %s", FormatGroupedInteger(static_cast(it->unknown_0014[0]), price, 64), currency); } this->DrawRightAlignedText(this->geometry.width - 18, top + 29, text, length, 0, 12, 0, 0); if (++visible == this->visibleRows * this->columns) { break; } } if (this->unknown_010C != 0) { int message; if (g_serviceType == 0 && *reinterpret_cast(&g_session.unknown_59DC[0x198]) == 1) { message = 1290; } else { message = 1210; } char text[352]; const int aid = *reinterpret_cast(&g_session.unknown_5913[0x1D]); const char* name = this->ClipTextToWidth(g_session.DecodePlayerName(), 100, 0, 12, 0); int length = sprintf(text, LookupMessage(message), name, aid); this->DrawTextAt(controls.fonts, controls.locale, 12, this->geometry.height - 21, text, length, 0, 12, 0, 0, 0); const int gid = *reinterpret_cast(&g_session.unknown_5913[0x21]); name = this->ClipTextToWidth(g_session.DecodePlayerName(), 100, 0, 12, 0); length = sprintf(text, LookupMessage(1305), name, gid); this->DrawTextAt(controls.fonts, controls.locale, 12, this->geometry.height - this->unknown_0104 - 21, text, length, 0, 12, 0, 0, 0); } } // OFFSET: 0x009808E0 // FUNCTION: fn_13337 void UIItemStoreWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(this->unknown_00B8 != 0 ? 3 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const int slotRows = (this->geometry.height - 74) / 32; if (!this->unknown_0190) { this->scrollBar->Show(0); unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(40, 17, columns * 32, slotRows * 32, RGB(fillRed, fillGreen, fillBlue)); DrawRoundedBorder(*this, 55, 131, 187, 139, 0xCE9484); DrawFilledRoundedBorder(*this, 56, 132, 185, 137, 0xFFE7DE); DrawFilledRoundedBorder(*this, 61, 137, 175, 127, 0xFFFFFF); const auto* poring = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\notice_poring.bmp"))); this->DrawBitmap(116, 151, &poring->image, true); this->DrawCenteredText(20, 210, LookupMessage(3540), 257, 0, 12, 0, 0); this->DrawCenteredText(20, 236, LookupMessage(3191), 257, 0, 15, 0xC89482, 1); this->DrawCenteredText(20, 272, LookupMessage(3603), 257, 0, 12, 0x6464DC, 1); return; } this->scrollBar->Show(1); int slots = slotRows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, slotRows * 32, RGB(fillRed, fillGreen, fillBlue)); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->scroll * this->columns) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int top = visible / this->columns * 32; const int column = visible % this->columns * 32; const int x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); this->DrawWrappedItemName(column + 80, top + 29, 180, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } if (++visible == this->visibleRows * this->columns) { break; } } const auto* icon = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\inventory\\icon_num.bmp"))); this->DrawBitmap(6, this->geometry.height - 21, &icon->image, true); const std::uint32_t color = this->unknown_0188 >= this->unknown_018C ? 0xFF : 0x232323; this->DrawTextAt(controls.fonts, controls.locale, 22, this->geometry.height - 19, FormatOwnedString("%d", this->unknown_0188).c_str(), 0, 0, 11, color, 0, 0); const int width = this->TextWidth(controls.fonts, controls.locale, FormatOwnedString("%d", this->unknown_0188).c_str(), 0, 0, 11, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, width + 23, this->geometry.height - 19, FormatOwnedString("/%d", this->unknown_018C).c_str(), 0, 0, 11, 0, 0, 0); } // OFFSET: 0x009819C0 // FUNCTION: fn_13341 void UIMerchantItemPurchaseWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } int rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = (this->geometry.height - 38) / 8 + ((this->geometry.height - 38) % 8 != 0); for (int y = 17; rows > 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - 38, RGB(red, green, blue)); this->FillRegion(20, (this->geometry.height - 38) / 32 * 32 + 17, this->geometry.width - 24, (this->geometry.height - 38) % 32, RGB(red, green, blue)); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const int slotRows = (this->geometry.height - 38) / 32; int slots = slotRows; for (int y = 17; slots > 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, slotRows * 32, RGB(fillRed, fillGreen, fillBlue)); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int column = visible % this->columns * 32; const int top = visible / this->columns * 32; if (this->hovered == index) { unsigned hoverRed, hoverGreen, hoverBlue; SkinPaletteChannels(controls.resources, 6, 2, hoverRed, hoverGreen, hoverBlue); this->FillRegion(column + 72, top + 19, 191, 28, RGB(hoverRed, hoverGreen, hoverBlue)); } const int x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); this->DrawWrappedItemName(column + 76, top + 29, 90, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } char price[64]; char text[64]; int length; if (it->unknown_0014[0] == it->unknown_0014[1]) { length = sprintf(text, " %s Zeny", FormatGroupedInteger(static_cast(it->unknown_0014[0]), price, 64)); } else { length = sprintf(text, " %d -> %s Zeny", it->unknown_0014[0], FormatGroupedInteger(static_cast(it->unknown_0014[1]), price, 64)); } this->DrawRightAlignedText(this->geometry.width - 18, top + 29, text, length, 0, 12, 0, 0); ++visible; } } // OFFSET: 0x00981EE0 // OFFSET: 0x00982A80 // FUNCTION: fn_13344 void UIMerchantShopMakeWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->ClearSurface(0xFF); this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(0, 17, this->geometry.width, this->geometry.height - 38, RGB(red, green, blue)); int barHeight; if (this->mode == 0) { this->DrawButtonBar(2, 0, 1); } else { barHeight = this->DrawButtonBar(2, 0, 2); } for (int i = 0; i < this->unknown_012C; ++i) { if (this->mode == 0) { this->priceEdits[i]->Show(i < this->visibleRows); } else if (i < this->visibleRows) { this->priceEdits[i]->Show(1); this->quantityEdits[i]->Show(1); } else { this->priceEdits[i]->Show(0); this->quantityEdits[i]->Show(0); } } for (int i = 0; i < this->unknown_012C; ++i) { unsigned char hidden = 1; if (this->scroll <= i && i < this->visibleRows + this->scroll) { hidden = 0; this->priceEdits[i]->Move(this->geometry.width - 119, (i - this->scroll) * 42 + 54); } this->priceEdits[i]->Show(hidden ^ 1); if (this->mode != 0) { this->quantityEdits[i]->Move(this->geometry.width + hidden * 340 - 221, (i - this->scroll) * 42 + 54); } } const char* message; int messageY; if (this->mode != 0) { int count = this->items.size(); if (static_cast(count) < static_cast(this->unknown_0140)) { count = this->unknown_0140; } for (int i = 0, y = 72; i < count; ++i, y += 42) { this->DrawTextAt(controls.fonts, controls.locale, this->geometry.width - 155, y - 15, LookupMessage(1721), 0, 0, 12, 0, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, this->geometry.width - 176, y - 15, LookupMessage(588), 0, 0, 12, 0, 0, 0); DrawItemSlotBackground(*this, 3, y - 18); if (i >= this->unknown_012C) { continue; } char text[24] = {}; std::strcpy(text, this->priceEdits[i]->Text()); if (g_session.IsNumberWithCommas(text) != 1) { continue; } std::int64_t price = _atoi64(text); if (price <= 0) { continue; } const int x = this->geometry.width - 155; this->DrawTextAt(controls.fonts, controls.locale, x, y, LookupMessage(3222), 0, 0, 12, 0, 0, 0); const int width = this->TextWidth(controls.fonts, controls.locale, LookupMessage(3222), 0, 0, 12, 0, 0); const double rate = PriceCommission(price) * 0.01; price += static_cast(price * rate); FormatGroupedInteger(price, text, 24); const PriceColors colors = PriceColor(price); if (colors.secondary == 0xFFFFFFFF) { this->DrawTextAt(controls.fonts, controls.locale, width + x, y, text, 0, 0, 12, colors.primary, 0, 0); } else { this->DrawEmboldenedText(width + x, y, text, colors.primary, colors.secondary, 0, 0, 12); } } this->DrawTextAt(controls.fonts, controls.locale, 17, 4, LookupMessage(1720), 0, 0, 12, 0xFFFFFF, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 16, 3, LookupMessage(1720), 0, 0, 12, 0, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 2, 25, LookupMessage(282), 0, 0, 12, 0, 0, 0); const int labelWidth = this->TextWidth(controls.fonts, controls.locale, LookupMessage(1723), 0, 0, 12, 0, 0) + 10; this->unknown_0128->Move(labelWidth, this->geometry.height - barHeight + 5); this->DrawTextAt(controls.fonts, controls.locale, 5, this->geometry.height - barHeight + 5, LookupMessage(1723), 0, 0, 12, 0, 0, 0); this->DrawTextAt( controls.fonts, controls.locale, this->unknown_0128->geometry.width + this->unknown_0128->geometry.x + 5, this->geometry.height - barHeight + 5, "Zeny", 0, 0, 12, 0, 0, 0 ); char grouped[16] = {}; char text[32] = {}; FormatGroupedInteger(g_session.m_zeny, grouped, 16); sprintf(text, "%s Zeny", grouped); this->DrawTextAt(controls.fonts, controls.locale, 5, this->geometry.height - barHeight * 2 + 5, LookupMessage(1722), 0, 0, 12, 0, 0, 0); this->DrawRightAlignedText(155, this->geometry.height - barHeight * 2 + 5, text, 0, 0, 12, 0, 0); std::uint32_t color; if (this->unknown_0188 == 1) { sprintf(text, "Max Weight : %3d", g_session.m_maxWeight); color = 0; } else { sprintf(text, "Weight : %3d / %3d", g_session.m_weight, g_session.m_maxWeight); color = g_session.m_weight * 100 / (g_session.m_maxWeight < 1 ? 1 : g_session.m_maxWeight) < 50 ? 0 : 0xFF; } this->DrawRightAlignedText(this->geometry.width - 20, this->geometry.height - barHeight * 2 + 5, text, 0, 0, 12, color, 0); message = LookupMessage(3224); messageY = this->geometry.height - 72; } else { for (int i = 0, y = 72; i < this->visibleRows; ++i, y += 42) { this->DrawTextAt(controls.fonts, controls.locale, this->geometry.width - 165, y - 15, LookupMessage(369), 0, 0, 12, 0, 0, 0); DrawItemSlotBackground(*this, 3, y - 18); if (i >= this->unknown_012C) { continue; } char text[24] = {}; std::strcpy(text, this->priceEdits[this->scroll + i]->Text()); if (g_session.IsNumberWithCommas(text) != 1) { continue; } std::int64_t price = _atoi64(text); if (price <= 0) { continue; } const int x = this->geometry.width - 165; this->DrawTextAt(controls.fonts, controls.locale, x, y, LookupMessage(3222), 0, 0, 12, 0, 0, 0); const int width = this->TextWidth(controls.fonts, controls.locale, LookupMessage(3222), 0, 0, 12, 0, 0); const double rate = PriceCommission(price) * -0.01; price += static_cast(price * rate); FormatGroupedInteger(price, text, 24); const PriceColors colors = PriceColor(price); if (colors.secondary == 0xFFFFFFFF) { this->DrawTextAt(controls.fonts, controls.locale, width + x, y, text, 0, 0, 12, colors.primary, 0, 0); } else { this->DrawEmboldenedText(width + x, y, text, colors.primary, colors.secondary, 0, 0, 12); } } this->DrawTextAt(controls.fonts, controls.locale, 17, 4, LookupMessage(224), 0, 0, 12, 0xFFFFFF, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 16, 3, LookupMessage(224), 0, 0, 12, 0, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 2, 25, LookupMessage(282), 0, 0, 12, 0, 0, 0); message = LookupMessage(3223); messageY = this->geometry.height - 43; } this->DrawTextAt(controls.fonts, controls.locale, 5, messageY, message, 0, 0, 12, 0xFF, 0, 0); ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (index < this->columns * this->scroll) { continue; } if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int top = visible / this->columns * 42; const int column = visible % this->columns * 42; const int x = column + 7; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 48, *it, 0, 0); this->DrawWrappedItemName(column + 39, top + 57, 100, &*it, 0, 0, 12); if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 60, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } if (++visible == this->visibleRows * this->columns) { break; } } } // GLOBAL: gl_25363 bool g_sortPrivateTab; // OFFSET: 0x00990810 // FUNCTION: fn_13428 int UIMerchantItemPurchaseMSGWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { if (message != 6) { return UIFrameWnd::SendMsg(sender, message, a, b, c, d); } switch (a) { case 184: static_cast(g_charViewMode)->SendMsg(83, reinterpret_cast(this->m_controls), this->unknown_00D0, 0, 0); case 185: g_windowMgr.CloseWindow(230); reinterpret_cast(&g_session)->ClearItems1760And1748(); break; } return 0; } // OFFSET: 0x00995170 // OFFSET: 0x00995E10 // FUNCTION: fn_13466 bool UIItemStoreSubWnd::FilterByName1(std::string query) { if (!this->sub_996950()) { return false; } for (auto it = this->items.begin(); it != this->items.end();) { ITEM_INFO item = *it; const std::string& name = item.unknown_0044; auto next = std::next(it); if (!_mbsstr(reinterpret_cast(name.c_str()), reinterpret_cast(query.c_str()))) { this->items.erase(it); } it = next; } return true; } // OFFSET: 0x00996090 // FUNCTION: fn_13467 bool UIItemStoreSubWnd::FilterByName2(std::string query) { if (!this->sub_996AF0()) { return false; } for (auto it = this->items.begin(); it != this->items.end();) { ITEM_INFO item = *it; const std::string& name = item.unknown_0044; if (name.find(query) == std::string::npos) { it = this->items.erase(it); } else { ++it; } } return true; } // OFFSET: 0x00996440 // FUNCTION: fn_13468 bool UIItemStoreSubWnd::FilterByName3(std::string query) { if (!this->sub_996C90()) { return false; } for (auto it = this->items.begin(); it != this->items.end();) { ITEM_INFO item = *it; const std::string& name = item.unknown_0044; if (name.find(query) == std::string::npos) { it = this->items.erase(it); } else { ++it; } } return true; } // OFFSET: 0x00996950 // FUNCTION: fn_13474 bool UIItemStoreSubWnd::sub_996950() { if (this->items.empty()) { return false; } for (std::list::iterator it = this->items.begin(); it != this->items.end(); ++it) { ITEM_INFO item = *it; int highlightColor; std::vector breaks; char text[256]; char* cursor = text; std::size_t remaining = 0x100; char* highlight = nullptr; this->BuildItemName(&item, &highlightColor, &breaks, &cursor, &remaining, &highlight, 1, 0); it->SetName(text); } return true; } // OFFSET: 0x00996AF0 // FUNCTION: fn_13475 bool UIItemStoreSubWnd::sub_996AF0() { if (this->items.empty()) { return false; } for (std::list::iterator it = this->items.begin(); it != this->items.end(); ++it) { ITEM_INFO item = *it; int highlightColor; std::vector breaks; char text[256]; char* cursor = text; std::size_t remaining = 0x100; char* highlight = nullptr; this->BuildItemName(&item, &highlightColor, &breaks, &cursor, &remaining, &highlight, 1, 0); it->SetName(text); } return true; } // OFFSET: 0x00996C90 // FUNCTION: fn_13476 bool UIItemStoreSubWnd::sub_996C90() { if (this->items.empty()) { return false; } for (std::list::iterator it = this->items.begin(); it != this->items.end(); ++it) { ITEM_INFO item = *it; int highlightColor; std::vector breaks; char text[256]; char* cursor = text; std::size_t remaining = 0x100; char* highlight = nullptr; this->BuildItemName(&item, &highlightColor, &breaks, &cursor, &remaining, &highlight, 1, 0); it->SetName(text); } return true; } // OFFSET: 0x00996E30 // OFFSET: 0x00857420 // FUNCTION: fn_10762 void UIEditCtrl3::DecodeLinkFields(const std::string& link, std::vector& fields) { char delimiters[] = "!#$%&'()*+,-/"; const int length = static_cast(link.size()) + 1; if (length < 6) { return; } char* text = new char[length]; strcpy_s(text, length, link.c_str()); std::string value; int optionCount = 0; std::vector options; int cardCount = 0; fields.reserve(23); for (int i = 23; i != 0; --i) { fields.push_back(0); } fields[6] = -1; for (int i = 0; i < 5; ++i) { value += text[i]; } fields[0] = this->DecodeLinkNumber(std::string(value.c_str(), value.size())); value.clear(); value += text[5]; fields[1] = this->DecodeLinkNumber(std::string(value.c_str(), value.size())); value.clear(); int field = 2; for (int position = 6; static_cast(position) < link.size() + 1; ++position) { const char byte = text[position]; if (byte >= '0') { value += byte; continue; } for (unsigned int kind = 0; kind < 14; ++kind) { if (delimiters[kind] != byte) { continue; } if (kind == 7) { if (!value.empty()) { fields[field] = this->DecodeLinkNumber(std::string(value.c_str(), value.size())); } const int size = static_cast(link.size()); cardCount = this->DecodeLinkCards(fields, text, position, delimiters[7], size, 6); } else if (kind == 9) { ++optionCount; if (!value.empty()) { fields[field] = this->DecodeLinkNumber(std::string(value.c_str(), value.size())); } const int size = static_cast(link.size()); this->DecodeLinkOptions(options, text, position, size, delimiters[10], delimiters[11]); } else if (!value.empty()) { fields[field] = this->DecodeLinkNumber(std::string(value.c_str(), value.size())); } value.clear(); field = kind; break; } } if (optionCount) { fields[cardCount + 8] = optionCount; for (unsigned int i = 0; i < options.size(); ++i) { fields[cardCount + 9 + i] = options[i]; } } delete[] text; } // OFFSET: 0x00859220 // FUNCTION: fn_10775 bool UIEditCtrl3::LinkDisplayName(const std::string& encoded, std::string& output) { const bool isTag = encoded.substr(0, 6) == "00000T"; if (isTag) { const int id = ItemLinkMessageId(encoded); if (g_itemTagOwner->unknown_0118 >= id) { const unsigned short codePage = static_cast(g_textCodePage); const TipBoxTitles titles{g_itemTagOwner->m_entries, g_itemTagOwner->m_missing, g_itemTagOwner->m_maximumId, codePage}; titles.Title(id, &output, 17); return true; } return false; } std::vector fields; this->DecodeLinkFields(encoded, fields); ITEM_INFO item; bool decoded; if (this->DecodeItemLink(fields, item)) { output = item.DisplayName(0); decoded = true; } else { decoded = false; } return decoded; } // FUNCTION: fn_13342 void UIMerchantItemShopWnd::Paint() { UIButtonContext& controls = *this->m_controls; this->DrawTitleBar(controls.fonts, controls.locale, false, "", 0); if (this->geometry.height == 17) { return; } unsigned rows = static_cast(this->geometry.height - this->unknown_0118 - 17) / 8 + (static_cast(this->geometry.height - this->unknown_0118 - 17) % 8 != 0); for (int y = 17; rows != 0; --rows, y += 8) { const auto* left = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_left.bmp"))); this->DrawBitmap(0, y, &left->image, false); } rows = static_cast(this->geometry.height - this->unknown_0118 - 17) / 8 + (static_cast(this->geometry.height - this->unknown_0118 - 17) % 8 != 0); for (int y = 17; rows != 0; --rows, y += 8) { const auto* right = static_cast(ResourceMgr::Instance().Load(Resolve("유저인터페이스\\basic_interface\\itemwin_right.bmp"))); this->DrawBitmap(this->geometry.width - right->image.width, y, &right->image, false); } unsigned red, green, blue; SkinPaletteChannels(controls.resources, 2, 2, red, green, blue); this->FillRegion(20, 17, (this->geometry.width - 60) % 32, this->geometry.height - this->unknown_0118 - 17, RGB(red, green, blue)); this->FillRegion( 20, static_cast(this->geometry.height - this->unknown_0118 - 17) / 32 * 32 + 17, this->geometry.width - 24, static_cast(this->geometry.height - this->unknown_0118 - 17) % 32, RGB(red, green, blue) ); this->DrawButtonBar(this->unknown_00B8 != 0 ? 2 : 0, 0, 1); const int columns = (this->geometry.width - 40) / 32; const unsigned slotRows = static_cast(this->geometry.height - this->unknown_0118 - 17) / 32; unsigned slots = slotRows; for (int y = 17; slots != 0; --slots, y += 32) { DrawItemSlotBackground(*this, 40, y); } unsigned fillRed, fillGreen, fillBlue; SkinPaletteChannels(controls.resources, 2, 2, fillRed, fillGreen, fillBlue); this->FillRegion(72, 17, columns * 32 - 32, slotRows * 32, RGB(fillRed, fillGreen, fillBlue)); { std::string actor = static_cast(g_modeMgr.GetGameMode())->ActorName(this->unknown_0100); const char* label = LookupMessage(this->unknown_010C == 0 ? 227 : 1737); char title[128]; if (!actor.empty()) { sprintf(title, "%s - %s", label, actor.c_str()); } else { this->m_context->registration.Add(this); sprintf(title, "%s", label); } this->DrawTextAt(controls.fonts, controls.locale, 17, 3, title, 0, 0, 12, 0xFFFFFF, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, 16, 2, title, 0, 0, 12, 0, 0, 0); } ItemDescriptions descriptions{g_itemDescriptions}; int visible = 0; int index = 0; for (auto it = this->items.begin(); it != this->items.end(); ++it, ++index) { if (g_session.IsPetEgg(std::atoi(it->itemId.c_str())) && it->unknown_005D) { continue; } const int column = visible % this->columns * 32; const int top = visible / this->columns * 32; const int left = column + 40; if (this->hovered == index) { unsigned hoverRed, hoverGreen, hoverBlue; SkinPaletteChannels(controls.resources, 6, 2, hoverRed, hoverGreen, hoverBlue); this->FillRegion(left + 32, top + 19, 191, 28, RGB(hoverRed, hoverGreen, hoverBlue)); } char price[128]; int x; if (this->unknown_010C != 0) { sprintf(price, LookupMessage(182), it->quantity); const int quantityX = this->geometry.width - this->TextWidth(controls.fonts, controls.locale, " 100,000,000Z", 0, 0, 12, 0, 0) - this->TextWidth(controls.fonts, controls.locale, price, 0, 0, 12, 0, 0) - 18; this->DrawTextAt(controls.fonts, controls.locale, quantityX, top + 29, price, 0, 0, 12, 0xFF, 0, 0); x = left + 4; DrawItemIcon(*this, controls.resources, descriptions, x, top + 21, *it, 0); } else { x = column + 44; DrawItemWithQuantity(*this, controls.resources, descriptions, controls.fonts, controls.locale, x, top + 21, *it, 0, 0); } if (it->unknown_0088 > 0) { this->DrawBitmap( x, top + 33, &static_cast( ResourceMgr::Instance().Load(Resolve(FormatOwnedString("유저인터페이스\\grade_enchant\\grade_icon%d.bmp", it->unknown_0088).c_str())) )->image, true ); } int width = this->TextWidth(controls.fonts, controls.locale, "Z", 0, 0, 12, 0, 0); this->DrawTextAt(controls.fonts, controls.locale, this->geometry.width - width - 18, top + 29, "Z", 0, 0, 12, 0, 0, 0); char text[128]; if (it->unknown_0014[0] != it->unknown_0014[1]) { sprintf(text, " %d -> %s ", it->unknown_0014[0], FormatGroupedInteger(static_cast(it->unknown_0014[1]), price, 128)); } else { sprintf(text, " %s ", FormatGroupedInteger(static_cast(it->unknown_0014[0]), price, 128)); } width += this->TextWidth(controls.fonts, controls.locale, text, 0, 0, 12, 0, 0); this->DrawAmount(controls.fonts, controls.locale, static_cast(it->unknown_0014[0]), text, this->geometry.width - width - 18, top + 29); int nameWidth = this->geometry.width - width - left - 66; if (nameWidth > 130) { nameWidth = 130; } this->DrawWrappedItemName(column + 76, top + 29, nameWidth, &*it, 0, 0, 12); ++visible; } if (this->unknown_0118 == 57) { this->DrawButtonBar(3, 0, 1); } if (this->duration != 0) { const int remaining = static_cast(this->startTick + this->duration - timeGetTime()); if (remaining > 0) { const int days = remaining / 86400000; const int hours = remaining / 3600000 % 24; const int minutes = remaining / 60000 % 60; const int seconds = remaining / 1000 % 60; if (remaining <= 60000) { this->DrawTextAt( controls.fonts, controls.locale, 20, this->geometry.height - 50, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 12, 0xFF, 1, 0 ); } else { this->DrawTextAt( controls.fonts, controls.locale, 20, this->geometry.height - 50, FormatOwnedString(LookupMessage(2927), days, hours, minutes, seconds).c_str(), 0, 0, 12, 0, 1, 0 ); } if (this->unknown_010C == 1) { this->notice->Move(170, this->geometry.height - 20); } } } } // OFFSET: 0x00857B60 // FUNCTION: fn_10763 bool UIEditCtrl3::ExtractItemLink(std::string& text, std::string& link, int& position, const char* source) { std::size_t close = text.find(g_itemLinkClose); if (close == std::string::npos) { return false; } do { text = text.substr(0, close); std::size_t open = text.find(g_itemLinkOpen); if (close != std::string::npos && open == std::string::npos) { position += g_itemLinkClose.size(); text = source; text = text.substr(position); return true; } close = text.find(g_itemLinkClose); if (open != std::string::npos) { for (;;) { position += open; text = text.substr(open + g_itemLinkOpen.size()); open = text.find(g_itemLinkOpen); close = text.find(g_itemLinkClose); if (open == std::string::npos) { break; } position += g_itemLinkOpen.size(); } link = text; text = source; std::string name = ""; if (!this->LinkDisplayName(link, name)) { position += link.size() + g_itemLinkOpen.size() + g_itemLinkClose.size(); text = text.substr(position); return true; } text = text.substr(position + link.size() + g_itemLinkOpen.size() + g_itemLinkClose.size()); } } while (close != std::string::npos); return true; } // OFFSET: 0x00971D30 // FUNCTION: fn_13265 void UIMerchantShopMakeWnd::PrintSellList() { auto it = this->items.begin(); char line[256]; char name[256]; char text[24]; char price[32]; char grouped[32]; std::sprintf(line, "====================== SALE LIST ======================"); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x96FFFF, 0, 0, 0); std::memset(name, 0, sizeof(name)); for (unsigned index = 0; index < this->items.size(); ++index, ++it) { const ITEM_INFO& item = *it; char* cursor = name; int capacity = 256; ItemDescriptions descriptions{g_itemDescriptions}; bool languagePrefix = false; WORD language = g_serverLanguage->language; ItemNamingContext naming{{descriptions, g_itemCardNames, *g_playerNameDictionary, languagePrefix, g_serviceType, language}}; if (item.unknown_0060 != 0) { cursor += item.Refine(cursor, capacity, 1); } if (naming.HasCards(item)) { cursor += naming.Prefixes(item, cursor, capacity, 1); cursor += descriptions.Name(item, cursor, capacity, 1); cursor += naming.Suffixes(item, cursor, capacity, 1); naming.Slots(item, cursor, capacity, 1); } else if (item.HasSpecialCard()) { cursor += naming.Star(item, cursor, capacity, 1); cursor += naming.Creator(item, cursor, capacity, 1); cursor += naming.Element(item, cursor, capacity, 1); descriptions.Name(item, cursor, capacity, 1); } else { cursor += descriptions.Name(item, cursor, capacity, 1); naming.Slots(item, cursor, capacity, 1); } std::sprintf(text, "%s ", this->priceEdits[index]->Text()); g_session.IsNumberWithCommas(text); if (std::atoi(text) > 1000000000) { std::sprintf(price, "1,000,000,000"); } else { std::sprintf(price, "%s", FormatGroupedInteger(std::atoi(text), grouped, 32)); } std::sprintf(line, " %s : %s Zeny", name, price); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x5AFFFF, 0, 0, 0); const double rate = PriceCommission(_atoi64(text)) * 0.01; const std::int64_t commission = static_cast(_atoi64(text) * rate); const std::string notice = FormatOwnedString("Commission : 1 EA = %s Zeny", FormatGroupedInteger(commission, line, 256)); g_windowMgr.SendNotice(1, reinterpret_cast(notice.c_str()), 0x5AFFFF, 0, 0, 0); } std::sprintf(price, "%s", FormatGroupedInteger(g_session.m_zeny, grouped, 32)); std::sprintf(line, " Current Zeny : %s Z", price); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x78FFFF, 0, 0, 0); std::sprintf(line, "============================ ============================"); g_windowMgr.SendNotice(1, reinterpret_cast(line), 0x96FFFF, 0, 0, 0); } // OFFSET: 0x00985160 // OFFSET: 0x00985610 // OFFSET: 0x00988590 // OFFSET: 0x0097EDE0 // OFFSET: 0x0097F790 // OFFSET: 0x0098CBF0 // FUNCTION: fn_13422 int UIItemSellWnd::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: { reinterpret_cast(this)->Record(this->geometry.id, static_cast(a), b, c, d); CMode* mode = g_modeMgr.gameMode; if (a == 184) { if (g_session.HasRequiredItems()) { mode->SendMsg(35, 0, 0, 0, 0); } } else if (a != 185) { break; } g_windowMgr.CloseWindow(22); g_windowMgr.CloseWindow(24); mode->SendMsg(40, 0, 0, 0, 0); reinterpret_cast(&g_session)->ClearTradeItems(); return 0; } case 14: if (a == 3) { int width = b <= 320 ? b : 320; int height = c <= 336 ? c : 336; if (width < 232) { width = 232; } if (height < 120) { height = 120; } const int newWidth = (width - 280) / 32 * 32 + 280; const int newHeight = (height - 120) / 32 * 32 + 120; if (newWidth != this->geometry.width || newHeight != this->geometry.height) { this->Resize(newWidth, newHeight); this->columns = 1; this->visibleRows = (newHeight - 38) / 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, this->geometry.height - 38); this->UpdateScrollBar(); } this->total->Move(12, this->geometry.height - 20); const int positions[2][2] = { {this->geometry.width - 106, this->geometry.height - 24}, {this->geometry.width - 61, this->geometry.height - 24}, }; for (int i = 0; i < 2; ++i) { this->buttons[i]->Move(positions[i][0], positions[i][1]); } this->m_frameContext->snapping.Store(this); return 0; } break; case 23: { this->items.erase(this->items.begin(), this->items.end()); int totalPrice = 0; const int size = reinterpret_cast(&g_session)->GetList4Size(); for (int i = 0; i < size; ++i) { ITEM_INFO item = g_session.GetItem1730At(i); if (item.unknown_0000[1] != 0) { totalPrice += item.quantity * item.unknown_0014[1]; this->items.push_back(item); } } char grouped[64]; char text[80]; std::sprintf(text, "Total : %s Zeny", FormatGroupedInteger(totalPrice, grouped, sizeof(grouped))); this->total->SetTextAutoWidth(text); this->Invalidate(); this->UpdateScrollBar(); return 0; } case 34: this->saved = reinterpret_cast(a); if (!this->saved->IsValid()) { this->saved->Reset(); } this->SendMsg(nullptr, 14, 3, 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()); ModeDragState& drag = mode->drag; ITEM_INFO item; item.Assign(reinterpret_cast(drag)); if (g_session.HasItem1718(drag.id)) { ClientItemLists* lists = reinterpret_cast(&g_session); lists->AddItem1730(item); lists->ReduceItem1718(item); if (g_windowMgr.unknown_0250) { g_windowMgr.unknown_0250->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); } mode->SendMsg(18, 0, 0, 0, 0); return 0; } case 123: { const auto* bytes = reinterpret_cast(a); ItemListChunkHeader header = *reinterpret_cast(bytes); unsigned offset = 6; if (header.type == 20750) { while (static_cast(b) > offset) { header = *reinterpret_cast(bytes + offset); offset += 6; if (header.type == 20751) { UIWindow* window = g_windowMgr.EnsureWindow(22); if (window) { window->SendMsg(nullptr, 36, 1, 0, 0, 0); window->SendMsg(nullptr, 23, 0, 0, 0, 0); } this->SendMsg(nullptr, 23, 0, 0, 0, 0); break; } offset += header.size; } } break; } default: return UIItemBaseWnd::SendMsg(sender, message, a, b, c, d); } return 0; }