diff --git a/Source/UI/Quest/UIQuestDisplay.cpp b/Source/UI/Quest/UIQuestDisplay.cpp index 4cf97921..6af26b49 100644 --- a/Source/UI/Quest/UIQuestDisplay.cpp +++ b/Source/UI/Quest/UIQuestDisplay.cpp @@ -19,6 +19,49 @@ struct PACKET_CZ_ACTIVE_QUEST { }; #pragma pack(pop) +// 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() { diff --git a/Source/UI/Quest/UIQuestDisplay.h b/Source/UI/Quest/UIQuestDisplay.h index 675793db..53dc296b 100644 --- a/Source/UI/Quest/UIQuestDisplay.h +++ b/Source/UI/Quest/UIQuestDisplay.h @@ -15,6 +15,7 @@ struct QuestDisplayMenuItem { class UIQuestDisplay : public UIWindow { public: void Slot11() override; + void Slot33(int x, int y) override; int SendMsg(UIWindow* sender, int message, std::intptr_t argument1, std::intptr_t argument2, std::intptr_t argument3, std::intptr_t argument4) override; protected: diff --git a/Source/UI/Text/UIStaticText_LF.cpp b/Source/UI/Text/UIStaticText_LF.cpp new file mode 100644 index 00000000..6373ab3b --- /dev/null +++ b/Source/UI/Text/UIStaticText_LF.cpp @@ -0,0 +1,25 @@ +#include "UI/Text/UIStaticText_LF.h" + +// OFFSET: 0x0094EEA0 +// FUNCTION: fn_12920 +void UIStaticText_LF::Slot25(int x, int y) { + if (this->parent) { + this->parent->Slot25(x, y); + } +} + +// OFFSET: 0x0094EFA0 +// FUNCTION: fn_12925 +void UIStaticText_LF::Slot31(int x, int y) { + if (this->parent) { + this->parent->Slot31(x, y); + } +} + +// OFFSET: 0x0094F300 +// FUNCTION: fn_12936 +void UIStaticText_LF::Slot35(int delta) { + if (this->parent) { + this->parent->Slot35(delta); + } +} diff --git a/Source/UI/Text/UIStaticText_LF.h b/Source/UI/Text/UIStaticText_LF.h new file mode 100644 index 00000000..a13d8fbb --- /dev/null +++ b/Source/UI/Text/UIStaticText_LF.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_UI_TEXT_UISTATICTEXT_LF_H +#define RAGNAROK_SOURCE_UI_TEXT_UISTATICTEXT_LF_H + +#include "UI/Window/UIWindow.h" + +class UIStaticText_LF : public UIWindow { +public: + void Slot25(int x, int y) override; + void Slot31(int x, int y) override; + void Slot35(int delta) override; +}; + +#endif diff --git a/Source/UI/Window/UIDebuffRemoveWnd.cpp b/Source/UI/Window/UIDebuffRemoveWnd.cpp index 8ed0506b..4500bb87 100644 --- a/Source/UI/Window/UIDebuffRemoveWnd.cpp +++ b/Source/UI/Window/UIDebuffRemoveWnd.cpp @@ -12,6 +12,21 @@ struct DebuffRemovePacket { #pragma pack(pop) } +// OFFSET: 0x0094EE60 +// FUNCTION: fn_12917 +void UIDebuffRemoveWnd::Slot25(int x, int y) { +} + +// OFFSET: 0x0094EF00 +// FUNCTION: fn_12922 +void UIDebuffRemoveWnd::Slot31(int x, int y) { +} + +// OFFSET: 0x0094F030 +// FUNCTION: fn_12928 +void UIDebuffRemoveWnd::Slot27(int x, int y) { +} + // OFFSET: 0x00950400 // FUNCTION: fn_12940 int UIDebuffRemoveWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { diff --git a/Source/UI/Window/UIDebuffRemoveWnd.h b/Source/UI/Window/UIDebuffRemoveWnd.h index 0011e51e..04011595 100644 --- a/Source/UI/Window/UIDebuffRemoveWnd.h +++ b/Source/UI/Window/UIDebuffRemoveWnd.h @@ -5,6 +5,9 @@ class UIDebuffRemoveWnd : public UIFrameWnd { public: + void Slot25(int x, int y) override; + void Slot27(int x, int y) override; + void Slot31(int x, int y) override; int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; }; diff --git a/Source/UI/Window/UIMileageWnd.cpp b/Source/UI/Window/UIMileageWnd.cpp index a2fab14d..f7c50808 100644 --- a/Source/UI/Window/UIMileageWnd.cpp +++ b/Source/UI/Window/UIMileageWnd.cpp @@ -1,18 +1,96 @@ #include "UI/Window/UIMileageWnd.h" +#include "Client/Session.h" #include "Contents/Configuration/ServiceOptions.h" +#include "Network/Connection/Connection.h" +#include "Network/Packets/PacketId.h" +#include "UI/Buttons/UIButton.h" +#include "Utility/Text/FormatString.h" +#include +#include #include #include +namespace { +#pragma pack(push, 1) +struct DynamicNpcCreatePacket { + /* 0000 */ std::int16_t id; + /* 0002 */ char name[24]; +}; +#pragma pack(pop) +} + // GLOBAL: gl_24859 int g_mileageWndActive; // GLOBAL: gl_24860 int g_mileageWndPoint; +// GLOBAL: gl_24890 +int g_mileageWndElapsed; + // GLOBAL: gl_24861 int g_mileageWndBonus; +// OFFSET: 0x0094EE70 +// FUNCTION: fn_12918 +void UIMileageWnd::Slot25(int x, int y) { +} + +// OFFSET: 0x0094EF10 +// FUNCTION: fn_12923 +void UIMileageWnd::Slot31(int x, int y) { + if (g_session.unknown_0000 == 20) { + return; + } + + DynamicNpcCreatePacket packet = {ID_CZ_DYNAMICNPC_CREATE_REQUEST}; + StringFormat(packet.name, sizeof(packet.name), static_cast(-1), "GOLDPCCAFE"); + GetRagConnection().Send(sizeof(packet), &packet); +} + +// OFFSET: 0x0094EFC0 +// FUNCTION: fn_12926 +void UIMileageWnd::Slot28(int x, int y) { + if (this->m_tooltip.size() == 0) { + return; + } + + int tipX = 10; + int tipY = -20; + this->ToScreen(tipX, tipY); + this->m_controls->services.Tooltip(this->m_tooltip.c_str(), tipX, tipY, -1, false, true); +} + +// OFFSET: 0x0094F040 +// FUNCTION: fn_12929 +void UIMileageWnd::Slot27(int x, int y) { +} + +// OFFSET: 0x0094F130 +// FUNCTION: fn_12932 +void UIMileageWnd::Slot19() { + if (!this->geometry.visible || this->m_point >= 300 || this->m_remaining == 0) { + return; + } + + const std::uint32_t now = timeGetTime(); + const std::uint32_t elapsed = now - this->m_startTime; + if (elapsed < 1000) { + return; + } + + const std::uint32_t seconds = elapsed / 1000; + this->m_remaining -= seconds; + if (this->m_remaining < 0) { + this->m_remaining = 0; + } + + this->m_startTime = seconds * 1000 - elapsed + now; + this->Invalidate(); + g_mileageWndElapsed = 3600 - this->m_remaining; +} + // OFFSET: 0x00950690 // FUNCTION: fn_12942 int UIMileageWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { diff --git a/Source/UI/Window/UIMileageWnd.h b/Source/UI/Window/UIMileageWnd.h index fdcf67ae..70fc7c17 100644 --- a/Source/UI/Window/UIMileageWnd.h +++ b/Source/UI/Window/UIMileageWnd.h @@ -4,9 +4,17 @@ #include "UI/Window/UIFrameWnd.h" #include +#include + +struct UIButtonContext; class UIMileageWnd : public UIFrameWnd { public: + void Slot19() override; + void Slot25(int x, int y) override; + void Slot27(int x, int y) override; + void Slot28(int x, int y) override; + void Slot31(int x, int y) override; int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; protected: @@ -14,10 +22,13 @@ protected: /* 00B8 */ int m_point; /* 00BC */ int m_remaining; /* 00C0 */ int m_bonus; + /* 00C4 */ std::string m_tooltip; + UIButtonContext* m_controls; }; extern int g_mileageWndActive; extern int g_mileageWndPoint; +extern int g_mileageWndElapsed; extern int g_mileageWndBonus; #endif diff --git a/Source/UI/Window/UINoteWnd.cpp b/Source/UI/Window/UINoteWnd.cpp new file mode 100644 index 00000000..47d0ec9c --- /dev/null +++ b/Source/UI/Window/UINoteWnd.cpp @@ -0,0 +1,30 @@ +#include "UI/Window/UINoteWnd.h" +#include "UI/Lists/UIScrollBar.h" + +// OFFSET: 0x0094EE80 +// FUNCTION: fn_12919 +void UINoteWnd_Scroll::Slot25(int x, int y) { + if (this->parent) { + this->parent->Slot25(x + 23, y + 27); + } +} + +// OFFSET: 0x0094EF80 +// FUNCTION: fn_12924 +void UINoteWnd_Scroll::Slot31(int x, int y) { + if (this->parent) { + this->parent->Slot31(x + 23, y + 27); + } +} + +// OFFSET: 0x0094F2C0 +// FUNCTION: fn_12935 +void UINoteWnd_Scroll::Slot35(int delta) { + if (this->wheelScroll == 1) { + if (delta < 0) { + this->SendMsg(this->scrollBar, 7, 12, 0, 0, 0); + } else { + this->SendMsg(this->scrollBar, 7, -12, 0, 0, 0); + } + } +} diff --git a/Source/UI/Window/UINoteWnd.h b/Source/UI/Window/UINoteWnd.h new file mode 100644 index 00000000..4cdbfed6 --- /dev/null +++ b/Source/UI/Window/UINoteWnd.h @@ -0,0 +1,13 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UINOTEWND_H +#define RAGNAROK_SOURCE_UI_WINDOW_UINOTEWND_H + +#include "UI/UIScrollWnd.h" + +class UINoteWnd_Scroll : public UIScrollWnd { +public: + void Slot25(int x, int y) override; + void Slot31(int x, int y) override; + void Slot35(int delta) override; +}; + +#endif diff --git a/Source/UI/Window/UIOpenMailBoxWnd.cpp b/Source/UI/Window/UIOpenMailBoxWnd.cpp index c741a125..a63f9816 100644 --- a/Source/UI/Window/UIOpenMailBoxWnd.cpp +++ b/Source/UI/Window/UIOpenMailBoxWnd.cpp @@ -3,6 +3,11 @@ #include "UI/Window/UIWindowMgr.h" #include "UI/Window/WindowManagerWindows.h" +// OFFSET: 0x0094F020 +// FUNCTION: fn_12927 +void UIOpenMailBoxWnd::Slot53() { +} + // OFFSET: 0x00950A60 // FUNCTION: fn_12945 int UIOpenMailBoxWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { diff --git a/Source/UI/Window/UIOpenMailBoxWnd.h b/Source/UI/Window/UIOpenMailBoxWnd.h index ea999fa1..2f8fa28b 100644 --- a/Source/UI/Window/UIOpenMailBoxWnd.h +++ b/Source/UI/Window/UIOpenMailBoxWnd.h @@ -6,6 +6,7 @@ class UIOpenMailBoxWnd : public UIFrameWnd { public: int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; + virtual void Slot53(); }; #endif diff --git a/Source/UI/Window/UIOpenRoulletteWnd.cpp b/Source/UI/Window/UIOpenRoulletteWnd.cpp index 1e74c9f5..e670a6eb 100644 --- a/Source/UI/Window/UIOpenRoulletteWnd.cpp +++ b/Source/UI/Window/UIOpenRoulletteWnd.cpp @@ -14,6 +14,11 @@ struct RouletteOpenPacket { #pragma pack(pop) } +// OFFSET: 0x0094F1C0 +// FUNCTION: fn_12933 +void UIOpenRoulletteWnd::Slot19() { +} + // OFFSET: 0x00950B60 // FUNCTION: fn_12946 int UIOpenRoulletteWnd::SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) { diff --git a/Source/UI/Window/UIOpenRoulletteWnd.h b/Source/UI/Window/UIOpenRoulletteWnd.h index e1a53eb0..1f8199e2 100644 --- a/Source/UI/Window/UIOpenRoulletteWnd.h +++ b/Source/UI/Window/UIOpenRoulletteWnd.h @@ -5,6 +5,7 @@ class UIOpenRoulletteWnd : public UIFrameWnd { public: + void Slot19() override; int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; }; diff --git a/Source/UI/Window/UIRPImageWnd2.cpp b/Source/UI/Window/UIRPImageWnd2.cpp new file mode 100644 index 00000000..9106909e --- /dev/null +++ b/Source/UI/Window/UIRPImageWnd2.cpp @@ -0,0 +1,14 @@ +#include "UI/Window/UIRPImageWnd2.h" + +// OFFSET: 0x0094EAF0 +// FUNCTION: fn_12912 +void UIRPImageWnd2::Paint() { + if (this->m_drawImage != 1) { + return; + } + + this->SetSolid(this->m_context->primitives, this->geometry.width, this->geometry.height, 0); + for (int i = 0; i < this->m_imageCount; ++i) { + this->DrawNamed(this->m_context->primitives, 0, 0, this->m_imageName, 0xFFFFFFFF, 0, 0); + } +} diff --git a/Source/UI/Window/UIRPImageWnd2.h b/Source/UI/Window/UIRPImageWnd2.h new file mode 100644 index 00000000..ad4ace61 --- /dev/null +++ b/Source/UI/Window/UIRPImageWnd2.h @@ -0,0 +1,18 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UIRPIMAGEWND2_H +#define RAGNAROK_SOURCE_UI_WINDOW_UIRPIMAGEWND2_H + +#include "UI/Window/UIFrameWnd.h" + +#include + +class UIRPImageWnd2 : public UIFrameWnd { +public: + void Paint() override; + +protected: + /* 00B4 */ std::string m_imageName; + /* 00CC */ int m_imageCount; + /* 00D0 */ unsigned char m_drawImage; +}; + +#endif diff --git a/Source/UI/Window/UIShowWarpWnd.cpp b/Source/UI/Window/UIShowWarpWnd.cpp new file mode 100644 index 00000000..a80d3862 --- /dev/null +++ b/Source/UI/Window/UIShowWarpWnd.cpp @@ -0,0 +1,7 @@ +#include "UI/Window/UIShowWarpWnd.h" + +// OFFSET: 0x0094ECE0 +// FUNCTION: fn_12914 +void UIShowWarpWnd::Paint() { + this->DrawBorder(0, 0, 0, 0); +} diff --git a/Source/UI/Window/UIShowWarpWnd.h b/Source/UI/Window/UIShowWarpWnd.h new file mode 100644 index 00000000..cd92973b --- /dev/null +++ b/Source/UI/Window/UIShowWarpWnd.h @@ -0,0 +1,11 @@ +#ifndef RAGNAROK_SOURCE_UI_WINDOW_UISHOWWARPWND_H +#define RAGNAROK_SOURCE_UI_WINDOW_UISHOWWARPWND_H + +#include "UI/Window/UIFrameWnd.h" + +class UIShowWarpWnd : public UIFrameWnd { +public: + void Paint() override; +}; + +#endif diff --git a/Source/UI/Window/UITransMenuWnd.cpp b/Source/UI/Window/UITransMenuWnd.cpp index 770fcd77..62ec1124 100644 --- a/Source/UI/Window/UITransMenuWnd.cpp +++ b/Source/UI/Window/UITransMenuWnd.cpp @@ -1,4 +1,69 @@ #include "UI/Window/UITransMenuWnd.h" +#include "UI/Buttons/UIButton.h" + +// OFFSET: 0x0094ED40 +// FUNCTION: fn_12916 +void UITransMenuWnd::Paint() { + this->ClearSurface(0xFFFF00FF); + if (this->m_items.begin() == this->m_items.end()) { + return; + } + + const int cellHeight = (this->geometry.height - 2 * this->m_margin) / this->m_items.size(); + for (unsigned i = 0; i < this->m_items.size(); ++i) { + std::uint32_t color = this->m_items[i].enabled ? 0xFFFFFF : 0x646464; + if (i == this->m_selected) { + color = 0x282828; + const int half = this->m_margin / 2; + this->FillRegion(0, (i - 1) * half + cellHeight * i + this->m_margin, this->geometry.width, cellHeight + half, 0xC8C8C8); + } + + auto& controls = *this->m_controls; + const int margin = this->m_margin; + this->DrawTextAt(controls.fonts, controls.locale, margin, (margin / 2 + cellHeight) * i + margin, this->m_items[i].text, 0, 0, this->m_lineHeight, color, 0, 0); + } +} + +// OFFSET: 0x0094EEC0 +// FUNCTION: fn_12921 +void UITransMenuWnd::Slot25(int x, int y) { + if (this->m_selected == -1) { + return; + } + + const TransMenuItem& item = this->m_items[this->m_selected]; + if (item.enabled) { + this->SendMsg(nullptr, 48, item.command, 0, 0, 0); + } +} + +// OFFSET: 0x0094F050 +// FUNCTION: fn_12930 +void UITransMenuWnd::Slot27(int x, int y) { + const int margin = this->m_margin; + const int previous = this->m_selected; + int selected = -1; + if (margin <= y) { + const unsigned count = this->m_items.size(); + if ((this->m_lineHeight + margin / 2) * count + margin >= static_cast(y)) { + const int cellHeight = (this->geometry.height - 2 * margin) / count; + selected = (y - margin) / cellHeight; + } + } + + this->m_selected = selected; + if (previous != selected && selected != -1) { + this->Invalidate(); + } +} + +// OFFSET: 0x0094F380 +// FUNCTION: fn_12937 +void UITransMenuWnd::Resize(int width, int height) { + this->UIWindow::Resize(width, height); + this->m_width = this->geometry.width; + this->m_height = this->geometry.height; +} // OFFSET: 0x00951440 // FUNCTION: fn_12950 diff --git a/Source/UI/Window/UITransMenuWnd.h b/Source/UI/Window/UITransMenuWnd.h index 732d2b7e..8c0c1378 100644 --- a/Source/UI/Window/UITransMenuWnd.h +++ b/Source/UI/Window/UITransMenuWnd.h @@ -3,9 +3,41 @@ #include "UI/Window/UIFrameWnd.h" -class UITransMenuWnd : public UIFrameWnd { -public: - int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; +#include + +struct UIButtonContext; + +struct TransMenuItem { + /* 0000 */ char text[24]; + /* 0018 */ int command; + /* 001C */ bool enabled; }; +class UITransMenuWnd : public UIFrameWnd { +public: + void Resize(int width, int height) override; + void Paint() override; + void Slot25(int x, int y) override; + void Slot27(int x, int y) override; + int SendMsg(UIWindow* sender, int message, std::intptr_t a, std::intptr_t b, std::intptr_t c, std::intptr_t d) override; + +protected: + /* 00B4 */ std::vector m_items; + /* 00C0 */ std::uint32_t unknown_00C0; + /* 00C4 */ std::uint32_t unknown_00C4; + /* 00C8 */ int m_width; + /* 00CC */ int m_height; + /* 00D0 */ std::uint32_t unknown_00D0; + /* 00D4 */ std::uint32_t unknown_00D4; + /* 00D8 */ std::uint32_t unknown_00D8; + /* 00DC */ int m_lineHeight; + /* 00E0 */ int m_margin; + /* 00E4 */ int m_selected; + UIButtonContext* m_controls; +}; + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(TransMenuItem) == 0x20); +#endif + #endif diff --git a/data/compile.json b/data/compile.json index d90a9002..3997c101 100644 --- a/data/compile.json +++ b/data/compile.json @@ -862,6 +862,7 @@ "Source/UI/Text/UIAchWnd.cpp": 2, "Source/UI/Text/UIBalloonText.cpp": 2, "Source/UI/Text/UIStaticText.cpp": 2, + "Source/UI/Text/UIStaticText_LF.cpp": 2, "Source/UI/Text/UITagTextViewer.cpp": 2, "Source/UI/Text/UITextViewer.cpp": 2, "Source/UI/Text/UITextViewerLinks.cpp": 2, @@ -910,13 +911,16 @@ "Source/UI/Window/UINavigationWnd.cpp": 2, "Source/UI/Window/UINewSelectCharWnd.cpp": 2, "Source/UI/Window/UINormalMB.cpp": 2, + "Source/UI/Window/UINoteWnd.cpp": 2, "Source/UI/Window/UIOpenMailBoxWnd.cpp": 2, "Source/UI/Window/UIOpenRoulletteWnd.cpp": 2, + "Source/UI/Window/UIRPImageWnd2.cpp": 2, "Source/UI/Window/UIResizer.cpp": 2, "Source/UI/Window/UIRoMapWnd.cpp": 2, "Source/UI/Window/UIRoulletteWnd.cpp": 2, "Source/UI/Window/UISecondCostumeWnd.cpp": 2, "Source/UI/Window/UISeekPartyListWnd.cpp": 2, + "Source/UI/Window/UIShowWarpWnd.cpp": 2, "Source/UI/Window/UITab.cpp": 2, "Source/UI/Window/UITransMenuWnd.cpp": 2, "Source/UI/Window/UIWindow.cpp": 2,