diff --git a/dCommon/ZoneFile.cpp b/dCommon/ZoneFile.cpp index 4929589f0..43d02bda0 100644 --- a/dCommon/ZoneFile.cpp +++ b/dCommon/ZoneFile.cpp @@ -176,7 +176,12 @@ void ZoneFile::ReadPath(std::istream& file) { BinaryIO::ReadString(file, path.pathName, BinaryIO::ReadType::WideString); - BinaryIO::BinaryRead(file, path.pathType); + if (path.pathVersion < 3) { + // Before version 3 the type is a name, "platform" or "npc" (LevelPath::FromBuffer) + std::string typeName; + BinaryIO::ReadString(file, typeName, BinaryIO::ReadType::WideString); + path.pathType = typeName == "platform" ? PathType::MovingPlatform : PathType::Movement; + } else BinaryIO::BinaryRead(file, path.pathType); BinaryIO::BinaryRead(file, path.flags); BinaryIO::BinaryRead(file, path.pathBehavior); @@ -236,6 +241,19 @@ void ZoneFile::ReadPath(std::istream& file) { BinaryIO::BinaryRead(file, waypoint.position.y); BinaryIO::BinaryRead(file, waypoint.position.z); + if (path.pathVersion < 3) { + // Before version 3 every waypoint has a moving platform's data and then name/value pairs, whatever its path's type + BinaryIO::BinaryRead(file, waypoint.rotation.w); + BinaryIO::BinaryRead(file, waypoint.rotation.x); + BinaryIO::BinaryRead(file, waypoint.rotation.y); + BinaryIO::BinaryRead(file, waypoint.rotation.z); + BinaryIO::BinaryRead(file, waypoint.movingPlatform.lockPlayer); + BinaryIO::BinaryRead(file, waypoint.speed); + BinaryIO::BinaryRead(file, waypoint.movingPlatform.wait); + ReadLdfConfig(file, path.pathType, waypoint); + path.pathWaypoints.push_back(waypoint); + continue; + } if (path.pathType == PathType::Spawner || path.pathType == PathType::MovingPlatform || path.pathType == PathType::Race || path.pathType == PathType::Camera || path.pathType == PathType::Rail) { BinaryIO::BinaryRead(file, waypoint.rotation.w); diff --git a/tests/dCommonTests/ZoneFileTests.cpp b/tests/dCommonTests/ZoneFileTests.cpp index f83f5b11e..6b38f3932 100644 --- a/tests/dCommonTests/ZoneFileTests.cpp +++ b/tests/dCommonTests/ZoneFileTests.cpp @@ -164,6 +164,46 @@ TEST(ZoneFileTests, PrePreAlphaHasNoZoneName) { EXPECT_TRUE(zone.zoneDesc.empty()); } +// Before path version 3 the type is a name and every waypoint has a platform's data and name/value pairs +TEST(ZoneFileTests, ReadsLegacyPaths) { + ZoneBytes w; + w.Put(35).Put(137).Put(1); // version, world, scene count + w.Text("lup.lvl").Put(0).Put(0).Text("Global Scene").Put(0).Put(0).Put(0); + w.Put(0).Text("lup.raw").Text("Name").Text("Description"); + w.Put(0); // no transitions + w.Put(0).Put(1).Put(2); + w.Put(2).Wide("LavaPath").Wide("npc").Put(1).Put(0); + w.Put(1).Point(1, 2, 3).Put(1.0f).Put(0.0f).Put(0.0f).Put(0.0f).Put(0).Put(3.0f).Put(0.5f); + w.Put(1).Wide("delay").Wide("2"); + w.Put(2).Wide("Mower").Wide("platform").Put(0).Put(2); + w.Put(1).Point(4, 5, 6).Put(0.0f).Put(1.0f).Put(0.0f).Put(0.0f).Put(1).Put(7.0f).Put(1.5f).Put(0); + + std::istringstream stream(w.data); + ZoneFile zone; + zone.Read(stream); + EXPECT_FALSE(stream.fail()); + EXPECT_EQ(stream.peek(), std::char_traits::eof()); + ASSERT_EQ(zone.paths.size(), 2u); + + const auto& npc = zone.paths[0]; + EXPECT_EQ(npc.pathType, PathType::Movement); + EXPECT_EQ(npc.flags, 1u); + ASSERT_EQ(npc.pathWaypoints.size(), 1u); + EXPECT_EQ(npc.pathWaypoints[0].position, NiPoint3(1, 2, 3)); + EXPECT_EQ(npc.pathWaypoints[0].speed, 3.0f); + ASSERT_EQ(npc.pathWaypoints[0].commands.size(), 1u); + EXPECT_EQ(npc.pathWaypoints[0].commands[0].command, eWaypointCommandType::DELAY); + + const auto& platform = zone.paths[1]; + EXPECT_EQ(platform.pathType, PathType::MovingPlatform); + EXPECT_EQ(platform.pathBehavior, PathBehavior::Once); + ASSERT_EQ(platform.pathWaypoints.size(), 1u); + EXPECT_EQ(platform.pathWaypoints[0].rotation.x, 1.0f); + EXPECT_EQ(platform.pathWaypoints[0].movingPlatform.lockPlayer, 1); + EXPECT_EQ(platform.pathWaypoints[0].speed, 7.0f); + EXPECT_EQ(platform.pathWaypoints[0].movingPlatform.wait, 1.5f); +} + TEST(ZoneFileTests, ShortFilesThrowOrFail) { const auto zone = SampleZone(); for (const size_t length : { size_t{ 3 }, size_t{ 40 }, zone.size() / 2, zone.size() - 1 }) {