diff --git a/Source/UI/UIIngredientInfoWnd.h b/Source/UI/UIIngredientInfoWnd.h index feed3669..b81f822c 100644 --- a/Source/UI/UIIngredientInfoWnd.h +++ b/Source/UI/UIIngredientInfoWnd.h @@ -19,8 +19,8 @@ public: void Move(int x, int y) override; void Slot10(int argument1, int argument2, std::intptr_t argument3) override; void Slot25(int x, int y) override; - void Slot26(int x, int y) override; void Slot28(int x, int y) override; + void Slot31(int x, int y) override; void Slot32(int x, int y) override; void Slot35(int argument) override; void Paint() override; diff --git a/Source/UI/UILapineBoxWnd.cpp b/Source/UI/UILapineBoxWnd.cpp index e9fcb703..7634c276 100644 --- a/Source/UI/UILapineBoxWnd.cpp +++ b/Source/UI/UILapineBoxWnd.cpp @@ -16,12 +16,11 @@ #include "UI/Window/WindowManagerWindows.h" #include "Utility/Text/FormatString.h" -#include - #include #include #include #include +#include #include #include #include @@ -83,6 +82,17 @@ void UIIngredientInfoWnd::Slot25(int x, int y) { } // OFFSET: 0x00600940 +// FUNCTION: fn_04164 +void UIIngredientInfoWnd::Slot31(int, int) { + if (this->insufficient != 1) { + this->selected = 1; + this->Invalidate(); + + if (this->parent) { + this->parent->SendMsg(this, 6, 0, 0, 0, 0); + } + } +} // OFFSET: 0x00600980 // FUNCTION: fn_04165 @@ -193,7 +203,52 @@ void UIIngredientInfoWnd::Slot32(int, int) { } } +__declspec(noinline) void UILapineBoxWnd::MaterialPosition(int* out, int index) { + const int count = static_cast(this->items.size()); + if (index < 0 || static_cast(index) >= static_cast(count)) { + out[0] = 0; + out[1] = 0; + return; + } + + int left = count > 5 ? 0x19 : 0x21; + int top = count > 5 ? 0x98 : 0xA2; + if (index >= 5) { + left = 0x2A; + top = 0xB7; + } + left += (index % 5) * 0x22; + out[0] = left; + out[1] = top; +} + +__declspec(noinline) void UILapineBoxWnd::ReadMaterial(ITEM_INFO* out, int x, int y) { + const int count = static_cast(this->items.size()); + for (int index = 0; index < count; ++index) { + int position[2] = {}; + this->MaterialPosition(position, index); + if (x >= position[0] && x <= position[0] + 0x18 && y >= position[1] && y <= position[1] + 0x18) { + new (out) ITEM_INFO(this->items[index]); + return; + } + } + new (out) ITEM_INFO(0); +} + // OFFSET: 0x00600C40 +// FUNCTION: fn_04169 +void UILapineBoxWnd::NotifyWindowAt(int x, int y) { + alignas(ITEM_INFO) unsigned char storage[sizeof(ITEM_INFO)]; + ITEM_INFO& item = *reinterpret_cast(storage); + this->ReadMaterial(&item, x, y); + + if (static_cast(item.unknown_0000[1]) > 0) { + UIWindow* window = g_windowMgr.EnsureWindow(12); + window->SendMsg(nullptr, 0x18, reinterpret_cast(&item), 0, 0, 0); + } + + item.~ITEM_INFO(); +} // OFFSET: 0x00600D00 // FUNCTION: fn_04170 @@ -294,8 +349,148 @@ int UILapineBoxWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std: return 0; } // OFFSET: 0x006011E0 +// FUNCTION: fn_04173 +int UILapineBox_IngredientListWnd::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: + for (UIIngredientInfoWnd* entry : this->items) { + if (sender != entry) { + entry->selected = 0; + entry->Invalidate(); + } + } + this->Invalidate(); + break; + + case 0x17: + for (const ITEM_INFO& material : this->materials) { + const int id = std::atoi(material.itemId.c_str()); + std::vector ids = g_session.FindInventoryIndicesByItemId(id, 1); + for (const int value : ids) { + this->AddIngredient(static_cast(value)); + } + } + + for (UIIngredientInfoWnd* entry : this->items) { + const ITEM_INFO owned = LookupClientItemByIdentity(g_session.m_inventoryItems, entry->item.unknown_0000[1]); + if (owned.unknown_0000[1] == 0) { + entry->Show(0); + } + } + this->SendMsg(this, 0x57, 0, 0, 0, 0); + break; + + case 0x57: { + std::vector& items = this->items; + std::size_t index = 0; + int y = 7; + while (index < items.size()) { + UIIngredientInfoWnd* entry = items[index]; + if (entry->geometry.visible == 0) { + entry->Invalidate(); + items.erase(items.begin() + static_cast(index)); + } else { + entry->Move(0, y); + this->childOrigins[entry] = std::pair(0, y); + SortChildWindows(this); + entry->Invalidate(); + ++index; + y += 0x1E; + } + } + SortChildWindows(this); + this->Invalidate(); + break; + } + + case 0x68: { + UIIngredientInfoWnd* selected = nullptr; + for (UIIngredientInfoWnd* entry : this->items) { + if (static_cast(a) == entry->item.unknown_0000[1]) { + selected = entry; + break; + } + } + if (selected == nullptr) { + return UIWindow::SendMsg(sender, message, a, b, c, d); + } + + std::vector::iterator found = this->materials.end(); + for (std::vector::iterator it = this->materials.begin(); it != this->materials.end(); ++it) { + ITEM_INFO copy(*it); + if (std::atoi(selected->item.itemId.c_str()) == std::atoi(copy.itemId.c_str())) { + found = it; + break; + } + } + + if (found != this->materials.end()) { + if (selected->item.quantity < found->quantity) { + const char* text = FormatString(LookupMessage(0xB52), found->quantity); + this->parent->SendMsg(this, 0x6F, reinterpret_cast(text), 0, 0, 0); + return -1; + } + + if (selected->item.unknown_0060 < found->unknown_0060) { + this->parent->SendMsg(this, 0x6F, reinterpret_cast(LookupMessage(0xB53)), 0, 0, 0); + return -1; + } + + selected->item.quantity -= found->quantity; + if (selected->item.quantity < 1) { + selected->Show(0); + } else { + selected->insufficient = 1; + selected->Invalidate(); + } + this->SendMsg(this, 0x57, 0, 0, 0, 0); + break; + } + break; + } + + default: + break; + } + + return UIWindow::SendMsg(sender, message, a, b, c, d); +} // OFFSET: 0x006016C0 +// FUNCTION: fn_04174 +void UILapineBoxWnd::SetIngredient(int id) { + this->unknown_00C4 = id; + + ITEM_INFO item; + item.SetItemId(id); + + char name[0x104]; + std::memset(name, 0, sizeof(name)); + int capacity = 0x104; + ItemDescriptions descriptions{g_itemDescriptions}; + descriptions.Name(item, name, capacity, 0); + this->title.assign(name, std::strlen(name)); + + int optionCount = 0; + g_luaScript->CallTable("tblLapineDdukddakBox", "set_resource_item_list", "d>d", id, &optionCount); + + int minRefine = 0; + g_luaScript->CallTable("tblLapineDdukddakBox", "get_min_need_refine", "d>d", id, &minRefine); + this->ingredientList->minRefine = minRefine; + + int refine = 0; + g_luaScript->CallTable("tblLapineDdukddakBox", "get_max_need_refine", "d>d", id, &refine); + this->ingredientList->maxRefine = refine; + + this->ingredientList->SendMsg(this, 0x17, 0, 0, 0, 0); + + g_luaScript->CallTable("tblLapineDdukddakBox", "get_need_item_count", "d>d", id, &this->maxItems); + + const char* source = nullptr; + g_luaScript->CallTable("tblLapineDdukddakBox", "get_need_source_string", "d>s", id, &source); + this->description.assign(source, std::strlen(source)); +} // OFFSET: 0x00601BC0 // FUNCTION: fn_04176 diff --git a/Source/UI/UILapineScrollBar.h b/Source/UI/UILapineScrollBar.h index d6698c57..abfb689d 100644 --- a/Source/UI/UILapineScrollBar.h +++ b/Source/UI/UILapineScrollBar.h @@ -90,6 +90,8 @@ public: void NotifyWindowAt(int x, int y); void SetIngredient(int id); void AddMaterial(int id, int quantity); + __declspec(noinline) void ReadMaterial(ITEM_INFO* out, int x, int y); + __declspec(noinline) void MaterialPosition(int* out, int index); // INLINED UIFrameContext& FrameContext() { return *this->m_frameContext;