From 253d8484bfb66e718fc2e41a09e26aa25622bb50 Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Tue, 23 Sep 2025 19:40:27 +0200 Subject: [PATCH] Make S4Importer::CorrectRCT1ParkValue independent of global game state (#25178) --- src/openrct2/rct1/S4Importer.cpp | 37 ++++++++++++++++---------------- src/openrct2/world/Park.cpp | 7 ------ src/openrct2/world/Park.h | 1 - 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 94e99b95cf..85576e782d 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -93,13 +93,15 @@ static constexpr ObjectEntryIndex ObjectEntryIndexIgnore = 254; namespace OpenRCT2::RCT1 { + constexpr uint8_t kDefaultParkValueConversionFactor = 100; + class S4Importer final : public IParkImporter { private: std::string _s4Path; S4 _s4 = {}; uint8_t _gameVersion = 0; - uint8_t _parkValueConversionFactor = 0; + uint8_t _parkValueConversionFactor = kDefaultParkValueConversionFactor; bool _isScenario = false; // Lists of dynamic object entries @@ -288,6 +290,17 @@ namespace OpenRCT2::RCT1 return {}; } + private: + uint8_t calculateParkValueConversionFactor(const Park::ParkData& park, const GameState_t& gameState) + { + if (_s4.ParkValue == 0) + return kDefaultParkValueConversionFactor; + + // Use the ratio between the old and new park value to calculate the ratio to + // use for the park value history and the goal. + return (Park::CalculateParkValue(park, gameState) * 10) / _s4.ParkValue; + } + money64 CorrectRCT1ParkValue(money32 oldParkValue) { if (oldParkValue == kMoney32Undefined) @@ -295,26 +308,11 @@ namespace OpenRCT2::RCT1 return kMoney64Undefined; } - if (_parkValueConversionFactor == 0) - { - if (_s4.ParkValue != 0) - { - // Use the ratio between the old and new park value to calcute the ratio to - // use for the park value history and the goal. - // TODO: split up this function so this can pass the actual park/gamestate as needed - _parkValueConversionFactor = (Park::CalculateParkValue() * 10) / _s4.ParkValue; - } - else - { - // In new games, the park value isn't set. - _parkValueConversionFactor = 100; - } - } + assert(_parkValueConversionFactor != 0); return (oldParkValue * _parkValueConversionFactor) / 10; } - private: std::unique_ptr ReadAndDecodeS4(IStream* stream, bool isScenario) { auto s4 = std::make_unique(); @@ -345,7 +343,7 @@ namespace OpenRCT2::RCT1 void Initialise(GameState_t& gameState) { // Avoid reusing the value used for last import - _parkValueConversionFactor = 0; + _parkValueConversionFactor = kDefaultParkValueConversionFactor; uint16_t mapSize = _s4.MapSize == 0 ? Limits::kMaxMapSize : _s4.MapSize; @@ -1514,6 +1512,9 @@ namespace OpenRCT2::RCT1 park.value = CorrectRCT1ParkValue(_s4.ParkValue); park.currentProfit = ToMoney64(_s4.Profit); + // With park value known, we can recalculate the conversion factor + _parkValueConversionFactor = calculateParkValueConversionFactor(park, gameState); + for (size_t i = 0; i < Limits::kFinanceGraphSize; i++) { park.cashHistory[i] = ToMoney64(_s4.CashHistory[i]); diff --git a/src/openrct2/world/Park.cpp b/src/openrct2/world/Park.cpp index bfdf4578b2..2f6b6f82d6 100644 --- a/src/openrct2/world/Park.cpp +++ b/src/openrct2/world/Park.cpp @@ -509,13 +509,6 @@ namespace OpenRCT2::Park return result; } - // TODO: refactor S4Importer so this hack is no longer needed - money64 CalculateParkValue() - { - auto& gameState = getGameState(); - return CalculateParkValue(gameState.park, gameState); - } - money64 CalculateCompanyValue(const ParkData& park) { auto result = park.value - park.bankLoan; diff --git a/src/openrct2/world/Park.h b/src/openrct2/world/Park.h index 3b2c0c906b..aab0ac117b 100644 --- a/src/openrct2/world/Park.h +++ b/src/openrct2/world/Park.h @@ -29,7 +29,6 @@ namespace OpenRCT2::Park uint32_t CalculateParkSize(ParkData& park); int32_t CalculateParkRating(const ParkData& park, const GameState_t& gameState); money64 CalculateParkValue(const ParkData& park, const GameState_t& gameState); - money64 CalculateParkValue(); money64 CalculateCompanyValue(const ParkData& park); Guest* GenerateGuest();