diff --git a/dCommon/ZoneFile.cpp b/dCommon/ZoneFile.cpp index b381e6fc3..77fbcb52b 100644 --- a/dCommon/ZoneFile.cpp +++ b/dCommon/ZoneFile.cpp @@ -279,6 +279,8 @@ bool ZoneFile::ReadPath(std::istream& file) { if (path.pathVersion >= 7) { BinaryIO::BinaryRead(file, path.property.cloneLimit); BinaryIO::BinaryRead(file, path.property.repMultiplier); + // The client takes a multiplier outside 0-1000 as 0 (LevelPath::FromBuffer) + if (path.property.repMultiplier < 0.0f || path.property.repMultiplier > 1000.0f) path.property.repMultiplier = 0.0f; BinaryIO::BinaryRead(file, path.property.rentalPeriod); } @@ -346,6 +348,8 @@ bool ZoneFile::ReadPath(std::istream& file) { } else if (path.pathType == PathType::Camera) { BinaryIO::BinaryRead(file, waypoint.camera.time); BinaryIO::BinaryRead(file, waypoint.camera.fov); + // Before version 11 the file's FOV is 1.25 times the one the client uses (LevelPath::FromBuffer) + if (path.pathVersion < 11) waypoint.camera.fov /= 1.25f; BinaryIO::BinaryRead(file, waypoint.camera.tension); BinaryIO::BinaryRead(file, waypoint.camera.continuity); BinaryIO::BinaryRead(file, waypoint.camera.bias); diff --git a/tests/dCommonTests/ZoneFileTests.cpp b/tests/dCommonTests/ZoneFileTests.cpp index 4599c0306..6161162c5 100644 --- a/tests/dCommonTests/ZoneFileTests.cpp +++ b/tests/dCommonTests/ZoneFileTests.cpp @@ -329,6 +329,35 @@ TEST(ZoneFileTests, SpawnerAndCameraFieldsFromVersion4) { EXPECT_EQ(zone.paths[1].pathWaypoints.at(0).position, NiPoint3(2, 2, 2)); } +// Values the client adjusts as it reads them: a reputation multiplier outside 0-1000 is 0, a camera FOV before path +// version 11 is divided by 1.25 +TEST(ZoneFileTests, AdjustsValuesAsTheClient) { + ZoneBytes w; + w.Put(41).Put(3).Put(1150); + w.Point(0, 0, 0).Put(1.0f).Put(0.0f).Put(0.0f).Put(0.0f); + w.Put(1); + w.Text("scene.lvl").Put(0).Put(0).Text("Global").Put(0).Put(0).Put(0); + w.Put(0).Text("zone.raw").Text("Name").Text("Description"); + w.Put(0).Paths().Put(1).Put(3); + for (const float multiplier : { 2000.0f, 3.0f }) { + w.Put(8).Wide("Property").Put(2).Put(0).Put(0); + w.Put(0).Put(0).Put(0).Put(0).Wide("").Put(0); + w.Put(0).Put(0).Put(multiplier).Put(0).Put(0).Point(0, 0, 0).Put(128.0f); + w.Put(0); + } + w.Put(10).Wide("Camera").Put(3).Put(0).Put(0).Wide(""); + w.Put(1).Point(0, 0, 0).Put(1.0f).Put(0.0f).Put(0.0f).Put(0.0f).Put(1.0f).Put(50.0f).Put(0.0f).Put(0.0f).Put(0.0f); + + std::istringstream stream(w.Done()); + ZoneFile zone; + zone.Read(stream); + EXPECT_FALSE(stream.fail()); + ASSERT_EQ(zone.paths.size(), 3u); + EXPECT_EQ(zone.paths[0].property.repMultiplier, 0.0f); + EXPECT_EQ(zone.paths[1].property.repMultiplier, 3.0f); + EXPECT_EQ(zone.paths[2].pathWaypoints.at(0).camera.fov, 40.0f); +} + // The paths are a chunk the client reads on its own: a path it refuses (here version 19) leaves the zone with no paths, // and the zone file goes on after the chunk TEST(ZoneFileTests, RefusedPathsLeaveNoPaths) {