diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index faf7c6e78b..f29e6ecc3b 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7098,7 +7098,7 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack( if (trackType == TrackElemType::OnRidePhoto) { tileElement->AsTrack()->SetPhotoTimeout(); - MapAnimation::Create(TrackLocation); + MapAnimation::CreateTemporary(TrackLocation, MapAnimation::TemporaryType::onRidePhoto); } if (trackType == TrackElemType::RotationControlToggle) { diff --git a/src/openrct2/world/MapAnimation.cpp b/src/openrct2/world/MapAnimation.cpp index 5951dc8f5c..cb02737820 100644 --- a/src/openrct2/world/MapAnimation.cpp +++ b/src/openrct2/world/MapAnimation.cpp @@ -40,6 +40,18 @@ using namespace OpenRCT2; +struct TemporaryMapAnimation +{ + CoordsXYZ location{}; + MapAnimation::TemporaryType type{}; + + bool operator<(const TemporaryMapAnimation& rhs) const + { + return std::tie(location.y, location.x, type, location.z) + < std::tie(rhs.location.y, rhs.location.x, rhs.type, rhs.location.z); + } +}; + struct TileCoordsXYCmp { constexpr bool operator()(const TileCoordsXY& lhs, const TileCoordsXY& rhs) const noexcept @@ -52,6 +64,8 @@ struct TileCoordsXYCmp // A list of tile coordinates which contains animated tile elements. static std::set _mapAnimations; +static std::set _temporaryMapAnimations; + static bool UpdateEntranceAnimation(const EntranceElement& entrance, const CoordsXYZ& loc, const int32_t baseZ) { if (entrance.GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE) @@ -136,7 +150,6 @@ static bool UpdateSmallSceneryAnimation(const SmallSceneryElement& scenery, cons static bool UpdateTrackAnimation(TrackElement& track, const CoordsXYZ& loc, const int32_t baseZ) { - const auto clearZ = track.GetClearanceZ(); switch (track.GetTrackType()) { case TrackElemType::Waterfall: @@ -149,13 +162,6 @@ static bool UpdateTrackAnimation(TrackElement& track, const CoordsXYZ& loc, cons case TrackElemType::SpinningTunnel: MapInvalidateTileZoom1({ loc, baseZ + 14, baseZ + 32 }); return true; - case TrackElemType::OnRidePhoto: - if (track.IsTakingPhoto()) - { - MapInvalidateTileZoom1({ loc, baseZ, clearZ }); - track.DecrementPhotoTimeout(); - return true; - } default: break; } @@ -281,6 +287,46 @@ static bool UpdateTileAnimations(const TileCoordsXY& coords) return hasAnimations; } +static bool UpdateOnRidePhotoAnimation(TrackElement& track, const CoordsXYZ& coords) +{ + if (track.IsTakingPhoto()) + { + track.DecrementPhotoTimeout(); + MapInvalidateTileZoom1({ coords, track.GetClearanceZ() }); + return true; + } + return false; +} + +static bool UpdateTemporaryAnimation(const TemporaryMapAnimation& animation) +{ + const TileCoordsXYZ tileCoords{ animation.location }; + TileElement* tileElement = MapGetFirstElementAt(tileCoords); + if (tileElement == nullptr) + { + return true; + } + + bool hasAnimations = false; + do + { + switch (animation.type) + { + case MapAnimation::TemporaryType::onRidePhoto: + { + if (tileElement->GetType() == TileElementType::Track && tileElement->BaseHeight == tileCoords.z + && tileElement->AsTrack()->GetTrackType() == TrackElemType::OnRidePhoto) + { + hasAnimations |= UpdateOnRidePhotoAnimation(*tileElement->AsTrack(), animation.location); + } + break; + } + } + } while (!(tileElement++)->IsLastForTile()); + + return hasAnimations; +} + static bool IsElementAnimated(const TileElementBase& element, const bool skipDoors) { switch (element.GetType()) @@ -355,7 +401,6 @@ static bool IsElementAnimated(const TileElementBase& element, const bool skipDoo case TrackElemType::Rapids: case TrackElemType::Whirlpool: case TrackElemType::SpinningTunnel: - case TrackElemType::OnRidePhoto: return true; default: break; @@ -374,6 +419,11 @@ void MapAnimation::Create(const CoordsXY coords) _mapAnimations.insert(TileCoordsXY(coords)); } +void MapAnimation::CreateTemporary(const CoordsXYZ& coords, const TemporaryType type) +{ + _temporaryMapAnimations.insert(TemporaryMapAnimation{ coords, type }); +} + void MapAnimation::CreateAll() { ClearAll(); @@ -389,27 +439,35 @@ void MapAnimation::CreateAll() } } +template +static void UpdateAll(auto& mapAnimations) +{ + auto it = mapAnimations.begin(); + while (it != mapAnimations.end()) + { + if (TUpdateFunction(*it)) + { + ++it; + } + else + { + it = mapAnimations.erase(it); + } + } +} + void MapAnimation::UpdateAll() { PROFILED_FUNCTION(); - auto it = _mapAnimations.begin(); - while (it != _mapAnimations.end()) - { - if (UpdateTileAnimations(*it)) - { - ++it; // Tile was updated, keep it - } - else - { - it = _mapAnimations.erase(it); // No updates, remove tile - } - } + UpdateAll(_mapAnimations); + UpdateAll(_temporaryMapAnimations); } void MapAnimation::ClearAll() { _mapAnimations.clear(); + _temporaryMapAnimations.clear(); } void MapAnimation::ShiftAll(const CoordsXY amount) @@ -423,4 +481,11 @@ void MapAnimation::ShiftAll(const CoordsXY amount) newMapAnimations.insert(a + TileCoordsXY(amount)); } _mapAnimations = std::move(newMapAnimations); + + std::set newTemporaryMapAnimations; + for (const auto& a : _temporaryMapAnimations) + { + newTemporaryMapAnimations.insert(TemporaryMapAnimation{ a.location + CoordsXYZ(amount, 0), a.type }); + } + _temporaryMapAnimations = std::move(newTemporaryMapAnimations); } diff --git a/src/openrct2/world/MapAnimation.h b/src/openrct2/world/MapAnimation.h index b7293c6570..a3002bf670 100644 --- a/src/openrct2/world/MapAnimation.h +++ b/src/openrct2/world/MapAnimation.h @@ -13,7 +13,13 @@ namespace OpenRCT2::MapAnimation { + enum class TemporaryType : uint8_t + { + onRidePhoto, + }; + void Create(const CoordsXY coords); + void CreateTemporary(const CoordsXYZ& coords, const TemporaryType type); void CreateAll(); void UpdateAll(); void ClearAll();