diff --git a/src/openrct2/audio/Audio.h b/src/openrct2/audio/Audio.h index 7a46a82c27..758c83dc1e 100644 --- a/src/openrct2/audio/Audio.h +++ b/src/openrct2/audio/Audio.h @@ -154,6 +154,14 @@ namespace OpenRCT2::Audio extern VehicleSound gVehicleSoundList[kMaxVehicleSounds]; + enum class DoorSoundType : uint8_t + { + none, + door, + portcullis, + }; + constexpr uint8_t kDoorSoundTypeCount = 3; + /** * Returns false when no audio device is available or when audio is turned off, otherwise true. */ diff --git a/src/openrct2/object/TerrainEdgeObject.cpp b/src/openrct2/object/TerrainEdgeObject.cpp index 9647581e7f..cd190509aa 100644 --- a/src/openrct2/object/TerrainEdgeObject.cpp +++ b/src/openrct2/object/TerrainEdgeObject.cpp @@ -57,6 +57,11 @@ void TerrainEdgeObject::ReadJson(IReadObjectContext* context, json_t& root) if (properties.is_object()) { HasDoors = Json::GetBoolean(properties["hasDoors"]); + const uint32_t doorSoundNumber = Json::GetNumber(properties["doorSound"]); + if (doorSoundNumber < OpenRCT2::Audio::kDoorSoundTypeCount) + { + doorSound = static_cast(doorSoundNumber); + } } PopulateTablesFromJson(context, root); diff --git a/src/openrct2/object/TerrainEdgeObject.h b/src/openrct2/object/TerrainEdgeObject.h index cdba67383a..93dcfd5145 100644 --- a/src/openrct2/object/TerrainEdgeObject.h +++ b/src/openrct2/object/TerrainEdgeObject.h @@ -9,6 +9,7 @@ #pragma once +#include "../audio/Audio.h" #include "Object.h" class TerrainEdgeObject final : public Object @@ -21,6 +22,7 @@ public: uint32_t IconImageId{}; uint32_t BaseImageId{}; bool HasDoors{}; + OpenRCT2::Audio::DoorSoundType doorSound{}; void ReadJson(IReadObjectContext* context, json_t& root) override; void Load() override; diff --git a/src/openrct2/object/WallSceneryEntry.cpp b/src/openrct2/object/WallSceneryEntry.cpp index ee9711c085..97caf2282c 100644 --- a/src/openrct2/object/WallSceneryEntry.cpp +++ b/src/openrct2/object/WallSceneryEntry.cpp @@ -9,7 +9,8 @@ #include "WallSceneryEntry.h" -DoorSoundType WallSceneryEntry::getDoorSoundType() const +OpenRCT2::Audio::DoorSoundType WallSceneryEntry::getDoorSoundType() const { - return static_cast((flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT); + return static_cast( + (flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT); } diff --git a/src/openrct2/object/WallSceneryEntry.h b/src/openrct2/object/WallSceneryEntry.h index 2fff156f62..0230a49daf 100644 --- a/src/openrct2/object/WallSceneryEntry.h +++ b/src/openrct2/object/WallSceneryEntry.h @@ -9,6 +9,7 @@ #pragma once +#include "../audio/Audio.h" #include "../core/Money.hpp" #include "../localisation/StringIdType.h" #include "ObjectTypes.h" @@ -36,13 +37,6 @@ enum WALL_SCENERY_2_FLAGS WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10 }; -enum class DoorSoundType : uint8_t -{ - none, - door, - portcullis, -}; - struct WallSceneryEntry { static constexpr auto kObjectType = ObjectType::walls; @@ -57,5 +51,5 @@ struct WallSceneryEntry ObjectEntryIndex scenery_tab_id; uint8_t scrolling_mode; - DoorSoundType getDoorSoundType() const; + OpenRCT2::Audio::DoorSoundType getDoorSoundType() const; }; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 883329451f..749636ccae 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -440,12 +440,14 @@ static constexpr OpenRCT2::Audio::SoundId kDoorOpenSoundIds[] = { OpenRCT2::Audio::SoundId::DoorOpen, // DoorSoundType::door OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; +static_assert(std::size(kDoorOpenSoundIds) == OpenRCT2::Audio::kDoorSoundTypeCount); static constexpr OpenRCT2::Audio::SoundId kDoorCloseSoundIds[] = { OpenRCT2::Audio::SoundId::Null, // DoorSoundType::none OpenRCT2::Audio::SoundId::DoorClose, // DoorSoundType::door OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; +static_assert(std::size(kDoorCloseSoundIds) == OpenRCT2::Audio::kDoorSoundTypeCount); template<> bool EntityBase::Is() const @@ -6347,7 +6349,9 @@ void Vehicle::UpdateSceneryDoor() const } template -static void AnimateLandscapeDoor(const CoordsXYZ& doorLocation, TrackElement& trackElement, const bool isLastVehicle) +static void AnimateLandscapeDoor( + const CoordsXYZ& doorLocation, TrackElement& trackElement, const bool isLastVehicle, + const OpenRCT2::Audio::DoorSoundType doorSound, const CoordsXYZ& soundLocation) { const auto doorState = isBackwards ? trackElement.GetDoorAState() : trackElement.GetDoorBState(); if (!isLastVehicle && doorState == kLandEdgeDoorFrameClosed) @@ -6358,6 +6362,7 @@ static void AnimateLandscapeDoor(const CoordsXYZ& doorLocation, TrackElement& tr trackElement.SetDoorBState(kLandEdgeDoorFrameOpening); MapAnimations::CreateTemporary(doorLocation, MapAnimations::TemporaryType::landEdgeDoor); + OpenRCT2::Audio::Play3D(kDoorOpenSoundIds[EnumValue(doorSound)], soundLocation); } if (isLastVehicle) @@ -6368,6 +6373,7 @@ static void AnimateLandscapeDoor(const CoordsXYZ& doorLocation, TrackElement& tr trackElement.SetDoorBState(kLandEdgeDoorFrameClosing); MapAnimations::CreateTemporary(doorLocation, MapAnimations::TemporaryType::landEdgeDoor); + OpenRCT2::Audio::Play3D(kDoorCloseSoundIds[EnumValue(doorSound)], soundLocation); } } @@ -6398,8 +6404,13 @@ void Vehicle::UpdateLandscapeDoors(const int32_t previousTrackHeight) const const auto* const surfaceElement = GetSurfaceElementAfterElement(previousTrackElement); if (surfaceElement != nullptr && surfaceElement->GetBaseZ() > previousTrackLocation.z) { - AnimateLandscapeDoor( - previousTrackLocation, *previousTrackElement->AsTrack(), next_vehicle_on_train.IsNull()); + const auto* const edgeObject = surfaceElement->GetEdgeObject(); + if (edgeObject != nullptr && edgeObject->HasDoors) + { + AnimateLandscapeDoor( + previousTrackLocation, *previousTrackElement->AsTrack(), next_vehicle_on_train.IsNull(), + edgeObject->doorSound, TrackLocation); + } } } else if (previousTrackElement == nullptr && currentTrackElement != nullptr) @@ -6407,7 +6418,13 @@ void Vehicle::UpdateLandscapeDoors(const int32_t previousTrackHeight) const const auto* const surfaceElement = GetSurfaceElementAfterElement(currentTrackElement); if (surfaceElement != nullptr && surfaceElement->GetBaseZ() > TrackLocation.z) { - AnimateLandscapeDoor(TrackLocation, *currentTrackElement->AsTrack(), next_vehicle_on_train.IsNull()); + const auto* const edgeObject = surfaceElement->GetEdgeObject(); + if (edgeObject != nullptr && edgeObject->HasDoors) + { + AnimateLandscapeDoor( + TrackLocation, *currentTrackElement->AsTrack(), next_vehicle_on_train.IsNull(), edgeObject->doorSound, + previousTrackLocation); + } } } }