diff --git a/Source/Contents/Party/PartyBookingInfo.h b/Source/Contents/Party/PartyBookingInfo.h new file mode 100644 index 00000000..50e1b373 --- /dev/null +++ b/Source/Contents/Party/PartyBookingInfo.h @@ -0,0 +1,21 @@ +#ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYBOOKINGINFO_H +#define RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYBOOKINGINFO_H + +#include + +struct PARTY_BOOKING_DETAIL { + /* 0000 */ short level; + /* 0002 */ short mapId; + /* 0004 */ short job[6]; +}; + +struct PARTY_BOOKING_AD_INFO { + /* 0000 */ int index; + /* 0004 */ char charName[24]; + /* 001C */ __time32_t expireTime; + /* 0020 */ PARTY_BOOKING_DETAIL detail; +}; + +static_assert(sizeof(PARTY_BOOKING_AD_INFO) == 0x30); + +#endif diff --git a/Source/Contents/Party/PartyBookingMgr.cpp b/Source/Contents/Party/PartyBookingMgr.cpp index 460c5b4f..3dd92f2e 100644 --- a/Source/Contents/Party/PartyBookingMgr.cpp +++ b/Source/Contents/Party/PartyBookingMgr.cpp @@ -2,6 +2,9 @@ #include "Client/Session.h" #include "Contents/MessageTable.h" +#include "Contents/Sound/SoundMgr.h" +#include "UI/Window/UISeekPartyListWnd.h" +#include "UI/Window/UIWindowMgr.h" #include #include @@ -24,6 +27,52 @@ void PartyBookingMgr::Clear() { // OFFSET: 0x00B16CF0 +// OFFSET: 0x00B175B0 +// FUNCTION: fn_18448 +void PartyBookingMgr::OnAdvertisement(PARTY_BOOKING_AD_INFO info) { + UISeekPartyListWnd* window = static_cast(g_windowMgr.LookupWindow(0xA9)); + if (window) { + if (window->MatchesFilter(info)) { + if (!this->m_lastPage) { + this->AddEntries(&info, 1, false); + window->NotifyNewAd(); + } else { + std::pair result = this->MakeEntry(info); + if (result.first) { + this->m_pending.insert(std::pair(info.index, result.second)); + } + window->NotifyNewAd(); + } + } + return; + } + + if (this->m_filterEnabled) { + PARTY_BOOKING_AD_INFO ad = info; + if (this->m_filterLevel > 0 && (ad.detail.level < this->m_filterLevel || this->m_filterLevel + 15 < ad.detail.level)) { + return; + } + + if (this->m_filterMap > 0 && this->m_filterMap != ad.detail.mapId) { + return; + } + + if (this->m_filterJob > 0) { + int i = 0; + while (this->m_filterJob != ad.detail.job[i]) { + if (++i >= 6) { + return; + } + } + } + } + + if (this->m_alarm) { + g_soundMgr->PlayWave("party_alarm.wav", 0.0f, 0.0f, 0.0f, 250, 40, 1.0f, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(0x6D9)), 0xFFFF00, 15, 0, 0); + } +} + // OFFSET: 0x00B17820 // OFFSET: 0x00B17C40 diff --git a/Source/Contents/Party/PartyBookingMgr.h b/Source/Contents/Party/PartyBookingMgr.h index 71cdd95c..2f2e695a 100644 --- a/Source/Contents/Party/PartyBookingMgr.h +++ b/Source/Contents/Party/PartyBookingMgr.h @@ -1,6 +1,8 @@ #ifndef RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYBOOKINGMGR_H #define RAGNAROK_SOURCE_CONTENTS_PARTY_PARTYBOOKINGMGR_H +#include "Contents/Party/PartyBookingInfo.h" + #include #include #include @@ -8,21 +10,6 @@ #include #include -struct PARTY_BOOKING_DETAIL { - /* 0000 */ short level; - /* 0002 */ short mapId; - /* 0004 */ short job[6]; -}; - -struct PARTY_BOOKING_AD_INFO { - /* 0000 */ int index; - /* 0004 */ char charName[24]; - /* 001C */ __time32_t expireTime; - /* 0020 */ PARTY_BOOKING_DETAIL detail; -}; - -static_assert(sizeof(PARTY_BOOKING_AD_INFO) == 0x30); - struct PartyBookingMapInfo { /* 0000 */ std::string name; /* 0018 */ int id; @@ -54,6 +41,7 @@ public: void SetJobs(int index, const short* jobs); bool FlushPending(); void AddEntries(const PARTY_BOOKING_AD_INFO* infos, int count, bool more); + void OnAdvertisement(PARTY_BOOKING_AD_INFO info); std::pair MakeEntry(PARTY_BOOKING_AD_INFO info); /* 0000 */ int unknown_0000; diff --git a/Source/UI/Window/UISeekPartyListWnd.cpp b/Source/UI/Window/UISeekPartyListWnd.cpp new file mode 100644 index 00000000..40a68a61 --- /dev/null +++ b/Source/UI/Window/UISeekPartyListWnd.cpp @@ -0,0 +1,38 @@ +#include "UI/Window/UISeekPartyListWnd.h" + +#include "Contents/MessageTable.h" +#include "Contents/Sound/SoundMgr.h" +#include "UI/Buttons/UICheckBox.h" +#include "UI/Window/UIWindowMgr.h" + +// OFFSET: 0x009431D0 +// FUNCTION: fn_12815 +void UISeekPartyListWnd::NotifyNewAd() { + if (this->m_alarmCheck->geometry.unknown_0030 != 0) { + g_soundMgr->PlayWave("party_alarm.wav", 0.0f, 0.0f, 0.0f, 250, 40, 1.0f, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(0x6D9)), 0xFFFF00, 15, 0, 0); + } +} + +// OFFSET: 0x009435F0 +// FUNCTION: fn_12825 +bool UISeekPartyListWnd::MatchesFilter(PARTY_BOOKING_AD_INFO info) { + if (this->m_filterLevel > 0 && (this->m_filterLevel > info.detail.level || this->m_filterLevel + 15 < info.detail.level)) { + return false; + } + + if (this->m_filterMap > 0 && this->m_filterMap != info.detail.mapId) { + return false; + } + + if (this->m_filterJob > 0) { + for (int i = 0; i < 6; ++i) { + if (this->m_filterJob == info.detail.job[i]) { + return true; + } + } + return false; + } + + return true; +} diff --git a/Source/UI/Window/UISeekPartyListWnd.h b/Source/UI/Window/UISeekPartyListWnd.h new file mode 100644 index 00000000..34f2dada --- /dev/null +++ b/Source/UI/Window/UISeekPartyListWnd.h @@ -0,0 +1,23 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UISEEKPARTYLISTWND_H +#define RAGNAROK_SOURCE_UI_WINDOW_UISEEKPARTYLISTWND_H + +#include "Contents/Party/PartyBookingInfo.h" +#include "UI/Window/UIFrameWnd.h" + +class UICheckBox; + +class UISeekPartyListWnd : public UIFrameWnd { +public: + void NotifyNewAd(); + bool MatchesFilter(PARTY_BOOKING_AD_INFO info); + +protected: + /* 00B4 */ unsigned char unknown_00B4[0x3C]; + /* 00F0 */ UICheckBox* m_alarmCheck; + /* 00F4 */ unsigned char unknown_00F4[0xD0]; + /* 01C4 */ short m_filterLevel; + /* 01C6 */ short m_filterMap; + /* 01C8 */ short m_filterJob; +}; + +#endif diff --git a/data/compile.json b/data/compile.json index 3ff14e92..7f0cfd8c 100644 --- a/data/compile.json +++ b/data/compile.json @@ -757,6 +757,7 @@ "Source/UI/Window/UIControl.cpp": 2, "Source/UI/Window/UIFrameWnd.cpp": 2, "Source/UI/Window/UIMessageBox.cpp": 2, + "Source/UI/Window/UISeekPartyListWnd.cpp": 2, "Source/UI/Window/UIWindow.cpp": 2, "Source/UI/Window/UIWindowMgr.cpp": 2, "Source/UI/Window/WindowAncestry.cpp": 2,