diff --git a/Source/UI/Buttons/UITextButton.h b/Source/UI/Buttons/UITextButton.h index 5782c254..7743f094 100644 --- a/Source/UI/Buttons/UITextButton.h +++ b/Source/UI/Buttons/UITextButton.h @@ -18,6 +18,7 @@ class UITextButton : public UIButton { friend class UIAchSummaryWnd; friend class CCreateLineInfo; friend class UISerachStoreInfoWnd; + friend class UISeekPartyListWnd; public: friend void OpenTextButtonLink(UITextButton* button); diff --git a/Source/UI/Window/UISeekPartyListWnd.cpp b/Source/UI/Window/UISeekPartyListWnd.cpp index af8e2edd..364fc82d 100644 --- a/Source/UI/Window/UISeekPartyListWnd.cpp +++ b/Source/UI/Window/UISeekPartyListWnd.cpp @@ -1,16 +1,239 @@ #include "UI/Window/UISeekPartyListWnd.h" +#include "Client/Session.h" #include "Contents/MessageTable.h" #include "Contents/Party/PartyBookingMgr.h" #include "Contents/Sound/SoundMgr.h" +#include "Contents/UserData/NormalItemSlots.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketId.h" +#include "Network/Packets/PacketLengths.h" #include "Script/LuaScript.h" +#include "UI/Buttons/UIBitmapButton.h" #include "UI/Buttons/UICheckBox.h" +#include "UI/Buttons/UITextButton.h" +#include "UI/Edit/UIEditCtrl.h" #include "UI/Lists/UIComboBoxDefWnd.h" #include "UI/Lists/UIScrollBar.h" +#include "UI/Text/UIStaticText.h" +#include "UI/Window/UISeekPartyWnd.h" #include "UI/Window/UIWindowMgr.h" +#include "UI/Window/WindowDialogs.h" +#include "Utility/Text/FormatString.h" + +#include +#include + +namespace { +#pragma pack(push, 1) +struct PACKET_CZ_PARTY_BOOKING_REQ_SEARCH { + /* 0000 */ short packetType; + /* 0002 */ short level; + /* 0004 */ short mapId; + /* 0006 */ short job; + /* 0008 */ int lastIndex; + /* 000C */ short pageSize; +}; +#pragma pack(pop) +} // GLOBAL: gl_24771 std::map g_friendRows; +// OFFSET: 0x00925D70 + +// OFFSET: 0x009393E0 +// FUNCTION: fn_12755 +int UISeekPartyListWnd::SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) { + WindowDialogs& dialogs = *reinterpret_cast(&g_windowMgr); + + switch (message) { + case 6: + switch (argument1) { + case 201: + g_session.m_partyBooking.m_alarm = this->m_alarmCheck->geometry.unknown_0030 != 0; + g_windowMgr.CloseWindow(0xA9); + return 0; + case 202: + if (this->m_minimized) { + this->Resize(this->geometry.width, this->m_restoreHeight); + } else { + this->m_restoreHeight = this->geometry.height; + this->Resize(this->geometry.width, 17); + } + this->m_minimized = !this->m_minimized; + this->Invalidate(); + return 0; + case 284: + this->Invalidate(); + return 0; + case 343: + g_windowMgr.EnsureWindow(0xAD); + return 0; + case 365: + case 380: { + std::string text(this->m_searchEdit->Text()); + const short level = static_cast(std::atoi(text.c_str())); + for (std::size_t i = 0; i < text.size(); ++i) { + if (text[i] < '/' || text[i] > '9') { + dialogs.Confirm(LookupMessage(1770), 0, true, false, 0, "Message", 280, 120, 0); + return 0; + } + } + + if (level < 0 || level > g_partyBookingLevelMax) { + char buffer[260]; + std::memset(buffer, 0, sizeof(buffer)); + StringFormat(buffer, sizeof(buffer), static_cast(-1), LookupMessage(2601), g_partyBookingLevelMax); + dialogs.Confirm(buffer, 0, true, false, 0, "Message", 280, 120, 0); + return 0; + } + + short mapId = 0; + if (this->m_region != 0) { + mapId = static_cast((this->m_region << 8) | this->m_mapIndex); + } + + const int jobOffsets[9] = {0, 1, 5, 11, 24, 30, 37, 43, 56}; + short job = -1; + if (this->m_jobCategory != 0) { + job = static_cast(this->m_jobCategoryChanged + jobOffsets[this->m_jobCategory] - 1); + } + + int lastIndex = 0; + if (argument1 == 365) { + if (this->m_filterJob == job && this->m_filterLevel == level && this->m_filterMap == mapId) { + return 0; + } + g_session.m_partyBooking.Clear(); + } else { + if (!g_session.m_partyBooking.m_lastPage) { + g_session.m_partyBooking.FlushPending(); + return 0; + } + lastIndex = g_session.m_partyBooking.m_lastIndex; + } + + PACKET_CZ_PARTY_BOOKING_REQ_SEARCH packet; + packet.packetType = ID_CZ_PARTY_BOOKING_REQ_SEARCH; + packet.level = level; + packet.mapId = mapId; + packet.job = job; + packet.lastIndex = lastIndex; + packet.pageSize = 10; + GetRagConnection().Send(g_packetLengths.FixedLength(packet.packetType), &packet); + + this->m_filterJob = job; + this->m_filterLevel = level; + this->m_filterMap = mapId; + + std::string title(LookupMessage(0x6E5)); + if (level > 0) { + title += " Level: "; + title += IntToString(level, 0); + } + + if (this->m_region != 0) { + title += " Map: "; + title += this->m_regionCombo->GetSelectedText(); + title += " "; + title += this->m_mapCombo->GetSelectedText(); + } + + if (this->m_jobCategory != 0) { + title += " Job: "; + title += this->m_jobCombo->GetSelectedText(); + } + + this->m_title->SetTextFitted(title.c_str()); + + g_session.m_partyBooking.SetFilter(this->m_filterLevel, this->m_filterMap, this->m_filterJob); + this->Invalidate(); + return 0; + } + case 381: { + const int hoverIndex = this->m_hoverIndex; + if (hoverIndex == -1) { + return 0; + } + + const int firstIndex = this->m_firstRow * this->m_columnCount; + int index = 0; + for (auto it = g_friendRows.begin(); it != g_friendRows.end(); ++it, ++index) { + if (index < firstIndex || index != hoverIndex) { + continue; + } + + const PartyBookingEntry entry = it->second; + if (entry.isEnd) { + this->SendMsg(nullptr, 6, 0x17C, 0, 0, 0); + g_session.m_partyBooking.EraseEntry(it->first); + } else { + const std::string leaderName = entry.leaderName; + if (std::strcmp(leaderName.c_str(), g_session.DecodePlayerName()) != 0) { + g_windowMgr.SendNotice(14, reinterpret_cast(leaderName.c_str()), 0, 0, 0, 0); + } + } + return 0; + } + return 0; + } + default: + return 0; + } + case 7: + case 9: + case 10: { + const int previous = this->m_firstRow; + int next; + if (message == 9) { + next = previous - this->m_visibleRows + 1; + } else if (message == 10) { + next = previous + this->m_visibleRows - 1; + } else { + next = static_cast(argument1) + previous; + } + + this->m_firstRow = next; + if (previous != next) { + this->UpdateScrollBar(); + this->Invalidate(); + next = this->m_firstRow; + } + return next - previous; + } + case 34: + this->m_saved = reinterpret_cast(argument1); + if (!this->m_saved->IsValid()) { + this->m_saved->Reset(); + } + + this->Move(this->m_saved->x, this->m_saved->y); + this->SendMsg(nullptr, 14, 3, this->m_saved->width, this->m_saved->height, 0); + this->SendMsg(nullptr, 23, 0, 0, 0, 0); + return 0; + case 39: + if (sender == this->m_regionCombo) { + this->SelectRegion(static_cast(argument1) + 1); + this->m_region = static_cast(argument1); + } else if (sender == this->m_mapCombo) { + this->m_mapIndex = static_cast(argument1); + } else if (sender == this->m_jobCategoryCombo) { + this->SelectJobCategory(static_cast(argument1)); + } else if (sender == this->m_jobCombo) { + this->m_jobCategoryChanged = static_cast(argument1) + 1; + } + return 0; + case 98: + if (argument1 != 378 || g_windowMgr.CloseWindow(0xA8)) { + return 0; + } + g_windowMgr.EnsureWindow(0xA8); + return 0; + default: + return UIFrameWnd::SendMsg(sender, message, argument1, argument2, argument3, argument4); + } +} + // OFFSET: 0x009431D0 // FUNCTION: fn_12815 void UISeekPartyListWnd::NotifyNewAd() { diff --git a/Source/UI/Window/UISeekPartyListWnd.h b/Source/UI/Window/UISeekPartyListWnd.h index 7691d5e9..a3ee8c4a 100644 --- a/Source/UI/Window/UISeekPartyListWnd.h +++ b/Source/UI/Window/UISeekPartyListWnd.h @@ -9,9 +9,13 @@ #include #include +class UIBitmapButton; class UICheckBox; class UIComboBoxDefWnd; +class UIEditCtrl; class UIScrollBar; +class UIStaticText; +class UITextButton; struct SeekPartyListWndInfo; extern std::map g_friendRows; @@ -24,10 +28,12 @@ struct SeekPartyMapEntry { class UISeekPartyListWnd : public UIFrameWnd { public: void Slot11() override; + void Slot15(int width, int height) override; void Paint() override; void Slot25(int x, int y) override; void Slot26(int x, int y) override; void Slot35(int delta) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; void NotifyNewAd(); void UpdateScrollBar(); bool MatchesFilter(PARTY_BOOKING_AD_INFO info); @@ -39,18 +45,30 @@ public: protected: int HitTestRow(int x, int y); - /* 00BC */ unsigned char unknown_00BC[0x24]; + /* 00B4 */ UIStaticText* m_title; + /* 00B8 */ UIStaticText* m_levelLabel; + /* 00BC */ UIStaticText* m_mapLabel; + /* 00C0 */ UIStaticText* m_jobLabel; + /* 00C4 */ UIStaticText* m_filterLabel0; + /* 00C8 */ UIStaticText* m_filterLabel1; + /* 00CC */ UIStaticText* m_filterLabel2; + /* 00D0 */ UIStaticText* m_filterLabel3; + /* 00DC */ UIEditCtrl* m_searchEdit; /* 00E0 */ UIComboBoxDefWnd* m_regionCombo; /* 00E4 */ UIComboBoxDefWnd* m_mapCombo; /* 00E8 */ UIComboBoxDefWnd* m_jobCategoryCombo; /* 00EC */ UIComboBoxDefWnd* m_jobCombo; /* 00F0 */ UICheckBox* m_alarmCheck; - /* 00F4 */ unsigned char unknown_00F4[0x14]; + /* 00F4 */ UIBitmapButton* m_findButton; + /* 00F8 */ UIBitmapButton* m_okButton; + /* 00FC */ UIBitmapButton* m_chatButton; + /* 0100 */ UITextButton* m_refreshButton; + /* 0104 */ UIBitmapButton* m_tabButton; /* 0108 */ UIScrollBar* m_scrollBar; /* 010C */ unsigned char unknown_010C[0x4]; /* 0110 */ std::map> m_regionMaps; /* 0118 */ std::vector m_jobOptions[9]; - /* 0184 */ int unknown_0184; + /* 0184 */ int m_region; /* 0188 */ int m_mapIndex; /* 018C */ int m_jobCategory; /* 0190 */ int m_jobCategoryChanged; @@ -61,7 +79,7 @@ protected: /* 01B0 */ int m_visibleRows; /* 01B4 */ int unknown_01B4; /* 01B8 */ int m_scrollable; - /* 01BC */ unsigned char unknown_01BC[0x4]; + /* 01BC */ int m_restoreHeight; /* 01C0 */ unsigned char m_minimized; /* 01C1 */ unsigned char unknown_01C1[0x3]; /* 01C4 */ short m_filterLevel;