diff --git a/Source/Contents/TipBoxTitles.cpp b/Source/Contents/TipBoxTitles.cpp index 1e0d625..ea7d4bb 100644 --- a/Source/Contents/TipBoxTitles.cpp +++ b/Source/Contents/TipBoxTitles.cpp @@ -1,7 +1,12 @@ #include "Contents/TipBoxTitles.h" +#include +#include #include +// GLOBAL: gl_24607 +CTipBoxMgr* g_itemTagOwner = nullptr; + namespace { // OFFSET: 0x009B45D0 // FUNCTION: fn_13832 @@ -31,6 +36,97 @@ TipBoxEntry::TipBoxEntry() : unknown_0018(0), unknown_0044(0), unknown_0048(0) { this->unknown_004C[2] = 0; } +// INLINED +CTipBoxMgr::CTipBoxMgr() + : m_width(240), + m_height(320), + m_maximumId(17), + m_entries{}, + m_randomList{}, + m_currentEntry{}, + unknown_007C{}, + unknown_009C{}, + unknown_00B4(0), + m_initialized(true), + m_missing{}, + unknown_0114(0), + unknown_0118(0) { +} + +// INLINED +CTipBoxMgr::~CTipBoxMgr() = default; + +// FUNCTION: fn_09122 +void CTipBoxMgr::AddParagraph(int id, std::string text) { + for (;;) { + const auto pos = text.find("\\n"); + if (pos == std::string::npos) { + break; + } + text.replace(pos, 2, "\n"); + } + + this->m_entries[id].paragraphs.push_back(text); +} + +// FUNCTION: fn_09123 +bool CTipBoxMgr::Create() { + if (g_itemTagOwner) { + return false; + } + + g_itemTagOwner = new (std::nothrow) CTipBoxMgr(); + if (!g_itemTagOwner) { + return false; + } + + if (!g_itemTagOwner->m_initialized) { + delete g_itemTagOwner; + g_itemTagOwner = nullptr; + return false; + } + + return true; +} + +// FUNCTION: fn_09124 +void CTipBoxMgr::Destroy() { + if (g_itemTagOwner) { + delete g_itemTagOwner; + g_itemTagOwner = nullptr; + } +} + +// FUNCTION: fn_09125 +TipBoxEntry& CTipBoxMgr::SelectRandomTip() { + this->m_randomList.clear(); + + for (const auto& entry : this->m_entries) { + if (entry.first < 1000 && entry.second.unknown_0018 == 1) { + this->m_randomList.push_back(entry.first); + } + } + + const auto count = this->m_randomList.size(); + const auto index = static_cast(rand()) % count; + const auto it = this->m_entries.find(this->m_randomList[index]); + if (it != this->m_entries.end()) { + this->unknown_0114 = this->m_randomList[index]; + this->m_currentEntry = it->second; + } + return this->m_currentEntry; +} + +// FUNCTION: fn_09126 +const TipBoxEntry& CTipBoxMgr::GetTip(int id) const { + const auto it = this->m_entries.find(id); + if (it == this->m_entries.end()) { + return this->m_missing; + } + + return it->second; +} + // OFFSET: 0x007ACC70 // FUNCTION: fn_09127 std::string TipBoxTitles::Title(int id, std::string* abbreviated, int width) const { diff --git a/Source/Contents/TipBoxTitles.h b/Source/Contents/TipBoxTitles.h index b66400b..7532baf 100644 --- a/Source/Contents/TipBoxTitles.h +++ b/Source/Contents/TipBoxTitles.h @@ -27,8 +27,38 @@ struct TipBoxTitles { std::string Title(int id, std::string* abbreviated, int width) const; }; +class CTipBoxMgr { +public: + CTipBoxMgr(); + virtual ~CTipBoxMgr(); + + void AddParagraph(int id, std::string text); + TipBoxEntry& SelectRandomTip(); + const TipBoxEntry& GetTip(int id) const; + + static bool Create(); + static void Destroy(); + + int m_width; + int m_height; + int m_maximumId; + std::map m_entries; + std::vector m_randomList; + TipBoxEntry m_currentEntry; + std::uint32_t unknown_007C[8]; + std::string unknown_009C; + int unknown_00B4; + bool m_initialized; + TipBoxEntry m_missing; + int unknown_0114; + int unknown_0118; +}; + +extern CTipBoxMgr* g_itemTagOwner; + #if defined(_WIN32) && !defined(_WIN64) static_assert(sizeof(TipBoxEntry) == 88); +static_assert(sizeof(CTipBoxMgr) == 284); #endif #endif