#include "UI/Quest/UIQuestDisplay.h" #include "Client/Input/Mouse.h" #include "Contents/MessageTable.h" #include "Contents/RenewQuestMgr.h" #include "Contents/UserData/NormalItemSlots.h" #include "Network/Connection/Connection.h" #include "Network/Packets/PacketLengths.h" #include "Render/Renderer.h" #include "UI/Window/UIWindowMgr.h" #include "UI/Window/WindowManagerWindows.h" #include "UI/Text/ColoredText.h" #include "UI/Text/NavigationLink.h" #include "UI/Text/TextMarkup.h" #include "UI/Text/UITextViewer.h" #include "Utility/Text/FormatString.h" #include #include #pragma pack(push, 1) struct PACKET_CZ_ACTIVE_QUEST { short packetType; unsigned int questId; unsigned char active; }; #pragma pack(pop) // OFFSET: 0x00948D10 // FUNCTION: fn_12881 void UIQuestDisplay::Create(int width, int height) { this->SetSize(width, height); } // OFFSET: 0x0094A400 // FUNCTION: fn_12887 bool UIQuestDisplay::Slot08() { return true; } // OFFSET: 0x0094D910 // FUNCTION: fn_12911 void UIQuestDisplay::Paint() { this->ClearSurface(0xFF00FF); CRenewQuestMgr* manager = g_renewQuestMgr; int none = 0; int multiple = 0; int single = 0; for (auto it = manager->m_ongoingQuests.begin(); it != manager->m_ongoingQuests.end(); ++it) { const unsigned int questId = it->first; const RenewQuestOngoingInfo& info = it->second; if (info.m_active != true || info.m_simpleView != true) { continue; } const int top = single * 50 + (none + multiple * 2) * 40; std::string title = info.m_title.size() == 0 ? FormatOwnedString("Unknown Quest, ID = %d", questId) : info.m_title; if (questId == reinterpret_cast(this->m_context)) { this->FillRegion(-12, top - 2, this->geometry.width - 10, 40, 0); } this->DrawShadowedText(0, top, title.c_str(), 0, 0xD6E1, 0, 0, 12, 0); std::string description = info.m_descriptions.size() == 0 ? std::string() : info.unknown_004C; description = StripColorCodes(description.c_str(), description.size()); description = static_cast(DisplayUrlTextTag(description)); description = static_cast(DisplayNavigationTextTag(description)); description = static_cast(DisplayTipBoxTextTag(description)); description = static_cast(DisplayItemTextTag(description)); description = static_cast(RemoveTextLinkInfo(description)); if (this->m_context->chatConverter) { description = this->m_context->chatConverter->ConvertChat(description); } std::string navigation; DisplayNavigationLink(navigation, description); description = std::move(navigation); description = static_cast(DisplayQuestTextTag(description)); if (std::strlen(description.c_str()) > 30) { description = this->TruncateText(description.c_str(), 30); description += std::string("..."); } if (std::strlen(description.c_str()) != 0) { this->DrawShadowedText(0, top + 15, description.c_str(), 0, 0xFFFFFF, 0, 0, 12, 0); } if (info.m_huntCount == 0 || info.m_huntCount > 3) { ++none; } else { for (int index = 0; index < info.m_huntCount; ++index) { std::string hunt; if (info.m_huntUnknown00D4[index] == 31999) { hunt = static_cast( g_renewQuestMgr->GetMonsterConditionText(info.m_huntUnknown01A0[index], info.m_huntUnknown01AC[index], info.m_huntUnknown01B2[index]) ); } else { const short minLevel = info.m_huntUnknown01AC[index]; const short maxLevel = info.m_huntUnknown01B2[index]; const char* name = info.m_huntName[index]; if (minLevel < 0 || maxLevel < 0 || (minLevel == 0 && maxLevel == 0)) { hunt = static_cast(FormatOwnedString("%s", name)); } else if (minLevel == 0) { hunt = static_cast(FormatOwnedString("%s Lv.%d▼", name, maxLevel)); } else if (maxLevel == 0) { hunt = static_cast(FormatOwnedString("%s Lv.%d▲", name, minLevel)); } else { hunt = static_cast(FormatOwnedString("%s Lv.%d~Lv.%d", name, minLevel, maxLevel)); } } hunt = StripColorCodes(hunt.c_str(), hunt.size()); description = static_cast(DisplayUrlTextTag(description)); description = static_cast(DisplayNavigationTextTag(description)); description = static_cast(DisplayTipBoxTextTag(description)); description = static_cast(DisplayItemTextTag(description)); description = static_cast(RemoveTextLinkInfo(description)); if (this->m_context->chatConverter) { description = this->m_context->chatConverter->ConvertChat(description); } std::string huntNavigation; DisplayNavigationLink(huntNavigation, description); description = std::move(huntNavigation); description = static_cast(DisplayQuestTextTag(description)); const short goal = info.m_huntUnknown0180[index]; if (goal > 0) { const short count = info.m_huntUnknown00E0[index]; if (count == goal) { hunt = static_cast(FormatOwnedString("%s ( %s )", hunt.c_str(), LookupMessage(0x7EE))); } else { hunt = static_cast(FormatOwnedString("%s ( %d / %d )", hunt.c_str(), count, goal)); } const int y = index * 13 + top; this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 11, y + 29, hunt.c_str(), 0, 0, 12, 0, 0, 0); this->DrawTextAt(this->m_context->fonts, this->m_context->locale, 10, y + 28, hunt.c_str(), 0, 0, 12, 0xFFFFFF, 0, 0); } } if (info.m_huntCount > 1) { ++multiple; } else { ++single; } } if (single + multiple + none >= 5) { break; } } } // OFFSET: 0x0094F1D0 // FUNCTION: fn_12934 void UIQuestDisplay::Slot33(int x, int y) { const int previous = this->m_selectedIndex; int selected = -1; int single = 0; int none = 0; int multiple = 0; int index = 0; const auto end = g_renewQuestMgr->m_ongoingQuests.end(); for (auto it = g_renewQuestMgr->m_ongoingQuests.begin(); it != end; ++it, ++index) { if (single + multiple + none >= 5) { break; } const int top = single * 50 + (none + multiple * 2) * 40; const RenewQuestOngoingInfo& info = it->second; if (info.m_active && info.m_simpleView) { if (top <= y && y <= top + 10) { selected = index; break; } if (info.m_huntCount == 0) { ++none; } else if (info.m_huntCount > 1) { ++multiple; } else { ++single; } } } this->m_selectedIndex = selected; if (previous != this->m_selectedIndex) { this->Invalidate(); } if (this->m_selectedIndex != -1) { this->SendMsg(nullptr, 49, 0, 0, 0, 0); } } // OFFSET: 0x009515D0 // FUNCTION: fn_12953 void UIQuestDisplay::Slot11() { if (this->m_visibleSetting) { *this->m_visibleSetting = this->geometry.visible; } } // OFFSET: 0x00950BC0 // FUNCTION: fn_12947 int UIQuestDisplay::SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) { switch (message) { case 34: { this->m_visibleSetting = reinterpret_cast(argument1); QuestDisplayInfo* info = reinterpret_cast(argument1); if (!info->IsValid()) { info->Reset(); } this->Show(*this->m_visibleSetting); break; } case 48: { int index = 0; for (auto it = g_renewQuestMgr->m_ongoingQuests.begin(); it != g_renewQuestMgr->m_ongoingQuests.end(); ++it, ++index) { if (index == this->m_selectedIndex) { int command = this->m_menuItems[argument1].command; if (command == 48) { PACKET_CZ_ACTIVE_QUEST packet; packet.packetType = 0x2B6; packet.questId = it->first; packet.active = !it->second.m_active; GetRagConnection().Send(reinterpret_cast(GetRagConnection()).FixedLength(packet.packetType), &packet); this->Invalidate(); } else if (command == 49) { g_renewQuestMgr->sub_67B620(it->first); } break; } } break; } case 49: { this->m_menuItems.clear(); if (g_windowMgr.unknown_0210 != 0) { this->Show(0); } if (this->m_selectedIndex != -1) { std::string text1 = LookupMessage(1622); this->m_menuItems.push_back({text1.c_str(), 49}); std::string text2 = LookupMessage(351); this->m_menuItems.push_back({text2.c_str(), 48}); } if (!this->m_menuItems.empty()) { UIWindow* menu = reinterpret_cast(&g_windowMgr)->EnsureWindow(18); for (size_t i = 0; i < this->m_menuItems.size(); ++i) { menu->SendMsg(nullptr, 31, reinterpret_cast(this->m_menuItems[i].text.c_str()), 0, 0, 0); } menu->SendMsg(nullptr, 83, 204, 0, 0, 0); menu->SendMsg(nullptr, 30, 0, 0, 0, 0); int x = std::max(1, g_mouse.x + 1); int maxX = g_renderer->viewport.width - menu->geometry.width; if (x > maxX) { x = maxX; } int y = std::max(1, g_mouse.y + 1); int maxY = g_renderer->viewport.height - menu->geometry.height; if (y > maxY) { y = maxY; } menu->Move(x, y); } break; } default: return this->UIWindow::SendMsg(sender, message, argument1, argument2, argument3, argument4); } return 0; } // OFFSET: 0x00946EA0 // FUNCTION: fn_12855 UIQuestDisplay::UIQuestDisplay(UIWindowContext& windows) : UIWindow(windows, 0) { }