From 7bdd1a48232e894f9c8bc54ff390a012d6aa8749 Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sun, 21 Dec 2025 00:08:05 +0100 Subject: [PATCH] Fix #25639: Scenery window crashes when a no longer present object is still selected --- distribution/changelog.txt | 3 +- src/openrct2-ui/windows/Scenery.cpp | 80 ++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 0b14623a87..c6e6879ea5 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -22,7 +22,8 @@ - Fix: [#25571] Potential crash due to drawing a Crooked House ride. - Fix: [#25588] When the master server becomes unreachable the server would not register again until a restart. - Fix: [#25592] Log flume, river rapids, & splash boats can get control failure breakdown instead of brakes failure. -- Fix: [#25628] Availability of AVX2 and SSE4.1 is not detected correctly. +- Fix: [#25628] Availability of AVX2 and SSE4.1 is not detected correctly. +- Fix: [#25639] Scenery window crashes when a no longer present object is still selected. - Fix: [#25642] The selection marker for purchasing land rights is not drawn with the correct colours. - Fix: [#25646] It is possible to remove scenery and paths when setting staff patrol areas and purchasing land. diff --git a/src/openrct2-ui/windows/Scenery.cpp b/src/openrct2-ui/windows/Scenery.cpp index 417a22fb4e..93cc170766 100644 --- a/src/openrct2-ui/windows/Scenery.cpp +++ b/src/openrct2-ui/windows/Scenery.cpp @@ -590,23 +590,39 @@ namespace OpenRCT2::Ui::Windows } else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_LARGE) { - gCurrentToolId = static_cast( - ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex)->tool_id); + const auto* sceneryEntry = ObjectManager::GetObjectEntry( + tabSelectedScenery.EntryIndex); + if (sceneryEntry != nullptr) + { + gCurrentToolId = static_cast(sceneryEntry->tool_id); + } } else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_WALL) { - gCurrentToolId = static_cast( - ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex)->tool_id); + const auto* sceneryEntry = ObjectManager::GetObjectEntry( + tabSelectedScenery.EntryIndex); + if (sceneryEntry != nullptr) + { + gCurrentToolId = static_cast(sceneryEntry->tool_id); + } } else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_PATH_ITEM) { - gCurrentToolId = static_cast( - ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex)->tool_id); + const auto* sceneryEntry = ObjectManager::GetObjectEntry( + tabSelectedScenery.EntryIndex); + if (sceneryEntry != nullptr) + { + gCurrentToolId = static_cast(sceneryEntry->tool_id); + } } - else - { // small scenery - gCurrentToolId = static_cast( - ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex)->tool_id); + else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_SMALL) + { + const auto* sceneryEntry = ObjectManager::GetObjectEntry( + tabSelectedScenery.EntryIndex); + if (sceneryEntry != nullptr) + { + gCurrentToolId = static_cast(sceneryEntry->tool_id); + } } } else @@ -712,7 +728,7 @@ namespace OpenRCT2::Ui::Windows widgets[WIDX_SCENERY_BUILD_CLUSTER_BUTTON].type = WidgetType::flatBtn; auto* sceneryEntry = ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex); - if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ROTATABLE)) + if (sceneryEntry != nullptr && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_ROTATABLE)) { widgets[WIDX_SCENERY_ROTATE_OBJECTS_BUTTON].type = WidgetType::flatBtn; } @@ -751,7 +767,7 @@ namespace OpenRCT2::Ui::Windows if (tabSelectedScenery.SceneryType == SCENERY_TYPE_BANNER) { auto* bannerEntry = ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex); - if (bannerEntry->flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR) + if (bannerEntry != nullptr && bannerEntry->flags & BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR) { widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WidgetType::colourBtn; } @@ -759,20 +775,22 @@ namespace OpenRCT2::Ui::Windows else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_LARGE) { auto* sceneryEntry = ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex); - - if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR - && !(sceneryEntry->flags & LARGE_SCENERY_FLAG_HIDE_PRIMARY_REMAP_BUTTON)) - widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WidgetType::colourBtn; - if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR - && !(sceneryEntry->flags & LARGE_SCENERY_FLAG_HIDE_SECONDARY_REMAP_BUTTON)) - widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WidgetType::colourBtn; - if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR) - widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WidgetType::colourBtn; + if (sceneryEntry != nullptr) + { + if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR + && !(sceneryEntry->flags & LARGE_SCENERY_FLAG_HIDE_PRIMARY_REMAP_BUTTON)) + widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WidgetType::colourBtn; + if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR + && !(sceneryEntry->flags & LARGE_SCENERY_FLAG_HIDE_SECONDARY_REMAP_BUTTON)) + widgets[WIDX_SCENERY_SECONDARY_COLOUR_BUTTON].type = WidgetType::colourBtn; + if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_TERTIARY_COLOUR) + widgets[WIDX_SCENERY_TERTIARY_COLOUR_BUTTON].type = WidgetType::colourBtn; + } } else if (tabSelectedScenery.SceneryType == SCENERY_TYPE_WALL) { auto* wallEntry = ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex); - if (wallEntry->flags & (WALL_SCENERY_HAS_PRIMARY_COLOUR | WALL_SCENERY_HAS_GLASS)) + if (wallEntry != nullptr && wallEntry->flags & (WALL_SCENERY_HAS_PRIMARY_COLOUR | WALL_SCENERY_HAS_GLASS)) { widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WidgetType::colourBtn; @@ -791,7 +809,8 @@ namespace OpenRCT2::Ui::Windows { auto* sceneryEntry = ObjectManager::GetObjectEntry(tabSelectedScenery.EntryIndex); - if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG_HAS_GLASS)) + if (sceneryEntry != nullptr + && sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR | SMALL_SCENERY_FLAG_HAS_GLASS)) { widgets[WIDX_SCENERY_PRIMARY_COLOUR_BUTTON].type = WidgetType::colourBtn; @@ -1573,6 +1592,9 @@ namespace OpenRCT2::Ui::Windows if (scenerySelection.SceneryType == SCENERY_TYPE_BANNER) { auto bannerEntry = ObjectManager::GetObjectEntry(scenerySelection.EntryIndex); + if (bannerEntry == nullptr) + return; + auto imageId = ImageId(bannerEntry->image + gWindowSceneryRotation * 2, _sceneryPrimaryColour); GfxDrawSprite(rt, imageId, { 33, 40 }); GfxDrawSprite(rt, imageId.WithIndexOffset(1), { 33, 40 }); @@ -1580,6 +1602,9 @@ namespace OpenRCT2::Ui::Windows else if (scenerySelection.SceneryType == SCENERY_TYPE_LARGE) { auto sceneryEntry = ObjectManager::GetObjectEntry(scenerySelection.EntryIndex); + if (sceneryEntry == nullptr) + return; + auto imageId = ImageId(sceneryEntry->image + gWindowSceneryRotation); if (sceneryEntry->flags & LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR) imageId = imageId.WithPrimary(_sceneryPrimaryColour); @@ -1592,6 +1617,9 @@ namespace OpenRCT2::Ui::Windows else if (scenerySelection.SceneryType == SCENERY_TYPE_WALL) { auto wallEntry = ObjectManager::GetObjectEntry(scenerySelection.EntryIndex); + if (wallEntry == nullptr) + return; + auto imageId = ImageId(wallEntry->image); auto spriteTop = (wallEntry->height * 2) + 0x32; if (wallEntry->flags & WALL_SCENERY_HAS_GLASS) @@ -1628,12 +1656,18 @@ namespace OpenRCT2::Ui::Windows else if (scenerySelection.SceneryType == SCENERY_TYPE_PATH_ITEM) { auto* pathAdditionEntry = ObjectManager::GetObjectEntry(scenerySelection.EntryIndex); + if (pathAdditionEntry == nullptr) + return; + auto imageId = ImageId(pathAdditionEntry->image); GfxDrawSprite(rt, imageId, { 11, 16 }); } else { auto sceneryEntry = ObjectManager::GetObjectEntry(scenerySelection.EntryIndex); + if (sceneryEntry == nullptr) + return; + auto imageId = ImageId(sceneryEntry->image + gWindowSceneryRotation); if (sceneryEntry->HasFlag(SMALL_SCENERY_FLAG_HAS_PRIMARY_COLOUR)) {