From 71174b8de7696ce1139dd28d3ffd141c4a3180c0 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 4 Feb 2021 17:46:21 +0200 Subject: [PATCH 1/3] Make the insertion of tile elements type explicit --- src/openrct2/Game.cpp | 3 ++- src/openrct2/actions/BannerPlaceAction.cpp | 3 +-- src/openrct2/actions/FootpathPlaceAction.cpp | 3 +-- src/openrct2/actions/FootpathPlaceFromTrackAction.cpp | 3 +-- src/openrct2/actions/LargeSceneryPlaceAction.cpp | 3 +-- src/openrct2/actions/MazePlaceTrackAction.cpp | 3 +-- src/openrct2/actions/MazeSetTrackAction.cpp | 5 ++--- src/openrct2/actions/PlaceParkEntranceAction.cpp | 4 ++-- src/openrct2/actions/RideEntranceExitPlaceAction.cpp | 4 ++-- src/openrct2/actions/SmallSceneryPlaceAction.cpp | 5 +++-- src/openrct2/actions/TrackPlaceAction.cpp | 3 +-- src/openrct2/actions/WallPlaceAction.cpp | 2 +- src/openrct2/scripting/ScTile.hpp | 8 ++++---- src/openrct2/world/Map.cpp | 6 +++--- src/openrct2/world/Map.h | 4 ++-- src/openrct2/world/MapGen.cpp | 3 +-- src/openrct2/world/TileInspector.cpp | 6 +++--- 17 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 4718adad9c..2892551ae5 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -481,7 +481,8 @@ void game_fix_save_vars() if (surfaceElement == nullptr) { log_error("Null map element at x = %d and y = %d. Fixing...", x, y); - auto tileElement = tile_element_insert(TileCoordsXYZ{ x, y, 14 }.ToCoordsXYZ(), 0b0000); + auto tileElement = tile_element_insert( + TileCoordsXYZ{ x, y, 14 }.ToCoordsXYZ(), 0b0000, TileElementType::Surface); if (tileElement == nullptr) { log_error("Unable to fix: Map element limit reached."); diff --git a/src/openrct2/actions/BannerPlaceAction.cpp b/src/openrct2/actions/BannerPlaceAction.cpp index ffb68b5bd9..7dd6cc6d1f 100644 --- a/src/openrct2/actions/BannerPlaceAction.cpp +++ b/src/openrct2/actions/BannerPlaceAction.cpp @@ -141,7 +141,7 @@ GameActions::Result::Ptr BannerPlaceAction::Execute() const return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE); } - TileElement* newTileElement = tile_element_insert({ _loc, _loc.z + (2 * COORDS_Z_STEP) }, 0b0000); + TileElement* newTileElement = tile_element_insert({ _loc, _loc.z + (2 * COORDS_Z_STEP) }, 0b0000, TileElementType::Banner); assert(newTileElement != nullptr); banner->flags = 0; @@ -150,7 +150,6 @@ GameActions::Result::Ptr BannerPlaceAction::Execute() const banner->type = _bannerType; // Banner must be deleted after this point in an early return banner->colour = _primaryColour; banner->position = TileCoordsXY(_loc); - newTileElement->SetType(TILE_ELEMENT_TYPE_BANNER); BannerElement* bannerElement = newTileElement->AsBanner(); bannerElement->SetClearanceZ(_loc.z + PATH_CLEARANCE); bannerElement->SetPosition(_loc.direction); diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 5c9f465b34..465996f491 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -340,9 +340,8 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: } else { - auto tileElement = tile_element_insert(_loc, 0b1111); + auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Path); assert(tileElement != nullptr); - tileElement->SetType(TILE_ELEMENT_TYPE_PATH); PathElement* pathElement = tileElement->AsPath(); pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); diff --git a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp index aee4964bdb..ec1232fbb8 100644 --- a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp +++ b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp @@ -230,9 +230,8 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game } else { - auto tileElement = tile_element_insert(_loc, 0b1111); + auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Path); assert(tileElement != nullptr); - tileElement->SetType(TILE_ELEMENT_TYPE_PATH); PathElement* pathElement = tileElement->AsPath(); pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index 8172d3d825..c470bbcb11 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -278,10 +278,9 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const } TileElement* newTileElement = tile_element_insert( - CoordsXYZ{ curTile.x, curTile.y, zLow }, quarterTile.GetBaseQuarterOccupied()); + CoordsXYZ{ curTile.x, curTile.y, zLow }, quarterTile.GetBaseQuarterOccupied(), TileElementType::LargeScenery); Guard::Assert(newTileElement != nullptr); map_animation_create(MAP_ANIMATION_TYPE_LARGE_SCENERY, { curTile, zLow }); - newTileElement->SetType(TILE_ELEMENT_TYPE_LARGE_SCENERY); newTileElement->SetClearanceZ(zHigh); auto newSceneryElement = newTileElement->AsLargeScenery(); diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp index e0411563e6..1c6cc6579d 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.cpp +++ b/src/openrct2/actions/MazePlaceTrackAction.cpp @@ -168,11 +168,10 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const auto startLoc = _loc.ToTileStart(); - auto tileElement = tile_element_insert(_loc, 0b1111); + auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Track); assert(tileElement != nullptr); tileElement->SetClearanceZ(clearanceHeight); - tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); tileElement->AsTrack()->SetTrackType(TrackElemType::Maze); tileElement->AsTrack()->SetRideIndex(_rideIndex); diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp index 9fe32e09ca..6bcda0fda5 100644 --- a/src/openrct2/actions/MazeSetTrackAction.cpp +++ b/src/openrct2/actions/MazeSetTrackAction.cpp @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -181,11 +181,10 @@ GameActions::Result::Ptr MazeSetTrackAction::Execute() const auto startLoc = _loc.ToTileStart(); - tileElement = tile_element_insert(_loc, 0b1111); + tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Track); assert(tileElement != nullptr); tileElement->SetClearanceZ(_loc.z + MAZE_CLEARANCE_HEIGHT); - tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); tileElement->AsTrack()->SetTrackType(TrackElemType::Maze); tileElement->AsTrack()->SetRideIndex(_rideIndex); diff --git a/src/openrct2/actions/PlaceParkEntranceAction.cpp b/src/openrct2/actions/PlaceParkEntranceAction.cpp index 9472879212..2aca2392e4 100644 --- a/src/openrct2/actions/PlaceParkEntranceAction.cpp +++ b/src/openrct2/actions/PlaceParkEntranceAction.cpp @@ -138,9 +138,9 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Execute() const } } - TileElement* newElement = tile_element_insert(CoordsXYZ{ entranceLoc, zLow }, 0b1111); + TileElement* newElement = tile_element_insert(CoordsXYZ{ entranceLoc, zLow }, 0b1111, TileElementType::Entrance); Guard::Assert(newElement != nullptr); - newElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); + auto entranceElement = newElement->AsEntrance(); if (entranceElement == nullptr) { diff --git a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp index 8a85b86b05..88fc495299 100644 --- a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp +++ b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp @@ -176,9 +176,9 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Execute() const res->Position = { _loc.ToTileCentre(), z }; res->Expenditure = ExpenditureType::RideConstruction; - TileElement* tileElement = tile_element_insert(CoordsXYZ{ _loc, z }, 0b1111); + TileElement* tileElement = tile_element_insert(CoordsXYZ{ _loc, z }, 0b1111, TileElementType::Entrance); assert(tileElement != nullptr); - tileElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); + tileElement->SetDirection(_direction); tileElement->SetClearanceZ(clear_z); tileElement->AsEntrance()->SetEntranceType(_isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE); diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.cpp b/src/openrct2/actions/SmallSceneryPlaceAction.cpp index 9668cf5e88..c41f211c8b 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.cpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.cpp @@ -430,10 +430,11 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Execute() const res->Expenditure = ExpenditureType::Landscaping; res->Cost = (sceneryEntry->small_scenery.price * 10) + clearCost; - TileElement* newElement = tile_element_insert(CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied()); + TileElement* newElement = tile_element_insert( + CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied(), TileElementType::SmallScenery); assert(newElement != nullptr); res->tileElement = newElement; - newElement->SetType(TILE_ELEMENT_TYPE_SMALL_SCENERY); + newElement->SetDirection(_loc.direction); SmallSceneryElement* sceneryElement = newElement->AsSmallScenery(); sceneryElement->SetSceneryQuadrant(quadrant); diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 0bbc903265..3b490073d9 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -592,10 +592,9 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const ride->overall_view = mapLoc; } - auto tileElement = tile_element_insert(mapLoc, quarterTile.GetBaseQuarterOccupied()); + auto tileElement = tile_element_insert(mapLoc, quarterTile.GetBaseQuarterOccupied(), TileElementType::Track); assert(tileElement != nullptr); tileElement->SetClearanceZ(clearanceZ); - tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); tileElement->SetDirection(_origin.direction); if (_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED) { diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index 0d87c4c4f6..1baee9df41 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -397,7 +397,7 @@ GameActions::Result::Ptr WallPlaceAction::Execute() const } } - TileElement* tileElement = tile_element_insert(targetLoc, 0b0000); + TileElement* tileElement = tile_element_insert(targetLoc, 0b0000, TileElementType::Wall); assert(tileElement != nullptr); map_animation_create(MAP_ANIMATION_TYPE_WALL, targetLoc); diff --git a/src/openrct2/scripting/ScTile.hpp b/src/openrct2/scripting/ScTile.hpp index 7840664191..c811799595 100644 --- a/src/openrct2/scripting/ScTile.hpp +++ b/src/openrct2/scripting/ScTile.hpp @@ -835,13 +835,13 @@ namespace OpenRCT2::Scripting // Insert corrupt element at the end of the list for this tile // Note: Z = MAX_ELEMENT_HEIGHT to guarantee this - TileElement* insertedElement = tile_element_insert({ _coords, MAX_ELEMENT_HEIGHT }, 0); + TileElement* insertedElement = tile_element_insert( + { _coords, MAX_ELEMENT_HEIGHT }, 0, TileElementType::Corrupt); if (insertedElement == nullptr) { // TODO: Show error return; } - insertedElement->SetType(TILE_ELEMENT_TYPE_CORRUPT); // Since inserting a new element may move the tile elements in memory, we have to update the local pointer _element = map_get_first_element_at(_coords) + elementIndex; @@ -1661,7 +1661,7 @@ namespace OpenRCT2::Scripting auto numToInsert = numElements - currentNumElements; for (size_t i = 0; i < numToInsert; i++) { - tile_element_insert(pos, 0); + tile_element_insert(pos, 0, TileElementType::Corrupt); } // Copy data to element span @@ -1706,7 +1706,7 @@ namespace OpenRCT2::Scripting std::vector data(first, first + origNumElements); auto pos = TileCoordsXYZ(TileCoordsXY(_coords), 0).ToCoordsXYZ(); - auto newElement = tile_element_insert(pos, 0); + auto newElement = tile_element_insert(pos, 0, TileElementType::Corrupt); if (newElement == nullptr) { auto ctx = GetDukContext(); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 8c6e99f95a..775dea76e1 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -1108,7 +1108,7 @@ bool map_check_free_elements_and_reorganise(int32_t numElements) * * rct2: 0x0068B1F6 */ -TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants) +TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type) { const auto& tileLoc = TileCoordsXYZ(loc); TileElement *originalTileElement, *newTileElement, *insertedElement; @@ -1153,7 +1153,7 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants // Insert new map element insertedElement = newTileElement; - newTileElement->type = 0; + newTileElement->SetType(static_cast(type)); newTileElement->SetBaseZ(loc.z); newTileElement->Flags = 0; newTileElement->SetLastForTile(isLastForTile); diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 038fceb1c8..0904114776 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -213,7 +213,7 @@ void map_invalidate_map_selection_tiles(); void map_invalidate_selection_rect(); void map_reorganise_elements(); bool map_check_free_elements_and_reorganise(int32_t num_elements); -TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants); +TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type); namespace GameActions { diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 24439c282c..8d0b1b60e2 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -240,10 +240,9 @@ static void mapgen_place_tree(int32_t type, const CoordsXY& loc) } int32_t surfaceZ = tile_element_height(loc.ToTileCentre()); - TileElement* tileElement = tile_element_insert({ loc, surfaceZ }, 0b1111); + TileElement* tileElement = tile_element_insert({ loc, surfaceZ }, 0b1111, TileElementType::SmallScenery); assert(tileElement != nullptr); tileElement->SetClearanceZ(surfaceZ + sceneryEntry->small_scenery.height); - tileElement->SetType(TILE_ELEMENT_TYPE_SMALL_SCENERY); tileElement->SetDirection(util_rand() & 3); SmallSceneryElement* sceneryElement = tileElement->AsSmallScenery(); sceneryElement->SetEntryIndex(type); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 21c00286ec..6f52d57dc6 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -88,13 +88,13 @@ GameActionResultPtr tile_inspector_insert_corrupt_at(const CoordsXY& loc, int16_ { // Create new corrupt element TileElement* corruptElement = tile_element_insert( - { loc, (-1 * COORDS_Z_STEP) }, 0b0000); // Ugly hack: -1 guarantees this to be placed first + { loc, (-1 * COORDS_Z_STEP) }, 0b0000, + TileElementType::Corrupt); // Ugly hack: -1 guarantees this to be placed first if (corruptElement == nullptr) { log_warning("Failed to insert corrupt element."); return std::make_unique(GameActions::Status::Unknown, STR_NONE); } - corruptElement->SetType(TILE_ELEMENT_TYPE_CORRUPT); // Set the base height to be the same as the selected element TileElement* const selectedElement = map_get_nth_element_at(loc, elementIndex + 1); @@ -382,7 +382,7 @@ GameActionResultPtr tile_inspector_paste_element_at(const CoordsXY& loc, TileEle // The occupiedQuadrants will be automatically set when the element is copied over, so it's not necessary to set them // correctly _here_. - TileElement* const pastedElement = tile_element_insert({ loc, element.GetBaseZ() }, 0b0000); + TileElement* const pastedElement = tile_element_insert({ loc, element.GetBaseZ() }, 0b0000, TileElementType::Corrupt); bool lastForTile = pastedElement->IsLastForTile(); *pastedElement = element; From 41c6c0bee390e12b5a399fbfc2b8b0548e05ee19 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 4 Feb 2021 17:59:06 +0200 Subject: [PATCH 2/3] Support casting back to TileElement --- src/openrct2/world/TileElement.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 905674ac42..d9d6c7186a 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -56,6 +56,7 @@ enum class TileElementType : uint8_t Corrupt = (8 << 2), }; +struct TileElement; struct SurfaceElement; struct PathElement; struct TrackElement; @@ -102,11 +103,19 @@ struct TileElementBase template const TType* as() const { - return static_cast(GetType()) == TType::ElementType ? reinterpret_cast(this) : nullptr; + if constexpr (std::is_same_v) + return reinterpret_cast(this); + else + return static_cast(GetType()) == TType::ElementType ? reinterpret_cast(this) + : nullptr; } + template TType* as() { - return static_cast(GetType()) == TType::ElementType ? reinterpret_cast(this) : nullptr; + if constexpr (std::is_same_v) + return reinterpret_cast(this); + else + return static_cast(GetType()) == TType::ElementType ? reinterpret_cast(this) : nullptr; } const SurfaceElement* AsSurface() const From 1aa75f04b7bced8e52de7121d1c3d9e6eb5181b7 Mon Sep 17 00:00:00 2001 From: Matt Date: Thu, 4 Feb 2021 18:21:17 +0200 Subject: [PATCH 3/3] Add templated version for tile element insertion and cleanup code --- src/openrct2/Game.cpp | 6 +-- src/openrct2/actions/BannerPlaceAction.cpp | 15 +++--- src/openrct2/actions/FootpathPlaceAction.cpp | 24 ++++------ .../actions/FootpathPlaceFromTrackAction.cpp | 22 +++------ .../actions/LargeSceneryPlaceAction.cpp | 13 +++-- src/openrct2/actions/MazePlaceTrackAction.cpp | 21 ++++---- src/openrct2/actions/MazeSetTrackAction.cpp | 21 ++++---- .../actions/PlaceParkEntranceAction.cpp | 23 +++------ .../actions/RideEntranceExitPlaceAction.cpp | 28 +++++------ .../actions/SmallSceneryPlaceAction.cpp | 17 +++---- src/openrct2/actions/TrackPlaceAction.cpp | 48 +++++++++---------- src/openrct2/actions/WallPlaceAction.cpp | 23 +++------ src/openrct2/scripting/ScTile.hpp | 4 +- src/openrct2/world/Map.cpp | 3 +- src/openrct2/world/Map.h | 8 +++- src/openrct2/world/MapGen.cpp | 11 +++-- src/openrct2/world/TileInspector.cpp | 2 +- 17 files changed, 117 insertions(+), 172 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 2892551ae5..f1e15ab889 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -481,14 +481,12 @@ void game_fix_save_vars() if (surfaceElement == nullptr) { log_error("Null map element at x = %d and y = %d. Fixing...", x, y); - auto tileElement = tile_element_insert( - TileCoordsXYZ{ x, y, 14 }.ToCoordsXYZ(), 0b0000, TileElementType::Surface); - if (tileElement == nullptr) + surfaceElement = TileElementInsert(TileCoordsXYZ{ x, y, 14 }.ToCoordsXYZ(), 0b0000); + if (surfaceElement == nullptr) { log_error("Unable to fix: Map element limit reached."); return; } - surfaceElement = tileElement->AsSurface(); } // Fix the invisible border tiles. diff --git a/src/openrct2/actions/BannerPlaceAction.cpp b/src/openrct2/actions/BannerPlaceAction.cpp index 7dd6cc6d1f..ec506bc35d 100644 --- a/src/openrct2/actions/BannerPlaceAction.cpp +++ b/src/openrct2/actions/BannerPlaceAction.cpp @@ -140,25 +140,22 @@ GameActions::Result::Ptr BannerPlaceAction::Execute() const log_error("Banner index in use, bannerIndex = %u", _bannerIndex); return MakeResult(GameActions::Status::InvalidParameters, STR_CANT_POSITION_THIS_HERE); } - - TileElement* newTileElement = tile_element_insert({ _loc, _loc.z + (2 * COORDS_Z_STEP) }, 0b0000, TileElementType::Banner); - assert(newTileElement != nullptr); - banner->flags = 0; banner->text = {}; banner->text_colour = 2; banner->type = _bannerType; // Banner must be deleted after this point in an early return banner->colour = _primaryColour; banner->position = TileCoordsXY(_loc); - BannerElement* bannerElement = newTileElement->AsBanner(); + + auto* bannerElement = TileElementInsert({ _loc, _loc.z + (2 * COORDS_Z_STEP) }, 0b0000); + Guard::Assert(bannerElement != nullptr); + bannerElement->SetClearanceZ(_loc.z + PATH_CLEARANCE); bannerElement->SetPosition(_loc.direction); bannerElement->ResetAllowedEdges(); bannerElement->SetIndex(_bannerIndex); - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - bannerElement->SetGhost(true); - } + bannerElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); + map_invalidate_tile_full(_loc); map_animation_create(MAP_ANIMATION_TYPE_BANNER, CoordsXYZ{ _loc, bannerElement->GetBaseZ() }); diff --git a/src/openrct2/actions/FootpathPlaceAction.cpp b/src/openrct2/actions/FootpathPlaceAction.cpp index 465996f491..33c00b3dfa 100644 --- a/src/openrct2/actions/FootpathPlaceAction.cpp +++ b/src/openrct2/actions/FootpathPlaceAction.cpp @@ -340,33 +340,25 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions:: } else { - auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Path); - assert(tileElement != nullptr); - PathElement* pathElement = tileElement->AsPath(); + auto* pathElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(pathElement != nullptr); + pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - pathElement->SetSloped(true); - } - if (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) - { - pathElement->SetIsQueue(true); - } + pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); + pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetAddition(0); pathElement->SetRideIndex(RIDE_ID_NULL); pathElement->SetAdditionStatus(255); pathElement->SetIsBroken(false); - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - pathElement->SetGhost(true); - } + pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); + footpath_queue_chain_reset(); if (!(GetFlags() & GAME_COMMAND_FLAG_PATH_SCENERY)) { - footpath_remove_edges_at(_loc, tileElement); + footpath_remove_edges_at(_loc, pathElement->as()); } if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(GetFlags() & GAME_COMMAND_FLAG_GHOST)) { diff --git a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp index ec1232fbb8..ea9407091c 100644 --- a/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp +++ b/src/openrct2/actions/FootpathPlaceFromTrackAction.cpp @@ -230,30 +230,22 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game } else { - auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Path); - assert(tileElement != nullptr); - PathElement* pathElement = tileElement->AsPath(); + auto* pathElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(pathElement != nullptr); + pathElement->SetClearanceZ(zHigh); pathElement->SetSurfaceEntryIndex(_type & ~FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetSlopeDirection(_slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK); - if (_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED) - { - pathElement->SetSloped(true); - } - if (_type & FOOTPATH_ELEMENT_INSERT_QUEUE) - { - pathElement->SetIsQueue(true); - } + pathElement->SetSloped(_slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED); + pathElement->SetIsQueue(_type & FOOTPATH_ELEMENT_INSERT_QUEUE); pathElement->SetAddition(0); pathElement->SetRideIndex(RIDE_ID_NULL); pathElement->SetAdditionStatus(255); pathElement->SetIsBroken(false); pathElement->SetEdges(_edges); pathElement->SetCorners(0); - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - pathElement->SetGhost(true); - } + pathElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); + map_invalidate_tile_full(_loc); } diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index c470bbcb11..ea9c3b86f6 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -277,18 +277,17 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const } } - TileElement* newTileElement = tile_element_insert( - CoordsXYZ{ curTile.x, curTile.y, zLow }, quarterTile.GetBaseQuarterOccupied(), TileElementType::LargeScenery); - Guard::Assert(newTileElement != nullptr); - map_animation_create(MAP_ANIMATION_TYPE_LARGE_SCENERY, { curTile, zLow }); - newTileElement->SetClearanceZ(zHigh); - auto newSceneryElement = newTileElement->AsLargeScenery(); + auto* newSceneryElement = TileElementInsert( + CoordsXYZ{ curTile.x, curTile.y, zLow }, quarterTile.GetBaseQuarterOccupied()); + Guard::Assert(newSceneryElement != nullptr); + newSceneryElement->SetClearanceZ(zHigh); SetNewLargeSceneryElement(*newSceneryElement, tileNum); + map_animation_create(MAP_ANIMATION_TYPE_LARGE_SCENERY, { curTile, zLow }); if (tileNum == 0) { - res->tileElement = newTileElement; + res->tileElement = newSceneryElement->as(); } map_invalidate_tile_full(curTile); } diff --git a/src/openrct2/actions/MazePlaceTrackAction.cpp b/src/openrct2/actions/MazePlaceTrackAction.cpp index 1c6cc6579d..fbb63a27c6 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.cpp +++ b/src/openrct2/actions/MazePlaceTrackAction.cpp @@ -168,24 +168,19 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const auto startLoc = _loc.ToTileStart(); - auto tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Track); - assert(tileElement != nullptr); + auto* trackElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(trackElement != nullptr); - tileElement->SetClearanceZ(clearanceHeight); - - tileElement->AsTrack()->SetTrackType(TrackElemType::Maze); - tileElement->AsTrack()->SetRideIndex(_rideIndex); - tileElement->AsTrack()->SetMazeEntry(_mazeEntry); - - if (flags & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } + trackElement->SetClearanceZ(clearanceHeight); + trackElement->SetTrackType(TrackElemType::Maze); + trackElement->SetRideIndex(_rideIndex); + trackElement->SetMazeEntry(_mazeEntry); + trackElement->SetGhost(flags & GAME_COMMAND_FLAG_GHOST); map_invalidate_tile_full(startLoc); ride->maze_tiles++; - ride->stations[0].SetBaseZ(tileElement->GetBaseZ()); + ride->stations[0].SetBaseZ(trackElement->GetBaseZ()); ride->stations[0].Start = { 0, 0 }; if (ride->maze_tiles == 1) diff --git a/src/openrct2/actions/MazeSetTrackAction.cpp b/src/openrct2/actions/MazeSetTrackAction.cpp index 6bcda0fda5..d71e53a26b 100644 --- a/src/openrct2/actions/MazeSetTrackAction.cpp +++ b/src/openrct2/actions/MazeSetTrackAction.cpp @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -181,19 +181,16 @@ GameActions::Result::Ptr MazeSetTrackAction::Execute() const auto startLoc = _loc.ToTileStart(); - tileElement = tile_element_insert(_loc, 0b1111, TileElementType::Track); - assert(tileElement != nullptr); + auto* trackElement = TileElementInsert(_loc, 0b1111); + Guard::Assert(trackElement != nullptr); - tileElement->SetClearanceZ(_loc.z + MAZE_CLEARANCE_HEIGHT); + trackElement->SetClearanceZ(_loc.z + MAZE_CLEARANCE_HEIGHT); + trackElement->SetTrackType(TrackElemType::Maze); + trackElement->SetRideIndex(_rideIndex); + trackElement->SetMazeEntry(0xFFFF); + trackElement->SetGhost(flags & GAME_COMMAND_FLAG_GHOST); - tileElement->AsTrack()->SetTrackType(TrackElemType::Maze); - tileElement->AsTrack()->SetRideIndex(_rideIndex); - tileElement->AsTrack()->SetMazeEntry(0xFFFF); - - if (flags & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } + tileElement = trackElement->as(); map_invalidate_tile_full(startLoc); diff --git a/src/openrct2/actions/PlaceParkEntranceAction.cpp b/src/openrct2/actions/PlaceParkEntranceAction.cpp index 2aca2392e4..661a69e1b9 100644 --- a/src/openrct2/actions/PlaceParkEntranceAction.cpp +++ b/src/openrct2/actions/PlaceParkEntranceAction.cpp @@ -138,30 +138,19 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Execute() const } } - TileElement* newElement = tile_element_insert(CoordsXYZ{ entranceLoc, zLow }, 0b1111, TileElementType::Entrance); - Guard::Assert(newElement != nullptr); + auto* entranceElement = TileElementInsert(CoordsXYZ{ entranceLoc, zLow }, 0b1111); + Guard::Assert(entranceElement != nullptr); - auto entranceElement = newElement->AsEntrance(); - if (entranceElement == nullptr) - { - Guard::Assert(false); - return nullptr; - } entranceElement->SetClearanceZ(zHigh); - - if (flags & GAME_COMMAND_FLAG_GHOST) - { - newElement->SetGhost(true); - } - + entranceElement->SetGhost(flags & GAME_COMMAND_FLAG_GHOST); entranceElement->SetDirection(_loc.direction); entranceElement->SetSequenceIndex(index); entranceElement->SetEntranceType(ENTRANCE_TYPE_PARK_ENTRANCE); entranceElement->SetPathType(gFootpathSelectedId); - if (!(flags & GAME_COMMAND_FLAG_GHOST)) + if (!entranceElement->IsGhost()) { - footpath_connect_edges(entranceLoc, newElement, GAME_COMMAND_FLAG_APPLY); + footpath_connect_edges(entranceLoc, entranceElement->as(), GAME_COMMAND_FLAG_APPLY); } update_park_fences(entranceLoc); @@ -170,7 +159,7 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Execute() const update_park_fences({ entranceLoc.x, entranceLoc.y - COORDS_XY_STEP }); update_park_fences({ entranceLoc.x, entranceLoc.y + COORDS_XY_STEP }); - map_invalidate_tile({ entranceLoc, newElement->GetBaseZ(), newElement->GetClearanceZ() }); + map_invalidate_tile({ entranceLoc, entranceElement->GetBaseZ(), entranceElement->GetClearanceZ() }); if (index == 0) { diff --git a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp index 88fc495299..bdea025199 100644 --- a/src/openrct2/actions/RideEntranceExitPlaceAction.cpp +++ b/src/openrct2/actions/RideEntranceExitPlaceAction.cpp @@ -176,27 +176,23 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Execute() const res->Position = { _loc.ToTileCentre(), z }; res->Expenditure = ExpenditureType::RideConstruction; - TileElement* tileElement = tile_element_insert(CoordsXYZ{ _loc, z }, 0b1111, TileElementType::Entrance); - assert(tileElement != nullptr); + auto* entranceElement = TileElementInsert(CoordsXYZ{ _loc, z }, 0b1111); + Guard::Assert(entranceElement != nullptr); - tileElement->SetDirection(_direction); - tileElement->SetClearanceZ(clear_z); - tileElement->AsEntrance()->SetEntranceType(_isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE); - tileElement->AsEntrance()->SetStationIndex(_stationNum); - tileElement->AsEntrance()->SetRideIndex(_rideIndex); - - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } + entranceElement->SetDirection(_direction); + entranceElement->SetClearanceZ(clear_z); + entranceElement->SetEntranceType(_isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE); + entranceElement->SetStationIndex(_stationNum); + entranceElement->SetRideIndex(_rideIndex); + entranceElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); if (_isExit) { - ride_set_exit_location(ride, _stationNum, TileCoordsXYZD(CoordsXYZD{ _loc, z, tileElement->GetDirection() })); + ride_set_exit_location(ride, _stationNum, TileCoordsXYZD(CoordsXYZD{ _loc, z, entranceElement->GetDirection() })); } else { - ride_set_entrance_location(ride, _stationNum, TileCoordsXYZD(CoordsXYZD{ _loc, z, tileElement->GetDirection() })); + ride_set_entrance_location(ride, _stationNum, TileCoordsXYZD(CoordsXYZD{ _loc, z, entranceElement->GetDirection() })); ride->stations[_stationNum].LastPeepInQueue = SPRITE_INDEX_NULL; ride->stations[_stationNum].QueueLength = 0; @@ -207,10 +203,10 @@ GameActions::Result::Ptr RideEntranceExitPlaceAction::Execute() const if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST)) { - maze_entrance_hedge_removal({ _loc, tileElement }); + maze_entrance_hedge_removal({ _loc, entranceElement->as() }); } - footpath_connect_edges(_loc, tileElement, GetFlags()); + footpath_connect_edges(_loc, entranceElement->as(), GetFlags()); footpath_update_queue_chains(); map_invalidate_tile_full(_loc); diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.cpp b/src/openrct2/actions/SmallSceneryPlaceAction.cpp index c41f211c8b..e8701443de 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.cpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.cpp @@ -430,29 +430,24 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Execute() const res->Expenditure = ExpenditureType::Landscaping; res->Cost = (sceneryEntry->small_scenery.price * 10) + clearCost; - TileElement* newElement = tile_element_insert( - CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied(), TileElementType::SmallScenery); - assert(newElement != nullptr); - res->tileElement = newElement; + auto* sceneryElement = TileElementInsert( + CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied()); + Guard::Assert(sceneryElement != nullptr); - newElement->SetDirection(_loc.direction); - SmallSceneryElement* sceneryElement = newElement->AsSmallScenery(); + sceneryElement->SetDirection(_loc.direction); sceneryElement->SetSceneryQuadrant(quadrant); sceneryElement->SetEntryIndex(_sceneryType); sceneryElement->SetAge(0); sceneryElement->SetPrimaryColour(_primaryColour); sceneryElement->SetSecondaryColour(_secondaryColour); sceneryElement->SetClearanceZ(sceneryElement->GetBaseZ() + sceneryEntry->small_scenery.height + 7); - + sceneryElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); if (supportsRequired) { sceneryElement->SetNeedsSupports(); } - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - sceneryElement->SetGhost(true); - } + res->tileElement = sceneryElement->as(); map_invalidate_tile_full(_loc); if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_ANIMATED)) diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index 3b490073d9..1a2edd27a9 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -592,57 +592,51 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const ride->overall_view = mapLoc; } - auto tileElement = tile_element_insert(mapLoc, quarterTile.GetBaseQuarterOccupied(), TileElementType::Track); - assert(tileElement != nullptr); - tileElement->SetClearanceZ(clearanceZ); - tileElement->SetDirection(_origin.direction); - if (_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED) - { - tileElement->AsTrack()->SetHasChain(true); - } + auto* trackElement = TileElementInsert(mapLoc, quarterTile.GetBaseQuarterOccupied()); + Guard::Assert(trackElement != nullptr); - tileElement->AsTrack()->SetSequenceIndex(trackBlock->index); - tileElement->AsTrack()->SetRideIndex(_rideIndex); - tileElement->AsTrack()->SetTrackType(_trackType); - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } + trackElement->SetClearanceZ(clearanceZ); + trackElement->SetDirection(_origin.direction); + trackElement->SetHasChain(_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED); + trackElement->SetSequenceIndex(trackBlock->index); + trackElement->SetRideIndex(_rideIndex); + trackElement->SetTrackType(_trackType); + trackElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); switch (_trackType) { case TrackElemType::Waterfall: - map_animation_create(MAP_ANIMATION_TYPE_TRACK_WATERFALL, CoordsXYZ{ mapLoc, tileElement->GetBaseZ() }); + map_animation_create(MAP_ANIMATION_TYPE_TRACK_WATERFALL, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() }); break; case TrackElemType::Rapids: - map_animation_create(MAP_ANIMATION_TYPE_TRACK_RAPIDS, CoordsXYZ{ mapLoc, tileElement->GetBaseZ() }); + map_animation_create(MAP_ANIMATION_TYPE_TRACK_RAPIDS, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() }); break; case TrackElemType::Whirlpool: - map_animation_create(MAP_ANIMATION_TYPE_TRACK_WHIRLPOOL, CoordsXYZ{ mapLoc, tileElement->GetBaseZ() }); + map_animation_create(MAP_ANIMATION_TYPE_TRACK_WHIRLPOOL, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() }); break; case TrackElemType::SpinningTunnel: - map_animation_create(MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL, CoordsXYZ{ mapLoc, tileElement->GetBaseZ() }); + map_animation_create(MAP_ANIMATION_TYPE_TRACK_SPINNINGTUNNEL, CoordsXYZ{ mapLoc, trackElement->GetBaseZ() }); break; } if (TrackTypeHasSpeedSetting(_trackType)) { - tileElement->AsTrack()->SetBrakeBoosterSpeed(_brakeSpeed); + trackElement->SetBrakeBoosterSpeed(_brakeSpeed); } else if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) { - tileElement->AsTrack()->SetDoorAState(LANDSCAPE_DOOR_CLOSED); - tileElement->AsTrack()->SetDoorBState(LANDSCAPE_DOOR_CLOSED); + trackElement->SetDoorAState(LANDSCAPE_DOOR_CLOSED); + trackElement->SetDoorBState(LANDSCAPE_DOOR_CLOSED); } else { - tileElement->AsTrack()->SetSeatRotation(_seatRotation); + trackElement->SetSeatRotation(_seatRotation); } if (_trackPlaceFlags & RIDE_TYPE_ALTERNATIVE_TRACK_TYPE) { - tileElement->AsTrack()->SetInverted(true); + trackElement->SetInverted(true); } - tileElement->AsTrack()->SetColourScheme(_colour); + trackElement->SetColourScheme(_colour); if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_FLAT_RIDE)) { @@ -688,13 +682,15 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const ride->UpdateMaxVehicles(); } + auto* tileElement = trackElement->as(); + if (rideTypeFlags & RIDE_TYPE_FLAG_TRACK_MUST_BE_ON_WATER) { auto* waterSurfaceElement = map_get_surface_element_at(mapLoc); if (waterSurfaceElement != nullptr) { waterSurfaceElement->SetHasTrackThatNeedsWater(true); - tileElement = reinterpret_cast(waterSurfaceElement); + tileElement = waterSurfaceElement->as(); } } diff --git a/src/openrct2/actions/WallPlaceAction.cpp b/src/openrct2/actions/WallPlaceAction.cpp index 1baee9df41..6002be50fa 100644 --- a/src/openrct2/actions/WallPlaceAction.cpp +++ b/src/openrct2/actions/WallPlaceAction.cpp @@ -397,24 +397,16 @@ GameActions::Result::Ptr WallPlaceAction::Execute() const } } - TileElement* tileElement = tile_element_insert(targetLoc, 0b0000, TileElementType::Wall); - assert(tileElement != nullptr); + auto* wallElement = TileElementInsert(targetLoc, 0b0000); + Guard::Assert(wallElement != nullptr); - map_animation_create(MAP_ANIMATION_TYPE_WALL, targetLoc); - - tileElement->SetType(TILE_ELEMENT_TYPE_WALL); - WallElement* wallElement = tileElement->AsWall(); wallElement->clearance_height = clearanceHeight; wallElement->SetDirection(_edge); wallElement->SetSlope(edgeSlope); wallElement->SetPrimaryColour(_primaryColour); wallElement->SetSecondaryColour(_secondaryColour); - - if (wallAcrossTrack) - { - wallElement->SetAcrossTrack(true); - } + wallElement->SetAcrossTrack(wallAcrossTrack); wallElement->SetEntryIndex(_wallType); if (_bannerId != BANNER_INDEX_NULL) @@ -427,12 +419,11 @@ GameActions::Result::Ptr WallPlaceAction::Execute() const wallElement->SetTertiaryColour(_tertiaryColour); } - if (GetFlags() & GAME_COMMAND_FLAG_GHOST) - { - wallElement->SetGhost(true); - } + wallElement->SetGhost(GetFlags() & GAME_COMMAND_FLAG_GHOST); - res->tileElement = tileElement; + res->tileElement = wallElement->as(); + + map_animation_create(MAP_ANIMATION_TYPE_WALL, targetLoc); map_invalidate_tile_zoom1({ _loc, wallElement->GetBaseZ(), wallElement->GetBaseZ() + 72 }); res->Cost = wallEntry->wall.price; diff --git a/src/openrct2/scripting/ScTile.hpp b/src/openrct2/scripting/ScTile.hpp index c811799595..de745a8269 100644 --- a/src/openrct2/scripting/ScTile.hpp +++ b/src/openrct2/scripting/ScTile.hpp @@ -1661,7 +1661,7 @@ namespace OpenRCT2::Scripting auto numToInsert = numElements - currentNumElements; for (size_t i = 0; i < numToInsert; i++) { - tile_element_insert(pos, 0, TileElementType::Corrupt); + tile_element_insert(pos, 0, TileElementType::Surface); } // Copy data to element span @@ -1706,7 +1706,7 @@ namespace OpenRCT2::Scripting std::vector data(first, first + origNumElements); auto pos = TileCoordsXYZ(TileCoordsXY(_coords), 0).ToCoordsXYZ(); - auto newElement = tile_element_insert(pos, 0, TileElementType::Corrupt); + auto newElement = tile_element_insert(pos, 0, TileElementType::Surface); if (newElement == nullptr) { auto ctx = GetDukContext(); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 775dea76e1..2d6de3c057 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -1153,6 +1153,7 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants // Insert new map element insertedElement = newTileElement; + newTileElement->type = 0; newTileElement->SetType(static_cast(type)); newTileElement->SetBaseZ(loc.z); newTileElement->Flags = 0; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 0904114776..f98fca3bcd 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -1,4 +1,4 @@ -/***************************************************************************** +/***************************************************************************** * Copyright (c) 2014-2020 OpenRCT2 developers * * For a complete list of all authors, please refer to contributors.md @@ -215,6 +215,12 @@ void map_reorganise_elements(); bool map_check_free_elements_and_reorganise(int32_t num_elements); TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type); +template T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants) +{ + auto* element = tile_element_insert(loc, occupiedQuadrants, T::ElementType); + return element->template as(); +} + namespace GameActions { class Result; diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 8d0b1b60e2..3f05c8340b 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -240,11 +240,12 @@ static void mapgen_place_tree(int32_t type, const CoordsXY& loc) } int32_t surfaceZ = tile_element_height(loc.ToTileCentre()); - TileElement* tileElement = tile_element_insert({ loc, surfaceZ }, 0b1111, TileElementType::SmallScenery); - assert(tileElement != nullptr); - tileElement->SetClearanceZ(surfaceZ + sceneryEntry->small_scenery.height); - tileElement->SetDirection(util_rand() & 3); - SmallSceneryElement* sceneryElement = tileElement->AsSmallScenery(); + + auto* sceneryElement = TileElementInsert({ loc, surfaceZ }, 0b1111); + Guard::Assert(sceneryElement != nullptr); + + sceneryElement->SetClearanceZ(surfaceZ + sceneryEntry->small_scenery.height); + sceneryElement->SetDirection(util_rand() & 3); sceneryElement->SetEntryIndex(type); sceneryElement->SetAge(0); sceneryElement->SetPrimaryColour(COLOUR_YELLOW); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 6f52d57dc6..717f142e3f 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -382,7 +382,7 @@ GameActionResultPtr tile_inspector_paste_element_at(const CoordsXY& loc, TileEle // The occupiedQuadrants will be automatically set when the element is copied over, so it's not necessary to set them // correctly _here_. - TileElement* const pastedElement = tile_element_insert({ loc, element.GetBaseZ() }, 0b0000, TileElementType::Corrupt); + TileElement* const pastedElement = tile_element_insert({ loc, element.GetBaseZ() }, 0b0000, TileElementType::Surface); bool lastForTile = pastedElement->IsLastForTile(); *pastedElement = element;