Merge pull request #13994 from ZehMatt/refactor/tileelementview-3

Make tile element insertion type explicit
This commit is contained in:
Michael Steenbeek 2021-02-05 13:46:58 +01:00 committed by GitHub
commit c0ab9e8a3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 132 additions and 184 deletions

View File

@ -481,13 +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);
if (tileElement == nullptr)
surfaceElement = TileElementInsert<SurfaceElement>(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.

View File

@ -140,26 +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);
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);
newTileElement->SetType(TILE_ELEMENT_TYPE_BANNER);
BannerElement* bannerElement = newTileElement->AsBanner();
auto* bannerElement = TileElementInsert<BannerElement>({ _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() });

View File

@ -340,34 +340,25 @@ GameActions::Result::Ptr FootpathPlaceAction::ElementInsertExecute(GameActions::
}
else
{
auto tileElement = tile_element_insert(_loc, 0b1111);
assert(tileElement != nullptr);
tileElement->SetType(TILE_ELEMENT_TYPE_PATH);
PathElement* pathElement = tileElement->AsPath();
auto* pathElement = TileElementInsert<PathElement>(_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<TileElement>());
}
if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !(GetFlags() & GAME_COMMAND_FLAG_GHOST))
{

View File

@ -230,31 +230,22 @@ GameActions::Result::Ptr FootpathPlaceFromTrackAction::ElementInsertExecute(Game
}
else
{
auto tileElement = tile_element_insert(_loc, 0b1111);
assert(tileElement != nullptr);
tileElement->SetType(TILE_ELEMENT_TYPE_PATH);
PathElement* pathElement = tileElement->AsPath();
auto* pathElement = TileElementInsert<PathElement>(_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);
}

View File

@ -277,19 +277,17 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const
}
}
TileElement* newTileElement = tile_element_insert(
auto* newSceneryElement = TileElementInsert<LargeSceneryElement>(
CoordsXYZ{ curTile.x, curTile.y, zLow }, quarterTile.GetBaseQuarterOccupied());
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();
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<TileElement>();
}
map_invalidate_tile_full(curTile);
}

View File

@ -168,25 +168,19 @@ GameActions::Result::Ptr MazePlaceTrackAction::Execute() const
auto startLoc = _loc.ToTileStart();
auto tileElement = tile_element_insert(_loc, 0b1111);
assert(tileElement != nullptr);
auto* trackElement = TileElementInsert<TrackElement>(_loc, 0b1111);
Guard::Assert(trackElement != nullptr);
tileElement->SetClearanceZ(clearanceHeight);
tileElement->SetType(TILE_ELEMENT_TYPE_TRACK);
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)

View File

@ -181,20 +181,16 @@ GameActions::Result::Ptr MazeSetTrackAction::Execute() const
auto startLoc = _loc.ToTileStart();
tileElement = tile_element_insert(_loc, 0b1111);
assert(tileElement != nullptr);
auto* trackElement = TileElementInsert<TrackElement>(_loc, 0b1111);
Guard::Assert(trackElement != nullptr);
tileElement->SetClearanceZ(_loc.z + MAZE_CLEARANCE_HEIGHT);
tileElement->SetType(TILE_ELEMENT_TYPE_TRACK);
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<TileElement>();
map_invalidate_tile_full(startLoc);

View File

@ -138,30 +138,19 @@ GameActions::Result::Ptr PlaceParkEntranceAction::Execute() const
}
}
TileElement* newElement = tile_element_insert(CoordsXYZ{ entranceLoc, zLow }, 0b1111);
Guard::Assert(newElement != nullptr);
newElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE);
auto entranceElement = newElement->AsEntrance();
if (entranceElement == nullptr)
{
Guard::Assert(false);
return nullptr;
}
auto* entranceElement = TileElementInsert<EntranceElement>(CoordsXYZ{ entranceLoc, zLow }, 0b1111);
Guard::Assert(entranceElement != 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<TileElement>(), 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)
{

View File

@ -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);
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);
tileElement->AsEntrance()->SetStationIndex(_stationNum);
tileElement->AsEntrance()->SetRideIndex(_rideIndex);
auto* entranceElement = TileElementInsert<EntranceElement>(CoordsXYZ{ _loc, z }, 0b1111);
Guard::Assert(entranceElement != nullptr);
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<TileElement>() });
}
footpath_connect_edges(_loc, tileElement, GetFlags());
footpath_connect_edges(_loc, entranceElement->as<TileElement>(), GetFlags());
footpath_update_queue_chains();
map_invalidate_tile_full(_loc);

