From 709a2d89143119ec4db4ee524f6c215704d6d2c6 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 27 Oct 2024 21:23:10 +0100 Subject: [PATCH] Fix #22908: Crash when passing through invalid wall door --- distribution/changelog.txt | 1 + src/openrct2/actions/WallPlaceAction.h | 2 ++ src/openrct2/libopenrct2.vcxproj | 1 + src/openrct2/object/WallSceneryEntry.cpp | 15 ++++++++ src/openrct2/object/WallSceneryEntry.h | 11 +++++- src/openrct2/ride/Vehicle.cpp | 44 ++++++++++++++---------- src/openrct2/world/Scenery.cpp | 5 --- src/openrct2/world/Scenery.h | 4 --- 8 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 src/openrct2/object/WallSceneryEntry.cpp diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 7494e672a7a9..87ee3ab65727 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -4,6 +4,7 @@ - Improved: [#23010] Make AppImage compatible with Ubuntu 22.04 and Debian Bookworm again. - Fix: [#22615] Crash when drawing Space Rings with an invalid ride entry. - Fix: [#22633] Crash when drawing loading screen with an outdated g2.dat. +- Fix: [#22908] Crash when passing through a door from an invalid wall type. - Fix: [#22918] Zooming with keyboard moves the view off centre. - Fix: [#22920] Crash when sacking a staff member. - Fix: [#22921] Wooden RollerCoaster flat to steep railings appear in front of track in front of them. diff --git a/src/openrct2/actions/WallPlaceAction.h b/src/openrct2/actions/WallPlaceAction.h index c511e9b3070f..f8ba664ada91 100644 --- a/src/openrct2/actions/WallPlaceAction.h +++ b/src/openrct2/actions/WallPlaceAction.h @@ -15,6 +15,8 @@ #include "../world/Scenery.h" #include "GameAction.h" +struct WallSceneryEntry; + struct WallPlaceActionResult { int32_t BaseHeight{}; diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 74ea55ec6ec1..8800560ef928 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -881,6 +881,7 @@ + diff --git a/src/openrct2/object/WallSceneryEntry.cpp b/src/openrct2/object/WallSceneryEntry.cpp new file mode 100644 index 000000000000..b66e282e6ae0 --- /dev/null +++ b/src/openrct2/object/WallSceneryEntry.cpp @@ -0,0 +1,15 @@ +/***************************************************************************** + * Copyright (c) 2014-2024 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 "WallSceneryEntry.h" + +DoorSoundType WallSceneryEntry::getDoorSoundType() const +{ + 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 eb0b07dbb7d7..7fd9b0f53f80 100644 --- a/src/openrct2/object/WallSceneryEntry.h +++ b/src/openrct2/object/WallSceneryEntry.h @@ -30,12 +30,19 @@ enum WALL_SCENERY_FLAGS enum WALL_SCENERY_2_FLAGS { WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR = (1 << 0), // 0x1 - WALL_SCENERY_2_DOOR_SOUND_MASK = 0x6, + WALL_SCENERY_2_DOOR_SOUND_MASK = 0b0110, WALL_SCENERY_2_DOOR_SOUND_SHIFT = 1, WALL_SCENERY_2_IS_OPAQUE = (1 << 3), // 0x8 WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10 }; +enum class DoorSoundType : uint8_t +{ + none, + door, + portcullis, +}; + struct WallSceneryEntry { static constexpr auto kObjectType = ObjectType::Walls; @@ -49,4 +56,6 @@ struct WallSceneryEntry money64 price; ObjectEntryIndex scenery_tab_id; uint8_t scrolling_mode; + + DoorSoundType getDoorSoundType() const; }; diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index c65cee84467b..1460cfb79281 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -439,13 +439,15 @@ static constexpr CoordsXY AvoidCollisionMoveOffset[] = { }; static constexpr OpenRCT2::Audio::SoundId DoorOpenSoundIds[] = { - OpenRCT2::Audio::SoundId::DoorOpen, - OpenRCT2::Audio::SoundId::Portcullis, + OpenRCT2::Audio::SoundId::Null, // DoorSoundType::none + OpenRCT2::Audio::SoundId::DoorOpen, // DoorSoundType::door + OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; static constexpr OpenRCT2::Audio::SoundId DoorCloseSoundIds[] = { - OpenRCT2::Audio::SoundId::DoorClose, - OpenRCT2::Audio::SoundId::Portcullis, + OpenRCT2::Audio::SoundId::Null, // DoorSoundType::none + OpenRCT2::Audio::SoundId::DoorClose, // DoorSoundType::door + OpenRCT2::Audio::SoundId::Portcullis, // DoorSoundType::portcullis }; template<> bool EntityBase::Is() const @@ -6246,14 +6248,17 @@ void Vehicle::UpdateAdditionalAnimation() static void play_scenery_door_open_sound(const CoordsXYZ& loc, WallElement* tileElement) { auto* wallEntry = tileElement->GetEntry(); - int32_t doorSoundType = WallEntryGetDoorSound(wallEntry); - if (doorSoundType != 0) + if (wallEntry == nullptr) + return; + + auto doorSoundType = wallEntry->getDoorSoundType(); + if (doorSoundType == DoorSoundType::none) + return; + + auto soundId = DoorOpenSoundIds[EnumValue(doorSoundType)]; + if (soundId != OpenRCT2::Audio::SoundId::Null) { - auto soundId = DoorOpenSoundIds[doorSoundType - 1]; - if (soundId != OpenRCT2::Audio::SoundId::Null) - { - OpenRCT2::Audio::Play3D(soundId, loc); - } + OpenRCT2::Audio::Play3D(soundId, loc); } } @@ -6264,14 +6269,17 @@ static void play_scenery_door_open_sound(const CoordsXYZ& loc, WallElement* tile static void play_scenery_door_close_sound(const CoordsXYZ& loc, WallElement* tileElement) { auto* wallEntry = tileElement->GetEntry(); - int32_t doorSoundType = WallEntryGetDoorSound(wallEntry); - if (doorSoundType != 0) + if (wallEntry == nullptr) + return; + + auto doorSoundType = wallEntry->getDoorSoundType(); + if (doorSoundType == DoorSoundType::none) + return; + + auto soundId = DoorCloseSoundIds[EnumValue(doorSoundType)]; + if (soundId != OpenRCT2::Audio::SoundId::Null) { - auto soundId = DoorCloseSoundIds[doorSoundType - 1]; - if (soundId != OpenRCT2::Audio::SoundId::Null) - { - Play3D(soundId, loc); - } + Play3D(soundId, loc); } } diff --git a/src/openrct2/world/Scenery.cpp b/src/openrct2/world/Scenery.cpp index d070fd4c7908..33caedd22b6c 100644 --- a/src/openrct2/world/Scenery.cpp +++ b/src/openrct2/world/Scenery.cpp @@ -300,11 +300,6 @@ void SceneryRemoveGhostToolPlacement() } } -int32_t WallEntryGetDoorSound(const WallSceneryEntry* wallEntry) -{ - return (wallEntry->flags2 & WALL_SCENERY_2_DOOR_SOUND_MASK) >> WALL_SCENERY_2_DOOR_SOUND_SHIFT; -} - bool IsSceneryAvailableToBuild(const ScenerySelection& item) { // All scenery can be built when in the scenario editor diff --git a/src/openrct2/world/Scenery.h b/src/openrct2/world/Scenery.h index 2d22ae0c556e..5810257525a3 100644 --- a/src/openrct2/world/Scenery.h +++ b/src/openrct2/world/Scenery.h @@ -69,10 +69,6 @@ extern const CoordsXY SceneryQuadrantOffsets[]; void SceneryUpdateTile(const CoordsXY& sceneryPos); void SceneryRemoveGhostToolPlacement(); -struct WallSceneryEntry; - -int32_t WallEntryGetDoorSound(const WallSceneryEntry* wallEntry); - bool IsSceneryAvailableToBuild(const ScenerySelection& item); bool IsSceneryItemRestricted(const ScenerySelection& item);