#include "Contents/ShowRankingScheduler.h" #include "Client/Session.h" #include "Contents/Schedule/CheckGDISchedule.h" #include "Contents/Schedule/TimeScheduler.h" #include "Contents/MessageTable.h" #include "Contents/PlayerNameDictionary.h" #include "UI/Window/UIWindowMgr.h" #include "Utility/Text/FormatString.h" #include #include #include #include #include #include // GLOBAL: gl_24719 int g_schedulerSerial; // GLOBAL: gl_24731 std::string g_namelessName; // OFFSET: 0x00637550 // FUNCTION: fn_04735 CShowRankingScheduler::CShowRankingScheduler(const std::uint64_t& start, const std::uint64_t& end, int extra) { ++g_schedulerSerial; *reinterpret_cast(this->schedule + 4) = g_schedulerSerial; *reinterpret_cast(this->schedule + 12) = start; *reinterpret_cast(this->schedule + 20) = end; *reinterpret_cast(this->schedule + 28) = extra; *reinterpret_cast(this->schedule + 32) = 1; *reinterpret_cast(this->schedule + 36) = 0; *reinterpret_cast(this->schedule + 40) = 0; this->unknown_0088 = 0; this->unknown_008C = 0; std::memset(this->rankingData, 0, sizeof(this->rankingData)); if (this->rankingList.capacity() < 16) { this->rankingList.reserve(16); } } // OFFSET: 0x00637C60 // FUNCTION: fn_04739 void CShowRankingScheduler::Process(const std::uint64_t& now) { if (*reinterpret_cast(this->rankingData) != 0) { const std::int64_t count = static_cast((static_cast(this->unknown_008C) << 32) | this->unknown_0088); if (count > 0) { const std::uint64_t due = static_cast(count) * 10000ull + *reinterpret_cast(this->schedule + 12); if (static_cast(due) <= static_cast(now)) { this->Show(); } else { bool complete = true; const auto* ids = reinterpret_cast(this->rankingData + 4); for (int index = 0; index < 10; ++index) { const std::uint32_t id = ids[index]; if (id == 0) { continue; } std::string name; for (std::uint32_t listed : this->rankingList) { if (listed == id) { name = g_namelessName; break; } } if (name.find(g_namelessName) == std::string::npos) { name = LookupPlayerName(id); if (name.empty()) { complete = false; } } } if (!complete) { g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(3481)), 0xffff, 0, 0, 0); return; } this->Show(); } } } this->schedule[32] = 0; } // OFFSET: 0x006378D0 // FUNCTION: fn_04738 std::map RankingBoardStyles() { std::map styles; styles.insert({0, {"========== BLACKSMITH RANK ============", 0x9B9B9B, 0xCDCDCD}}); styles.insert({1, {"=========== ALCHEMIST RANK =============", 0x9BCD9B, 0xCDFFCD}}); styles.insert({2, {"============ TAEKWON RANK =============", 0xCD9B9B, 0xFFCDCD}}); styles.insert({3, {"=========== KILLER RANK ==============", 0x9B9B9B, 0xCDCDCD}}); return styles; } // OFFSET: 0x006380A0 // FUNCTION: fn_04740 const void* CShowRankingScheduler::SetData(const void* data) { if (data) { std::memcpy(this->rankingData, data, sizeof(this->rankingData)); return data; } std::memset(this->rankingData, 0, sizeof(this->rankingData)); errno = EINVAL; _invalid_parameter_noinfo(); return nullptr; } // OFFSET: 0x00638110 // FUNCTION: fn_04741 void CShowRankingScheduler::Show() { // GLOBAL: gl_25055 static const std::map styles = RankingBoardStyles(); const int kind = *reinterpret_cast(this->rankingData + 2); const char* title; std::uint32_t color; std::uint32_t background; auto style = styles.lower_bound(kind); if (style != styles.end() && !(kind < style->first)) { title = style->second.title; color = style->second.color; background = style->second.background; } else { title = "==========================================="; background = 0; color = 0; } g_windowMgr.SendNotice(1, reinterpret_cast(title), color, 0, 0, 0); const auto* ids = reinterpret_cast(this->rankingData + 4); const auto* points = reinterpret_cast(this->rankingData + 44); for (int index = 0; index < 10; ++index) { std::string name; const std::uint32_t id = ids[index]; if (id != 0) { for (std::uint32_t listed : this->rankingList) { if (listed == id) { name = g_namelessName; break; } } if (name.find(g_namelessName) == std::string::npos) { name = LookupPlayerName(id); } } if (name.empty() || name.find(g_namelessName) != std::string::npos) { name = LookupMessage(581); } std::string line = FormatOwnedString("[ %2d ] %s : %4d POINT", index + 1, name.c_str(), points[index]); g_windowMgr.SendNotice(1, reinterpret_cast(line.c_str()), background, 0, 0, 0); } g_windowMgr.SendNotice(1, reinterpret_cast("==========================================="), color, 0, 0, 0); std::string mine = FormatOwnedString("MY POINT : %4d POINT ", *reinterpret_cast(this->rankingData + 84)); g_windowMgr.SendNotice(1, reinterpret_cast(mine.c_str()), background, 0, 0, 0); g_windowMgr.SendNotice(1, reinterpret_cast("==========================================="), color, 0, 0, 0); } // OFFSET: 0x00E493E0 // FUNCTION: fn_24235 void CSession::SetShowRankingSchedule(bool show, const void* data) { CSchedule* existing = reinterpret_cast(g_timeScheduler)->FindSchedule(this->m_showRankingSchedule); if (show == true) { if (existing == nullptr) { std::uint64_t now = _Xtime_get_ticks(); CShowRankingScheduler* ranking; { const std::uint64_t duration = 1000; ranking = new CShowRankingScheduler(now, duration, 1); } if (ranking != nullptr) { ranking->unknown_0088 = 3000; ranking->unknown_008C = 0; ranking->SetData(data); CSchedule* schedule = reinterpret_cast(ranking); schedule->Process(now); this->m_showRankingSchedule = schedule->serial; reinterpret_cast(g_timeScheduler)->AddSchedule(schedule); } } } else if (existing != nullptr) { existing->active = false; } } // OFFSET: 0x00D18AB0 // FUNCTION: fn_21599 void CSession::SetTraitStat(int type, int value) { std::map& traitStats = reinterpret_cast&>(this->unknown_7FC0); traitStats[type] = value; }