diff --git a/CMakeLists.txt b/CMakeLists.txt index 91e31c0b4f..b2a742f306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,9 +50,9 @@ set(OBJECTS_VERSION "1.0.21") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip") set(OBJECTS_SHA1 "c38af45d51a6e440386180feacf76c64720b6ac5") -set(REPLAYS_VERSION "0.0.46") +set(REPLAYS_VERSION "0.0.47") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v${REPLAYS_VERSION}/replays.zip") -set(REPLAYS_SHA1 "4DDCF0A78F8B9A20601607173247C418A2526CC3") +set(REPLAYS_SHA1 "61CAB8A0AD0B057B13B003DF32748977C2B5975F") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/OpenRCT2.xcodeproj/project.pbxproj b/OpenRCT2.xcodeproj/project.pbxproj index 5b071a34fb..5733a6f091 100644 --- a/OpenRCT2.xcodeproj/project.pbxproj +++ b/OpenRCT2.xcodeproj/project.pbxproj @@ -796,6 +796,9 @@ 5B6E418A2F264952BA0CC2F2 /* ScTileElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 43D18154E96444749737E3F6 /* ScTileElement.cpp */; }; DEC539DE402F4B8993E4C357 /* ScTileElement.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F4C26E211F1D44C9ADA70740 /* ScTileElement.hpp */; }; 6C90BE01D190493295071B23 /* ScTile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B67E36A8620400CA70FBA49 /* ScTile.cpp */; }; + 258C212125F84FA2B4C3BCAE /* RideUseSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 58DEACC694664E7C8DACB93D /* RideUseSystem.cpp */; }; + E6C71B6165224F65AA87E65B /* RideUseSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DA720D496604387806AC168 /* RideUseSystem.h */; }; + C8D612EB56BD4214BEC0F7FF /* GroupVector.hpp in Headers */ = {isa = PBXBuildFile; fileRef = F4D523B8782E4C458AF1490D /* GroupVector.hpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1894,6 +1897,9 @@ 43D18154E96444749737E3F6 /* ScTileElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScTileElement.cpp; path = src/openrct2/scripting/bindings/world/ScTileElement.cpp; sourceTree = SOURCE_ROOT; }; F4C26E211F1D44C9ADA70740 /* ScTileElement.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ScTileElement.hpp; path = src/openrct2/scripting/bindings/world/ScTileElement.hpp; sourceTree = SOURCE_ROOT; }; 5B67E36A8620400CA70FBA49 /* ScTile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScTile.cpp; path = src/openrct2/scripting/bindings/world/ScTile.cpp; sourceTree = SOURCE_ROOT; }; + 58DEACC694664E7C8DACB93D /* RideUseSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RideUseSystem.cpp; path = src/openrct2/peep/RideUseSystem.cpp; sourceTree = SOURCE_ROOT; }; + 2DA720D496604387806AC168 /* RideUseSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RideUseSystem.h; path = src/openrct2/peep/RideUseSystem.h; sourceTree = SOURCE_ROOT; }; + F4D523B8782E4C458AF1490D /* GroupVector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = GroupVector.hpp; path = src/openrct2/core/GroupVector.hpp; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2563,6 +2569,7 @@ F76C83991EC4E7CC00FA49E2 /* Zip.cpp */, F76C839A1EC4E7CC00FA49E2 /* Zip.h */, BA2317BF6FB54E328DEB7055 /* EnumMap.hpp */, + F4D523B8782E4C458AF1490D /* GroupVector.hpp */, ); path = core; sourceTree = ""; @@ -2831,6 +2838,8 @@ 4CFE4E7D1F90A3F1005243C2 /* PeepData.cpp */, 4CFE4E7E1F90A3F1005243C2 /* Staff.cpp */, 4CFE4E7F1F90A3F1005243C2 /* Staff.h */, + 58DEACC694664E7C8DACB93D /* RideUseSystem.cpp */, + 2DA720D496604387806AC168 /* RideUseSystem.h */, ); path = peep; sourceTree = ""; @@ -3638,6 +3647,8 @@ 63858E295E3F451283987982 /* ScRideStation.hpp in Headers */, AD5EC8B5EBF240B3874BC581 /* ScParkMessage.hpp in Headers */, DEC539DE402F4B8993E4C357 /* ScTileElement.hpp in Headers */, + E6C71B6165224F65AA87E65B /* RideUseSystem.h in Headers */, + C8D612EB56BD4214BEC0F7FF /* GroupVector.hpp in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4457,6 +4468,7 @@ 887B0043454440BAB322A9E8 /* ScPark.cpp in Sources */, 5B6E418A2F264952BA0CC2F2 /* ScTileElement.cpp in Sources */, 6C90BE01D190493295071B23 /* ScTile.cpp in Sources */, + 258C212125F84FA2B4C3BCAE /* RideUseSystem.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/openrct2.proj b/openrct2.proj index 014df4a74d..710f325bd9 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -48,8 +48,8 @@ 304d13a126c15bf2c86ff13b81a2f2cc1856ac8d https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip c38af45d51a6e440386180feacf76c64720b6ac5 - https://github.com/OpenRCT2/replays/releases/download/v0.0.46/replays.zip - 4DDCF0A78F8B9A20601607173247C418A2526CC3 + https://github.com/OpenRCT2/replays/releases/download/v0.0.47/replays.zip + 61CAB8A0AD0B057B13B003DF32748977C2B5975F diff --git a/src/openrct2/GameStateSnapshots.cpp b/src/openrct2/GameStateSnapshots.cpp index 3a95370b77..5574143b7f 100644 --- a/src/openrct2/GameStateSnapshots.cpp +++ b/src/openrct2/GameStateSnapshots.cpp @@ -39,6 +39,21 @@ struct GameStateSnapshot_t OpenRCT2::MemoryStream storedSprites; OpenRCT2::MemoryStream parkParameters; + template bool EntitySizeCheck(DataSerialiser& ds) + { + uint32_t size = sizeof(T); + ds << size; + if (ds.IsLoading()) + { + return size == sizeof(T); + } + return true; + } + template bool EntitiesSizeCheck(DataSerialiser& ds) + { + return (EntitySizeCheck(ds) && ...); + } + // Must pass a function that can access the sprite. void SerialiseSprites(std::function getEntity, const size_t numSprites, bool saving) { @@ -64,6 +79,13 @@ struct GameStateSnapshot_t numSavedSprites = static_cast(indexTable.size()); } + // Encodes and checks the size of each of the entity so that we + // can fail gracefully when fields added/removed + if (!EntitiesSizeCheck(ds)) + { + log_error("Entity index corrupted!"); + return; + } ds << numSavedSprites; if (loading) @@ -300,20 +322,12 @@ struct GameStateSnapshots final : public IGameStateSnapshots COMPARE_FIELD(Guest, Intensity); COMPARE_FIELD(Guest, NauseaTolerance); COMPARE_FIELD(Guest, PaidOnDrink); - for (int i = 0; i < 16; i++) - { - COMPARE_FIELD(Guest, RideTypesBeenOn[i]); - } COMPARE_FIELD(Guest, ItemFlags); COMPARE_FIELD(Guest, Photo2RideRef); COMPARE_FIELD(Guest, Photo3RideRef); COMPARE_FIELD(Guest, Photo4RideRef); COMPARE_FIELD(Guest, GuestNextInQueue); COMPARE_FIELD(Guest, TimeInQueue); - for (int i = 0; i < 32; i++) - { - COMPARE_FIELD(Guest, RidesBeenOn[i]); - } COMPARE_FIELD(Guest, CashInPocket); COMPARE_FIELD(Guest, CashSpent); diff --git a/src/openrct2/actions/RideDemolishAction.cpp b/src/openrct2/actions/RideDemolishAction.cpp index 1e584de91b..3add2042dc 100644 --- a/src/openrct2/actions/RideDemolishAction.cpp +++ b/src/openrct2/actions/RideDemolishAction.cpp @@ -17,6 +17,7 @@ #include "../interface/Window.h" #include "../localisation/Localisation.h" #include "../management/NewsItem.h" +#include "../peep/RideUseSystem.h" #include "../ride/Ride.h" #include "../ride/RideData.h" #include "../ui/UiContext.h" @@ -134,6 +135,7 @@ GameActions::Result::Ptr RideDemolishAction::DemolishRide(Ride* ride) const UnlinkAllBannersForRide(_rideIndex); + RideUse::GetHistory().RemoveValue(_rideIndex); for (auto peep : EntityList()) { peep->RemoveRideFromMemory(_rideIndex); diff --git a/src/openrct2/core/GroupVector.hpp b/src/openrct2/core/GroupVector.hpp new file mode 100644 index 0000000000..195e669783 --- /dev/null +++ b/src/openrct2/core/GroupVector.hpp @@ -0,0 +1,81 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once +#include +#include + +template class GroupVector +{ + std::vector> _data; + +public: + bool Contains(Handle handle, V value) + { + if (handle >= _data.size()) + return false; + + const auto& values = _data[handle]; + return std::find(values.begin(), values.end(), value) != values.end(); + } + + void Add(Handle handle, V value) + { + if (handle >= _data.size()) + { + _data.resize(handle + 1); + } + auto& values = _data[handle]; + + auto it = std::find(values.begin(), values.end(), value); + if (it != values.end()) + return; + + values.push_back(value); + } + + void Set(Handle handle, std::vector&& values) + { + if (handle >= _data.size()) + { + _data.resize(handle + 1); + } + _data[handle] = values; + } + + std::vector* GetAll(Handle handle) + { + if (handle < _data.size()) + { + return &_data[handle]; + } + return nullptr; + } + + void Clear() + { + _data.clear(); + } + + void RemoveHandle(Handle handle) + { + if (handle < _data.size()) + { + _data[handle].clear(); + } + } + + void RemoveValue(V value) + { + for (auto& values : _data) + { + values.erase(std::remove_if(values.begin(), values.end(), [value](auto v) { return v == value; }), values.end()); + } + } +}; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 7029514897..3d685e7517 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -164,6 +164,7 @@ + @@ -285,6 +286,7 @@ + @@ -735,6 +737,7 @@ + diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 7f3578ff38..a0417603bc 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -37,7 +37,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "3" +#define NETWORK_STREAM_VERSION "4" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/peep/Guest.cpp b/src/openrct2/peep/Guest.cpp index 2aa6787403..d57c25d151 100644 --- a/src/openrct2/peep/Guest.cpp +++ b/src/openrct2/peep/Guest.cpp @@ -45,6 +45,7 @@ #include "../world/TileElementsView.h" #include "GuestPathfinding.h" #include "Peep.h" +#include "RideUseSystem.h" #include "Staff.h" #include @@ -2296,27 +2297,30 @@ void Guest::SpendMoney(money16& peep_expend_type, money32 amount, ExpenditureTyp void Guest::SetHasRidden(const Ride* ride) { - RidesBeenOn[ride->id / 8] |= 1 << (ride->id % 8); + OpenRCT2::RideUse::GetHistory().Add(sprite_index, ride->id); + SetHasRiddenRideType(ride->type); } bool Guest::HasRidden(const Ride* ride) const { - return RidesBeenOn[ride->id / 8] & (1 << (ride->id % 8)); + return OpenRCT2::RideUse::GetHistory().Contains(sprite_index, ride->id); } void Guest::SetHasRiddenRideType(int32_t rideType) { // This is needed to avoid desyncs. TODO: remove once the new save format is introduced. rideType = OpenRCT2RideTypeToRCT2RideType(rideType); - RideTypesBeenOn[rideType / 8] |= 1 << (rideType % 8); + + OpenRCT2::RideUse::GetTypeHistory().Add(sprite_index, rideType); } bool Guest::HasRiddenRideType(int32_t rideType) const { // This is needed to avoid desyncs. TODO: remove once the new save format is introduced. rideType = OpenRCT2RideTypeToRCT2RideType(rideType); - return RideTypesBeenOn[rideType / 8] & (1 << (rideType % 8)); + + return OpenRCT2::RideUse::GetTypeHistory().Contains(sprite_index, rideType); } void Guest::SetParkEntryTime(int32_t entryTime) @@ -7030,10 +7034,8 @@ Guest* Guest::Generate(const CoordsXYZ& coords) peep->Toilet = 0; peep->TimeToConsume = 0; - std::fill_n(peep->RidesBeenOn, 32, 0x00); peep->GuestNumRides = 0; - std::fill_n(peep->RideTypesBeenOn, 16, 0x00); peep->Id = gNextGuestNumber++; peep->Name = nullptr; @@ -7373,11 +7375,6 @@ static bool IsThoughtShopItemRelated(const PeepThoughtType type) void Guest::RemoveRideFromMemory(ride_id_t rideId) { - uint8_t ride_id_bit = rideId % 8; - uint8_t ride_id_offset = rideId / 8; - - // clear ride from potentially being in RidesBeenOn - RidesBeenOn[ride_id_offset] &= ~(1 << ride_id_bit); if (State == PeepState::Watching) { if (CurrentRide == rideId) diff --git a/src/openrct2/peep/Peep.h b/src/openrct2/peep/Peep.h index 6683f419c9..cf3f035803 100644 --- a/src/openrct2/peep/Peep.h +++ b/src/openrct2/peep/Peep.h @@ -693,11 +693,7 @@ public: uint8_t TimeToConsume; IntensityRange Intensity{ 0 }; PeepNauseaTolerance NauseaTolerance; - uint8_t RideTypesBeenOn[16]; uint16_t TimeInQueue; - // 255 bit bitmap of every ride the peep has been on see - // window_peep_rides_update for how to use. - uint8_t RidesBeenOn[32]; money32 CashInPocket; money32 CashSpent; ride_id_t Photo1RideRef; diff --git a/src/openrct2/peep/RideUseSystem.cpp b/src/openrct2/peep/RideUseSystem.cpp new file mode 100644 index 0000000000..d393dfe93c --- /dev/null +++ b/src/openrct2/peep/RideUseSystem.cpp @@ -0,0 +1,26 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#include "RideUseSystem.h" + +namespace OpenRCT2::RideUse +{ + static RideHistory _history; + static RideTypeHistory _typeHistory; + + RideHistory& GetHistory() + { + return _history; + } + + RideTypeHistory& GetTypeHistory() + { + return _typeHistory; + } +} // namespace OpenRCT2::RideUse diff --git a/src/openrct2/peep/RideUseSystem.h b/src/openrct2/peep/RideUseSystem.h new file mode 100644 index 0000000000..bc1971ef00 --- /dev/null +++ b/src/openrct2/peep/RideUseSystem.h @@ -0,0 +1,22 @@ +/***************************************************************************** + * Copyright (c) 2014-2021 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once +#include "../core/GroupVector.hpp" +#include "../ride/RideTypes.h" + +namespace OpenRCT2::RideUse +{ + using RideHistory = GroupVector; + using RideTypeHistory = GroupVector; + + RideHistory& GetHistory(); + RideTypeHistory& GetTypeHistory(); + +} // namespace OpenRCT2::RideUse diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index c0e9c05d26..c4a4a54212 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -33,6 +33,7 @@ #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../peep/Peep.h" +#include "../peep/RideUseSystem.h" #include "../peep/Staff.h" #include "../ride/RideData.h" #include "../ride/Station.h" @@ -2832,14 +2833,8 @@ template<> void S4Importer::ImportEntity(const RCT12SpriteBase& srcBase) dst->Angriness = src->angriness; dst->TimeLost = src->time_lost; - for (size_t i = 0; i < 32; i++) - { - dst->RidesBeenOn[i] = src->rides_been_on[i]; - } - for (size_t i = 0; i < 16; i++) - { - dst->RideTypesBeenOn[i] = src->ride_types_been_on[i]; - } + OpenRCT2::RideUse::GetHistory().Set(dst->sprite_index, RCT12GetRidesBeenOn(src)); + OpenRCT2::RideUse::GetTypeHistory().Set(dst->sprite_index, RCT12GetRideTypesBeenOn(src)); dst->Photo1RideRef = RCT12RideIdToOpenRCT2RideId(src->photo1_ride_ref); diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index d83239370f..4652c88625 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -17,6 +17,7 @@ #include #include +#include using track_type_t = uint16_t; using RCT12TrackType = uint8_t; @@ -26,6 +27,8 @@ constexpr uint8_t RCT2_STRING_FORMAT_ARG_END = 141; constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_START = 142; constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_END = 156; +constexpr const uint8_t RCT12_MAX_RIDE_OBJECTS = 128; + constexpr const uint8_t RCT12_MAX_RIDES_IN_PARK = 255; constexpr const uint8_t RCT12_MAX_AWARDS = 4; constexpr const uint8_t RCT12_MAX_NEWS_ITEMS = 61; @@ -937,3 +940,28 @@ static constexpr money32 RCT12_COMPANY_VALUE_ON_FAILED_OBJECTIVE = 0x80000001; money64 RCT12CompletedCompanyValueToOpenRCT2(money32 origValue); money32 OpenRCT2CompletedCompanyValueToRCT12(money64 origValue); + +template std::vector RCT12GetRideTypesBeenOn(T* srcPeep) +{ + std::vector ridesTypesBeenOn; + for (uint16_t i = 0; i < RCT12_MAX_RIDE_OBJECTS; i++) + { + if (srcPeep->ride_types_been_on[i / 8] & (1 << (i % 8))) + { + ridesTypesBeenOn.push_back(i); + } + } + return ridesTypesBeenOn; +} +template std::vector RCT12GetRidesBeenOn(T* srcPeep) +{ + std::vector ridesBeenOn; + for (uint16_t i = 0; i < RCT12_MAX_RIDES_IN_PARK; i++) + { + if (srcPeep->rides_been_on[i / 8] & (1 << (i % 8))) + { + ridesBeenOn.push_back(i); + } + } + return ridesBeenOn; +} diff --git a/src/openrct2/rct2/RCT2.h b/src/openrct2/rct2/RCT2.h index 10003fb038..d3a95d98b7 100644 --- a/src/openrct2/rct2/RCT2.h +++ b/src/openrct2/rct2/RCT2.h @@ -39,7 +39,6 @@ constexpr const uint16_t RCT2_MAX_RESEARCHED_SCENERY_ITEMS = (RCT2_MAX_RESEARCHE // per quad. constexpr uint16_t TD6MaxTrackElements = 8192; -constexpr const uint8_t RCT2_MAX_RIDE_OBJECTS = 128; constexpr const uint8_t RCT2_MAX_SMALL_SCENERY_OBJECTS = 252; constexpr const uint8_t RCT2_MAX_LARGE_SCENERY_OBJECTS = 128; constexpr const uint8_t RCT2_MAX_WALL_SCENERY_OBJECTS = 128; @@ -58,7 +57,7 @@ constexpr const uint16_t RCT2_MAXIMUM_MAP_SIZE_TECHNICAL = 256; // clang-format off constexpr const uint16_t RCT2_OBJECT_ENTRY_COUNT = - RCT2_MAX_RIDE_OBJECTS + + RCT12_MAX_RIDE_OBJECTS + RCT2_MAX_SMALL_SCENERY_OBJECTS + RCT2_MAX_LARGE_SCENERY_OBJECTS + RCT2_MAX_WALL_SCENERY_OBJECTS + @@ -74,7 +73,7 @@ static_assert(RCT2_OBJECT_ENTRY_COUNT == 721); // clang-format off constexpr const int32_t rct2_object_entry_group_counts[] = { - RCT2_MAX_RIDE_OBJECTS, + RCT12_MAX_RIDE_OBJECTS, RCT2_MAX_SMALL_SCENERY_OBJECTS, RCT2_MAX_LARGE_SCENERY_OBJECTS, RCT2_MAX_WALL_SCENERY_OBJECTS, diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index b32404921e..9f0d58f773 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -33,6 +33,7 @@ #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../peep/Peep.h" +#include "../peep/RideUseSystem.h" #include "../peep/Staff.h" #include "../rct12/SawyerChunkWriter.h" #include "../ride/Ride.h" @@ -1212,9 +1213,21 @@ template<> void S6Exporter::ExportEntity(RCT2SpritePeep* dst, const Guest* src) dst->intensity = static_cast(src->Intensity); dst->nausea_tolerance = EnumValue(src->NauseaTolerance); dst->paid_on_drink = src->PaidOnDrink; - for (size_t i = 0; i < std::size(src->RideTypesBeenOn); i++) + auto* typeHistory = OpenRCT2::RideUse::GetTypeHistory().GetAll(src->sprite_index); + if (typeHistory != nullptr) { - dst->ride_types_been_on[i] = src->RideTypesBeenOn[i]; + for (auto typeId : *typeHistory) + { + dst->ride_types_been_on[typeId / 8] |= (1 << (typeId % 8)); + } + } + auto* rideHistory = OpenRCT2::RideUse::GetHistory().GetAll(src->sprite_index); + if (rideHistory != nullptr) + { + for (auto rideId : *rideHistory) + { + dst->rides_been_on[rideId / 8] |= (1 << (rideId % 8)); + } } dst->item_extra_flags = static_cast(src->GetItemFlags() >> 32); dst->photo1_ride_ref = OpenRCT2RideIdToRCT12RideId(src->Photo1RideRef); @@ -1223,10 +1236,6 @@ template<> void S6Exporter::ExportEntity(RCT2SpritePeep* dst, const Guest* src) dst->photo4_ride_ref = OpenRCT2RideIdToRCT12RideId(src->Photo4RideRef); dst->next_in_queue = src->GuestNextInQueue; dst->time_in_queue = src->TimeInQueue; - for (size_t i = 0; i < std::size(src->RidesBeenOn); i++) - { - dst->rides_been_on[i] = src->RidesBeenOn[i]; - } dst->cash_in_pocket = src->CashInPocket; dst->cash_spent = src->CashSpent; dst->park_entry_time = src->ParkEntryTime; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 441926fb5a..ed4a4397d9 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -34,6 +34,7 @@ #include "../object/ObjectManager.h" #include "../object/ObjectRepository.h" #include "../peep/Peep.h" +#include "../peep/RideUseSystem.h" #include "../peep/Staff.h" #include "../rct12/RCT12.h" #include "../rct12/SawyerChunkReader.h" @@ -1699,10 +1700,10 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) dst->Intensity = static_cast(src->intensity); dst->NauseaTolerance = static_cast(src->nausea_tolerance); dst->PaidOnDrink = src->paid_on_drink; - for (size_t i = 0; i < std::size(src->ride_types_been_on); i++) - { - dst->RideTypesBeenOn[i] = src->ride_types_been_on[i]; - } + + OpenRCT2::RideUse::GetHistory().Set(dst->sprite_index, RCT12GetRidesBeenOn(src)); + OpenRCT2::RideUse::GetTypeHistory().Set(dst->sprite_index, RCT12GetRideTypesBeenOn(src)); + dst->SetItemFlags(src->GetItemFlags()); dst->Photo1RideRef = RCT12RideIdToOpenRCT2RideId(src->photo1_ride_ref); dst->Photo2RideRef = RCT12RideIdToOpenRCT2RideId(src->photo2_ride_ref); @@ -1710,10 +1711,6 @@ template<> void S6Importer::ImportEntity(const RCT12SpriteBase& baseSrc) dst->Photo4RideRef = RCT12RideIdToOpenRCT2RideId(src->photo4_ride_ref); dst->GuestNextInQueue = src->next_in_queue; dst->TimeInQueue = src->time_in_queue; - for (size_t i = 0; i < std::size(src->rides_been_on); i++) - { - dst->RidesBeenOn[i] = src->rides_been_on[i]; - } dst->CashInPocket = src->cash_in_pocket; dst->CashSpent = src->cash_spent; dst->ParkEntryTime = src->park_entry_time; diff --git a/src/openrct2/world/Entity.cpp b/src/openrct2/world/Entity.cpp index 3d3624dd4e..d3591c07f2 100644 --- a/src/openrct2/world/Entity.cpp +++ b/src/openrct2/world/Entity.cpp @@ -186,9 +186,7 @@ void Guest::Serialise(DataSerialiser& stream) stream << TimeToConsume; stream << Intensity; stream << NauseaTolerance; - stream << RideTypesBeenOn; stream << TimeInQueue; - stream << RidesBeenOn; stream << CashInPocket; stream << CashSpent; stream << Photo1RideRef; diff --git a/src/openrct2/world/Sprite.cpp b/src/openrct2/world/Sprite.cpp index 8c0a36a03f..7537acdc8d 100644 --- a/src/openrct2/world/Sprite.cpp +++ b/src/openrct2/world/Sprite.cpp @@ -17,6 +17,7 @@ #include "../core/MemoryStream.h" #include "../interface/Viewport.h" #include "../peep/Peep.h" +#include "../peep/RideUseSystem.h" #include "../ride/Vehicle.h" #include "../scenario/Scenario.h" #include "Balloon.h" @@ -43,6 +44,8 @@ constexpr const uint32_t SPATIAL_INDEX_LOCATION_NULL = SPATIAL_INDEX_SIZE - 1; static std::array, SPATIAL_INDEX_SIZE> gSpriteSpatialIndex; +static void FreeEntity(SpriteBase* entity); + constexpr size_t GetSpatialIndexOffset(int32_t x, int32_t y) { size_t index = SPATIAL_INDEX_LOCATION_NULL; @@ -226,6 +229,8 @@ void reset_sprite_list() { gSavedAge = 0; std::memset(static_cast(_spriteList), 0, sizeof(_spriteList)); + OpenRCT2::RideUse::GetHistory().Clear(); + OpenRCT2::RideUse::GetTypeHistory().Clear(); for (int32_t i = 0; i < MAX_ENTITIES; ++i) { auto* spr = GetEntity(i); @@ -233,7 +238,7 @@ void reset_sprite_list() { continue; } - + FreeEntity(spr); spr->Type = EntityType::Null; spr->sprite_index = i; @@ -537,17 +542,32 @@ void sprite_set_coordinates(const CoordsXYZ& spritePos, SpriteBase* sprite) sprite->z = spritePos.z; } +/** + * Frees any dynamically attached memory to the entity, such as peep name. + */ +static void FreeEntity(SpriteBase* entity) +{ + auto* guest = entity->As(); + auto* staff = entity->As(); + if (staff != nullptr) + { + staff->SetName({}); + } + else if (guest != nullptr) + { + guest->SetName({}); + OpenRCT2::RideUse::GetHistory().RemoveHandle(guest->sprite_index); + OpenRCT2::RideUse::GetTypeHistory().RemoveHandle(guest->sprite_index); + } +} + /** * * rct2: 0x0069EDB6 */ void sprite_remove(SpriteBase* sprite) { - auto peep = sprite->As(); - if (peep != nullptr) - { - peep->SetName({}); - } + FreeEntity(sprite); EntityTweener::Get().RemoveEntity(sprite); RemoveFromEntityList(sprite); // remove from existing list