From a786c89603f09efbeb58d9d0657faabe051f5e9c Mon Sep 17 00:00:00 2001 From: Aaron van Geffen Date: Mon, 2 Dec 2024 17:15:51 +0100 Subject: [PATCH] Start working on peep entity animation object conversion --- src/openrct2/entity/Peep.h | 1 + src/openrct2/object/PeepAnimationsObject.cpp | 20 ++++++ src/openrct2/object/PeepAnimationsObject.h | 3 + src/openrct2/park/Legacy.cpp | 72 ++++++++++++++++++++ src/openrct2/park/Legacy.h | 3 + src/openrct2/park/ParkFile.cpp | 14 +++- src/openrct2/peep/PeepAnimations.h | 6 +- src/openrct2/rct1/S4Importer.cpp | 6 +- src/openrct2/rct2/S6Importer.cpp | 5 ++ 9 files changed, 125 insertions(+), 5 deletions(-) diff --git a/src/openrct2/entity/Peep.h b/src/openrct2/entity/Peep.h index 01911b76fb..9e23450a7a 100644 --- a/src/openrct2/entity/Peep.h +++ b/src/openrct2/entity/Peep.h @@ -313,6 +313,7 @@ struct Peep : EntityBase PeepRideSubState RideSubState; PeepUsingBinSubState UsingBinSubState; }; + ObjectEntryIndex AnimationObjectIndex; PeepAnimationGroup AnimationGroup; uint8_t TshirtColour; uint8_t TrousersColour; diff --git a/src/openrct2/object/PeepAnimationsObject.cpp b/src/openrct2/object/PeepAnimationsObject.cpp index 620a4c677f..a89baea185 100644 --- a/src/openrct2/object/PeepAnimationsObject.cpp +++ b/src/openrct2/object/PeepAnimationsObject.cpp @@ -90,10 +90,30 @@ void PeepAnimationsObject::ReadJson(IReadObjectContext* context, json_t& root) group[typeEnum] = anim; } + // Is this animation group replacing a legacy group? + if (groupJson.contains("legacyPosition")) + { + auto position = Json::GetNumber(groupJson["legacyPosition"]); + if (position <= EnumValue(PeepAnimationGroup::Count)) + { + group.legacyPosition = static_cast(position); + } + } + _animationGroups.push_back(group); } } +size_t PeepAnimationsObject::GetNumAnimationGroups() const +{ + return _animationGroups.size(); +} + +PeepAnimationGroup PeepAnimationsObject::GetLegacyPosition(PeepAnimationGroup animGroup) const +{ + return _animationGroups[EnumValue(animGroup)].legacyPosition; +} + void PeepAnimationsObject::DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const { auto centre = ScreenCoordsXY{ width / 2, height / 2 }; diff --git a/src/openrct2/object/PeepAnimationsObject.h b/src/openrct2/object/PeepAnimationsObject.h index b9415a61d1..ee5a1f6e5c 100644 --- a/src/openrct2/object/PeepAnimationsObject.h +++ b/src/openrct2/object/PeepAnimationsObject.h @@ -29,5 +29,8 @@ public: void Load() override; void Unload() override; + size_t GetNumAnimationGroups() const; + PeepAnimationGroup GetLegacyPosition(PeepAnimationGroup animGroup) const; + void DrawPreview(DrawPixelInfo& dpi, int32_t width, int32_t height) const override; }; diff --git a/src/openrct2/park/Legacy.cpp b/src/openrct2/park/Legacy.cpp index 1644e4c2f2..dec5defd4c 100644 --- a/src/openrct2/park/Legacy.cpp +++ b/src/openrct2/park/Legacy.cpp @@ -9,7 +9,15 @@ #include "Legacy.h" +#include "../Context.h" +#include "../Diagnostic.h" +#include "../entity/EntityList.h" +#include "../entity/Guest.h" +#include "../entity/Staff.h" +#include "../object/ObjectLimits.h" #include "../object/ObjectList.h" +#include "../object/ObjectManager.h" +#include "../object/PeepAnimationsObject.h" #include "../rct2/RCT2.h" #include "../ride/Ride.h" #include "../ride/Track.h" @@ -2289,6 +2297,70 @@ const std::vector& GetLegacyPeepAnimationObjects(const ObjectL return peepAnimObjects; } +// TODO: change type to legacy PeepAnimationGroup and new PeepAnimationGroup +using AnimObjectConversionTable = std::map>; + +static AnimObjectConversionTable BuildPeepAnimObjectConversionTable() +{ + auto& objectManager = GetContext()->GetObjectManager(); + + AnimObjectConversionTable table{}; + for (auto i = 0u; i < kMaxPeepAnimationsObjects; i++) + { + auto object = objectManager.GetLoadedObject(i); + if (object == nullptr) + continue; + + for (auto j = 0u; j < object->GetNumAnimationGroups(); j++) + { + auto legacyPosition = object->GetLegacyPosition(PeepAnimationGroup(j)); + if (legacyPosition == PeepAnimationGroup::Invalid) + continue; + + table[legacyPosition] = { i, j }; + } + } + + return table; +} + +template +static bool ConvertPeepAnimationType(TPeepType* peep, AnimObjectConversionTable& table) +{ + if (peep->AnimationObjectIndex != OBJECT_ENTRY_INDEX_NULL) + return false; + + // TODO: catch missings + auto conversion = table[peep->AnimationGroup]; + peep->AnimationObjectIndex = conversion.first; + peep->AnimationGroup = static_cast(conversion.second); + return true; +} + +void ConvertPeepAnimationTypeToObjects(OpenRCT2::GameState_t& gameState) +{ + // First, build a conversion table based on the currently selected objects + auto table = BuildPeepAnimObjectConversionTable(); + + auto numConverted = 0u; + + // Convert all guests + for (auto* guest : EntityList()) + { + if (ConvertPeepAnimationType(guest, table)) + numConverted++; + } + + // Convert all staff members + for (auto* staff : EntityList()) + { + if (ConvertPeepAnimationType(staff, table)) + numConverted++; + } + + LOG_INFO("Converted %d peep entities", numConverted); +} + bool TrackTypeMustBeMadeInvisible(ride_type_t rideType, OpenRCT2::TrackElemType trackType, int32_t parkFileVersion) { // Lots of Log Flumes exist where the downward slopes are simulated by using other track diff --git a/src/openrct2/park/Legacy.h b/src/openrct2/park/Legacy.h index 3b9987c973..3453e49376 100644 --- a/src/openrct2/park/Legacy.h +++ b/src/openrct2/park/Legacy.h @@ -18,6 +18,8 @@ namespace OpenRCT2 { + struct GameState_t; + enum class TrackElemType : uint16_t; namespace RCT2 @@ -39,6 +41,7 @@ void UpdateFootpathsFromMapping( const OpenRCT2::RCT2::FootpathMapping* footpathMapping); const std::vector& GetLegacyPeepAnimationObjects(const ObjectList& entryList); +void ConvertPeepAnimationTypeToObjects(OpenRCT2::GameState_t& gameState); /** * If new pieces get added to existing ride types, this could cause existing parks to change appearance, diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index e9d43a2277..ff9f10f884 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -1725,6 +1725,12 @@ namespace OpenRCT2 cs.ReadWrite(entity.State); cs.ReadWrite(entity.SubState); + + if (version >= kPeepAnimationObjectsVersion) + cs.ReadWrite(entity.AnimationObjectIndex); + else + entity.AnimationObjectIndex = OBJECT_ENTRY_INDEX_NULL; + cs.ReadWrite(entity.AnimationGroup); if (version <= 1) @@ -2575,7 +2581,7 @@ namespace OpenRCT2 void ParkFile::ReadWriteEntitiesChunk(GameState_t& gameState, OrcaStream& os) { - os.ReadWriteChunk(ParkFileChunkType::ENTITIES, [this, &os](OrcaStream::ChunkStream& cs) { + os.ReadWriteChunk(ParkFileChunkType::ENTITIES, [this, &gameState, &os](OrcaStream::ChunkStream& cs) { if (cs.GetMode() == OrcaStream::Mode::READING) { ResetAllEntities(); @@ -2587,6 +2593,12 @@ namespace OpenRCT2 ReadEntitiesOfTypes< Vehicle, Guest, Staff, Litter, SteamParticle, MoneyEffect, VehicleCrashParticle, ExplosionCloud, CrashSplashParticle, ExplosionFlare, JumpingFountain, Balloon, Duck>(os, cs); + + auto version = os.GetHeader().TargetVersion; + if (version < kPeepAnimationObjectsVersion) + { + ConvertPeepAnimationTypeToObjects(gameState); + } } else { diff --git a/src/openrct2/peep/PeepAnimations.h b/src/openrct2/peep/PeepAnimations.h index b68f771dd0..46632180ed 100644 --- a/src/openrct2/peep/PeepAnimations.h +++ b/src/openrct2/peep/PeepAnimations.h @@ -16,9 +16,6 @@ #include -enum class PeepAnimationGroup : uint8_t; -enum class PeepAnimationType : uint8_t; - namespace OpenRCT2 { enum class AnimationPeepType : uint8_t @@ -58,6 +55,9 @@ namespace OpenRCT2 struct PeepAnimations { public: + // TODO: move type to RCT12? + PeepAnimationGroup legacyPosition = PeepAnimationGroup::Invalid; + constexpr PeepAnimation& operator[](PeepAnimationType n) { return animations[EnumValue(n)]; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 5627591e3b..9075894a48 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -207,6 +207,8 @@ namespace OpenRCT2::RCT1 ImportScenarioObjective(gameState); ImportSavedView(gameState); + ConvertPeepAnimationTypeToObjects(gameState); + if (_isScenario) { RCT12::FetchAndApplyScenarioPatch(_s4Path); @@ -1319,8 +1321,10 @@ namespace OpenRCT2::RCT1 void ImportPeep(::Peep* dst, const RCT1::Peep* src) { - // Peep vs. staff (including which kind) + // TODO + dst->AnimationObjectIndex = OBJECT_ENTRY_INDEX_NULL; dst->AnimationGroup = RCT1::GetPeepAnimationGroup(src->AnimationGroup); + dst->Action = static_cast(src->Action); dst->SpecialSprite = src->SpecialSprite; dst->NextAnimationType = static_cast(src->NextAnimationType); diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index fe304fa486..7fc96a042c 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -352,6 +352,7 @@ namespace OpenRCT2::RCT2 DetermineFlatRideStatus(); ImportTileElements(gameState); ImportEntities(); + ConvertPeepAnimationTypeToObjects(gameState); gameState.InitialCash = ToMoney64(_s6.InitialCash); gameState.BankLoan = ToMoney64(_s6.CurrentLoan); @@ -1647,7 +1648,11 @@ namespace OpenRCT2::RCT2 dst->NextFlags = src->NextFlags; dst->State = static_cast(src->State); dst->SubState = src->SubState; + + // TODO + dst->AnimationObjectIndex = OBJECT_ENTRY_INDEX_NULL; dst->AnimationGroup = static_cast(src->AnimationGroup); + dst->TshirtColour = src->TshirtColour; dst->TrousersColour = src->TrousersColour; dst->DestinationX = src->DestinationX;