View File

@ -430,28 +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());
assert(newElement != nullptr);
res->tileElement = newElement;
newElement->SetType(TILE_ELEMENT_TYPE_SMALL_SCENERY);
newElement->SetDirection(_loc.direction);
SmallSceneryElement* sceneryElement = newElement->AsSmallScenery();
auto* sceneryElement = TileElementInsert<SmallSceneryElement>(
CoordsXYZ{ _loc, zLow }, quarterTile.GetBaseQuarterOccupied());
Guard::Assert(sceneryElement != nullptr);
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<TileElement>();
map_invalidate_tile_full(_loc);
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_ANIMATED))

View File

@ -592,58 +592,51 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
ride->overall_view = mapLoc;
}
auto tileElement = tile_element_insert(mapLoc, quarterTile.GetBaseQuarterOccupied());
assert(tileElement != nullptr);
tileElement->SetClearanceZ(clearanceZ);
tileElement->SetType(TILE_ELEMENT_TYPE_TRACK);
tileElement->SetDirection(_origin.direction);
if (_trackPlaceFlags & CONSTRUCTION_LIFT_HILL_SELECTED)
{
tileElement->AsTrack()->SetHasChain(true);
}
auto* trackElement = TileElementInsert<TrackElement>(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))
{
@ -689,13 +682,15 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const
ride->UpdateMaxVehicles();
}
auto* tileElement = trackElement->as<TileElement>();
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<TileElement*>(waterSurfaceElement);
tileElement = waterSurfaceElement->as<TileElement>();
}
}

View File

@ -397,24 +397,16 @@ GameActions::Result::Ptr WallPlaceAction::Execute() const
}
}
TileElement* tileElement = tile_element_insert(targetLoc, 0b0000);
assert(tileElement != nullptr);
auto* wallElement = TileElementInsert<WallElement>(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<TileElement>();
map_animation_create(MAP_ANIMATION_TYPE_WALL, targetLoc);
map_invalidate_tile_zoom1({ _loc, wallElement->GetBaseZ(), wallElement->GetBaseZ() + 72 });
res->Cost = wallEntry->wall.price;

View File

@ -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::Surface);
}
// Copy data to element span
@ -1706,7 +1706,7 @@ namespace OpenRCT2::Scripting
std::vector<TileElement> 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::Surface);
if (newElement == nullptr)
{
auto ctx = GetDukContext();

View File

@ -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;
@ -1154,6 +1154,7 @@ TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants
// Insert new map element
insertedElement = newTileElement;
newTileElement->type = 0;
newTileElement->SetType(static_cast<uint8_t>(type));
newTileElement->SetBaseZ(loc.z);
newTileElement->Flags = 0;
newTileElement->SetLastForTile(isLastForTile);

View File

@ -213,7 +213,13 @@ 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);
template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants)
{
auto* element = tile_element_insert(loc, occupiedQuadrants, T::ElementType);
return element->template as<T>();
}
namespace GameActions
{

View File

@ -240,12 +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);
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();
auto* sceneryElement = TileElementInsert<SmallSceneryElement>({ 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);

View File

@ -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<typename TType> const TType* as() const
{
return static_cast<TileElementType>(GetType()) == TType::ElementType ? reinterpret_cast<const TType*>(this) : nullptr;
if constexpr (std::is_same_v<TType, TileElement>)
return reinterpret_cast<const TileElement*>(this);
else
return static_cast<TileElementType>(GetType()) == TType::ElementType ? reinterpret_cast<const TType*>(this)
: nullptr;
}
template<typename TType> TType* as()
{
return static_cast<TileElementType>(GetType()) == TType::ElementType ? reinterpret_cast<TType*>(this) : nullptr;
if constexpr (std::is_same_v<TType, TileElement>)
return reinterpret_cast<TileElement*>(this);
else
return static_cast<TileElementType>(GetType()) == TType::ElementType ? reinterpret_cast<TType*>(this) : nullptr;
}
const SurfaceElement* AsSurface() const

View File

@ -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::Result>(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::Surface);
bool lastForTile = pastedElement->IsLastForTile();
*pastedElement = element;