From 8a252ed81ce6611da255573e69902a7aeee70d1b Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 04:21:40 +0000 Subject: [PATCH] Decompile 4 functions in Source/Contents/NavigationRoute.cpp, Source/Contents/NavigationManager.h Batch #4638 by eAthena: 1 byte-identical, 3 confirmed by peer review. - fn_19382 NaviDataEntry::Init: byte-identical - fn_19383 CNaviData::Search: logic confirmed by peer review - fn_19385 CNaviData::ParseSearchKind: logic confirmed by peer review - fn_19386 CNaviData::FindMobByTitle: logic confirmed by peer review Peer-reviewed-by: willerthal, Snow Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Contents/NavigationManager.h | 4 + Source/Contents/NavigationRoute.cpp | 112 ++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) diff --git a/Source/Contents/NavigationManager.h b/Source/Contents/NavigationManager.h index ff82d5ac..47e76a74 100644 --- a/Source/Contents/NavigationManager.h +++ b/Source/Contents/NavigationManager.h @@ -34,6 +34,7 @@ struct NaviLink { struct NaviDataEntry { void Reset(); + void Init(); int GetPrevious() const; int GetCost() const; @@ -260,6 +261,9 @@ public: int FindRoute(std::vector* route, bool direct, bool allowGates, bool includeObjects, bool allowWarps, int side); void ResetLinkDepths(); bool CollectLinksTo(CNaviInfo* target, std::vector* out); + bool Search(std::string query, int type, std::vector& out); + int ParseSearchKind(std::vector& tokens); + CNavi_Object* FindMobByTitle(std::string title); int ObjectCount() const; /* 0000 */ std::vector destinations; diff --git a/Source/Contents/NavigationRoute.cpp b/Source/Contents/NavigationRoute.cpp index f1c90c8a..76575d01 100644 --- a/Source/Contents/NavigationRoute.cpp +++ b/Source/Contents/NavigationRoute.cpp @@ -13,6 +13,7 @@ #include #include +#include #include // OFFSET: 0x00B88800 @@ -728,3 +729,114 @@ bool CNaviData::CollectLinksTo(CNaviInfo* target, std::vector* out) int CNaviData::ObjectCount() const { return static_cast(this->objects.size()); } + +// OFFSET: 0x00B88A60 +// FUNCTION: fn_19382 +void NaviDataEntry::Init() { + this->previous = -1; + this->link = nullptr; + this->cost = 0; +} + +// OFFSET: 0x00B88AB0 +// FUNCTION: fn_19383 +bool CNaviData::Search(std::string query, int type, std::vector& out) { + if (query.size() == 0) { + return false; + } + std::vector tokens; + std::vector text(query.begin(), query.end()); + bool result = false; + text.push_back(0); + std::vector spaces; + spaces.push_back(-1); + for (unsigned int i = 0; i < text.size(); ++i) { + if (text[i] == ' ') { + spaces.push_back(i); + } + } + spaces.push_back(static_cast(text.size()) - 1); + for (auto it = spaces.begin(); it != spaces.end() - 1;) { + int start = *it + 1; + ++it; + if (start < *it) { + std::string token(&text[0] + start, &text[0] + *it); + tokens.push_back(token); + } + } + if (tokens.empty()) { + result = false; + } else { + int kind = this->ParseSearchKind(tokens); + out.clear(); + for (CNaviInfo* info : this->destinations) { + if (kind == 2) { + info->CollectTargets(type, out); + } else if (kind == 3) { + info->CollectMobsInRange(std::atoi(tokens[0].c_str()), std::atoi(tokens[1].c_str()), out); + } else if (kind == 4) { + if (tokens.size() == 2) { + info->CollectMobsByTitle(tokens[1].c_str(), out); + } + } else { + info->Search(type, tokens, out); + } + } + result = true; + } + return result; +} + +// OFFSET: 0x00B891C0 +// FUNCTION: fn_19385 +int CNaviData::ParseSearchKind(std::vector& tokens) { + if (std::strncmp(tokens[0].c_str(), LookupMessage(0x912), std::strlen(LookupMessage(0x912))) != 0) { + return 1; + } + std::size_t prefixLength = std::strlen(LookupMessage(0x913)); + if (prefixLength < tokens[0].size() && std::strncmp(tokens[0].c_str(), LookupMessage(0x913), prefixLength) == 0) { + std::string token(tokens[0]); + const char* separator = std::strstr(token.c_str(), LookupMessage(0x914)); + std::string minimum; + std::string maximum; + if (separator == nullptr) { + minimum.assign(token.c_str() + prefixLength, token.c_str() + token.size()); + maximum = minimum; + } else { + minimum.assign(token.c_str() + prefixLength, separator); + maximum.assign(separator + std::strlen(LookupMessage(0x914)), token.c_str() + token.size()); + if (maximum.size() == 0) { + maximum = "500"; + } + } + int low = std::atoi(minimum.c_str()); + int high = std::atoi(maximum.c_str()); + int kind; + if (low < 1 || high < 1 || low > high) { + kind = 0; + } else { + tokens.clear(); + tokens.push_back(minimum); + tokens.push_back(maximum); + kind = 3; + } + return kind; + } + if (std::strncmp(tokens[0].c_str(), LookupMessage(0x915), std::strlen(LookupMessage(0x915))) == 0) { + return 2; + } + return std::strncmp(tokens[0].c_str(), "$$DB", 4) == 0 ? 4 : 0; +} + +// OFFSET: 0x00B896E0 +// FUNCTION: fn_19386 +CNavi_Object* CNaviData::FindMobByTitle(std::string title) { + std::vector targets; + for (CNaviInfo* info : this->destinations) { + info->CollectMobsByTitle(title, targets); + if (targets.begin() != targets.end()) { + return static_cast(targets.front().object); + } + } + return nullptr; +}