diff --git a/distribution/changelog.txt b/distribution/changelog.txt index f379860ddd..59f030d3a4 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -3,6 +3,7 @@ - Feature: [#16662] Show a warning message when g2.dat is mismatched. - Change: [#17319] Giant screenshots are now cropped to the horizontal view-clipping selection. - Change: [#17499] Update error text when using vehicle incompatible with TD6 and add error when using incompatible track elements. +- Fix: [#16476] The game sometimes crashes when demolishing a maze. - Fix: [#17444] “Manta Ray” boats slowed down too much in “Ayers Rock” scenario (original bug). 0.4.1 (2022-07-04) diff --git a/src/openrct2/actions/RideDemolishAction.cpp b/src/openrct2/actions/RideDemolishAction.cpp index c64170a64b..c332cbe3d3 100644 --- a/src/openrct2/actions/RideDemolishAction.cpp +++ b/src/openrct2/actions/RideDemolishAction.cpp @@ -200,37 +200,44 @@ money32 RideDemolishAction::DemolishTracks() const for (tilePos.y = 0; tilePos.y < gMapSize.y; ++tilePos.y) { const auto tileCoords = tilePos.ToCoordsXY(); - // Keep retrying a tile coordinate until there are no more items to remove - bool itemRemoved = false; - do + // Loop over all elements of the tile until there are no more items to remove + int offset = -1; + bool lastForTileReached = false; + while (!lastForTileReached) { - itemRemoved = false; - for (auto* trackElement : TileElementsView(tileCoords)) + offset++; + auto* tileElement = map_get_first_element_at(tileCoords) + offset; + if (tileElement == nullptr) + break; + + lastForTileReached = tileElement->IsLastForTile(); + if (tileElement->GetType() != TileElementType::Track) + continue; + + auto* trackElement = tileElement->AsTrack(); + if (trackElement->GetRideIndex() != _rideIndex) + continue; + + const auto location = CoordsXYZD(tileCoords, trackElement->GetBaseZ(), trackElement->GetDirection()); + const auto type = trackElement->GetTrackType(); + + if (type != TrackElemType::Maze) { - if (trackElement->GetRideIndex() != _rideIndex) - continue; + auto trackRemoveAction = TrackRemoveAction(type, trackElement->GetSequenceIndex(), location); + trackRemoveAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND); - const auto location = CoordsXYZD(tileCoords, trackElement->GetBaseZ(), trackElement->GetDirection()); - const auto type = trackElement->GetTrackType(); - - if (type != TrackElemType::Maze) + auto removRes = GameActions::ExecuteNested(&trackRemoveAction); + if (removRes.Error != GameActions::Status::Ok) { - auto trackRemoveAction = TrackRemoveAction(type, trackElement->GetSequenceIndex(), location); - trackRemoveAction.SetFlags(GAME_COMMAND_FLAG_NO_SPEND); - - auto removRes = GameActions::ExecuteNested(&trackRemoveAction); - itemRemoved = true; - if (removRes.Error != GameActions::Status::Ok) - { - tile_element_remove(trackElement->as()); - } - else - { - refundPrice += removRes.Cost; - } - continue; + tile_element_remove(tileElement); } - + else + { + refundPrice += removRes.Cost; + } + } + else + { static constexpr const CoordsXY DirOffsets[] = { { 0, 0 }, { 0, 16 }, @@ -244,13 +251,13 @@ money32 RideDemolishAction::DemolishTracks() const if (removePrice != MONEY32_UNDEFINED) { refundPrice += removePrice; - itemRemoved = true; } - else - break; } } - } while (itemRemoved); + + // Now we have removed an element, decrement the offset, or we may skip consecutive track elements + offset--; + } } }