From 96bc52887feddbbbdf1812922d4c2e5633d454ae Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Thu, 29 Oct 2026 18:31:03 +0000 Subject: [PATCH] Decompile fn_19615 (CNavigationManager::WriteReplayState) Batch #2663 by youko: 0 byte-identical, 1 confirmed by peer review. - fn_19615 CNavigationManager::WriteReplayState: logic confirmed by peer review Peer-reviewed-by: willerthal Reviewed-by: ragnarok-clanker --- Source/Contents/NavigationManager.h | 3 +- Source/Contents/NavigationRoute.cpp | 107 ++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 1 deletion(-) diff --git a/Source/Contents/NavigationManager.h b/Source/Contents/NavigationManager.h index cb9144a5..c67c5452 100644 --- a/Source/Contents/NavigationManager.h +++ b/Source/Contents/NavigationManager.h @@ -289,6 +289,7 @@ public: NaviCell ParseCell(const char* text); std::vector WriteTarget(NavigationTarget target); std::vector WriteObject(CNavi_Object* object); + std::vector WriteReplayState(); CNavi_Link* ReadObject(const char* record); void ClearSavedTarget(); void ClearCurrentObject(); @@ -303,7 +304,7 @@ public: /* 10FC */ NavigationTarget currentTarget; /* 1124 */ NavigationTarget savedTarget; /* 114C */ int routeResult; - /* 1150 */ std::vector nodes; + /* 1150 */ std::vector nodes; /* 115C */ bool unknown_115C; /* 1160 */ int selectedNode; /* 1164 */ MovementRouteInterpolation movementRoute; diff --git a/Source/Contents/NavigationRoute.cpp b/Source/Contents/NavigationRoute.cpp index cd308bce..958f06ae 100644 --- a/Source/Contents/NavigationRoute.cpp +++ b/Source/Contents/NavigationRoute.cpp @@ -3,6 +3,7 @@ #include "Contents/MessageTable.h" #include "Utility/Text/FormatString.h" #include "Client/Registry.h" +#include "Client/Replay.h" #include "Client/Session.h" #include "Resource/ResourceMgr.h" #include "UI/Window/UIWindow.h" @@ -449,6 +450,112 @@ void CNavigationManager::LoadSettings() { } } +// OFFSET: 0x00B99CE0 +// FUNCTION: fn_19615 +std::vector CNavigationManager::WriteReplayState() { + std::vector output; + const auto append = [&output](const std::vector& record) { output.insert(output.end(), record.begin(), record.end()); }; + + append(BuildReplayTaggedRecord(8000, nullptr, 0)); + append(BuildReplayTaggedRecord(8002, &this->unknown_127C, 1)); + append(BuildReplayTaggedRecord(8003, &this->unknown_127D, 1)); + append(BuildReplayTaggedRecord(8004, &this->unknown_127E, 1)); + append(BuildReplayTaggedRecord(8005, &this->unknown_1280, 4)); + + for (std::size_t i = 0; i < this->nodes.size(); ++i) { + CNavi_Link* node = this->nodes[i]; + std::vector buffer; + if (node != nullptr) { + const int type = node->GetType(); + const int index = node->GetIndex(); + NaviCell cell; + node->GetCell(&cell); + std::string name = node->GetName(); + std::string title = node->GetTitle(); + std::string map = node->GetInfo()->GetName(); + std::string linkedMap = node->GetLinkedName(); + const NaviCell linkedCell = node->GetLinkedCell(); + + buffer.resize(linkedMap.size() + 0x20 + title.size() + name.size() + map.size(), '\0'); + + NaviObjectRecord* record = reinterpret_cast(buffer.data()); + record->type = type; + record->index = index; + record->cellX = cell.x; + record->cellY = cell.y; + + const std::size_t nameLength = static_cast(name.size()); + record->nameLength = static_cast(name.size()); + std::memcpy(buffer.data() + 0x12, name.c_str(), nameLength); + + std::size_t offset = nameLength + 0x12; + const std::size_t titleLength = static_cast(title.size()); + *reinterpret_cast(buffer.data() + offset) = static_cast(title.size()); + offset += 2; + std::memcpy(buffer.data() + offset, title.c_str(), titleLength); + offset += titleLength; + + const std::size_t mapLength = static_cast(map.size()); + *reinterpret_cast(buffer.data() + offset) = static_cast(map.size()); + offset += 2; + std::memcpy(buffer.data() + offset, map.c_str(), mapLength); + offset += mapLength; + + *reinterpret_cast(buffer.data() + offset) = linkedCell.x; + *reinterpret_cast(buffer.data() + offset + 4) = linkedCell.y; + *reinterpret_cast(buffer.data() + offset + 8) = static_cast(linkedMap.size()); + offset += 10; + std::memcpy(buffer.data() + offset, linkedMap.c_str(), static_cast(linkedMap.size())); + } + append(BuildReplayTaggedRecord(8022, buffer.data(), static_cast(buffer.size()))); + } + + append(BuildReplayTaggedRecord(8009, &this->unknown_124C, 4)); + append(BuildReplayTaggedRecord(8010, &this->unknown_1250, 4)); + append(BuildReplayTaggedRecord(8011, &this->unknown_1254, 1)); + append(BuildReplayTaggedRecord(8013, &this->unknown_125C, 4)); + append(BuildReplayTaggedRecord(8014, &this->unknown_1260, 4)); + append(BuildReplayTaggedRecord(8016, &this->unknown_1284, 4)); + append(BuildReplayTaggedRecord(8017, &this->unknown_117C, 1)); + append(BuildReplayTaggedRecord(8018, &this->routeResult, 4)); + append(BuildReplayTaggedRecord(8019, &this->unknown_115C, 1)); + append(BuildReplayTaggedRecord(8020, &this->selectedNode, 4)); + append(BuildReplayTaggedRecord(8023, &this->unknown_1248, 1)); + append(BuildReplayTaggedRecord(8012, &this->unknown_1258, 4)); + if (!this->unknown_1264.empty()) { + append(BuildReplayTaggedRecord(8015, this->unknown_1264.c_str(), static_cast(this->unknown_1264.size()))); + } + + std::vector target; + for (std::size_t i = 0; i < this->states.size(); ++i) { + target = this->WriteTarget(this->states[i]); + if (!target.empty()) { + append(BuildReplayTaggedRecord(8006, target.data(), static_cast(target.size()))); + } + } + + target = this->WriteTarget(this->currentTarget); + if (!target.empty()) { + append(BuildReplayTaggedRecord(8007, target.data(), static_cast(target.size()))); + } + + target = this->WriteTarget(this->savedTarget); + if (!target.empty()) { + append(BuildReplayTaggedRecord(8008, target.data(), static_cast(target.size()))); + } + + const int count = static_cast(this->movementRoute.points.size()); + if (count > 1) { + const int route[4] = { + this->movementRoute.points[0].x, this->movementRoute.points[0].y, this->movementRoute.points[count - 1].x, this->movementRoute.points[count - 1].y + }; + append(BuildReplayTaggedRecord(8021, route, sizeof(route))); + } + + append(BuildReplayTaggedRecord(8001, nullptr, 0)); + return output; +} + // OFFSET: 0x00B9C020 // FUNCTION: fn_19618 float CNavigationManager::FitToSquare(int* offsetX, int* offsetY, int width, int height, float size) const {