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
This commit is contained in:
ragnarok-clanker 2026-10-29 18:31:03 +00:00
commit 96bc52887f
2 changed files with 109 additions and 1 deletions

View file

@ -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<unsigned char> CNavigationManager::WriteReplayState() {
std::vector<unsigned char> output;
const auto append = [&output](const std::vector<unsigned char>& 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<char> 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<NaviObjectRecord*>(buffer.data());
record->type = type;
record->index = index;
record->cellX = cell.x;
record->cellY = cell.y;
const std::size_t nameLength = static_cast<std::int16_t>(name.size());
record->nameLength = static_cast<std::int16_t>(name.size());
std::memcpy(buffer.data() + 0x12, name.c_str(), nameLength);
std::size_t offset = nameLength + 0x12;
const std::size_t titleLength = static_cast<std::int16_t>(title.size());
*reinterpret_cast<std::int16_t*>(buffer.data() + offset) = static_cast<std::int16_t>(title.size());
offset += 2;
std::memcpy(buffer.data() + offset, title.c_str(), titleLength);
offset += titleLength;
const std::size_t mapLength = static_cast<std::int16_t>(map.size());
*reinterpret_cast<std::int16_t*>(buffer.data() + offset) = static_cast<std::int16_t>(map.size());
offset += 2;
std::memcpy(buffer.data() + offset, map.c_str(), mapLength);
offset += mapLength;
*reinterpret_cast<int*>(buffer.data() + offset) = linkedCell.x;
*reinterpret_cast<int*>(buffer.data() + offset + 4) = linkedCell.y;
*reinterpret_cast<std::int16_t*>(buffer.data() + offset + 8) = static_cast<std::int16_t>(linkedMap.size());
offset += 10;
std::memcpy(buffer.data() + offset, linkedMap.c_str(), static_cast<std::int16_t>(linkedMap.size()));
}
append(BuildReplayTaggedRecord(8022, buffer.data(), static_cast<std::uint32_t>(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<std::uint32_t>(this->unknown_1264.size())));
}
std::vector<char> 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<std::uint32_t>(target.size())));
}
}
target = this->WriteTarget(this->currentTarget);
if (!target.empty()) {
append(BuildReplayTaggedRecord(8007, target.data(), static_cast<std::uint32_t>(target.size())));
}
target = this->WriteTarget(this->savedTarget);
if (!target.empty()) {
append(BuildReplayTaggedRecord(8008, target.data(), static_cast<std::uint32_t>(target.size())));
}
const int count = static_cast<int>(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 {