Merge pull request #13998 from ZehMatt/refactor/tileelementsview-4

Use TileElementsView and minor cleanups
This commit is contained in:
Michael Steenbeek 2021-02-08 22:18:27 +01:00 committed by GitHub
commit 27b7657d1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 325 additions and 457 deletions

View File

@ -13,8 +13,11 @@
#include "../world/Banner.h"
#include "../world/MapAnimation.h"
#include "../world/Scenery.h"
#include "../world/TileElementsView.h"
#include "GameAction.h"
using namespace OpenRCT2;
BannerPlaceAction::BannerPlaceAction(const CoordsXYZD& loc, uint8_t bannerType, BannerIndex bannerIndex, uint8_t primaryColour)
: _loc(loc)
, _bannerType(bannerType)
@ -165,17 +168,8 @@ GameActions::Result::Ptr BannerPlaceAction::Execute() const
PathElement* BannerPlaceAction::GetValidPathElement() const
{
TileElement* tileElement = map_get_first_element_at(_loc);
do
for (auto* pathElement : TileElementsView<PathElement>(_loc))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
continue;
auto pathElement = tileElement->AsPath();
if (pathElement->GetBaseZ() != _loc.z && pathElement->GetBaseZ() != _loc.z - PATH_HEIGHT_STEP)
continue;
@ -186,6 +180,7 @@ PathElement* BannerPlaceAction::GetValidPathElement() const
continue;
return pathElement;
} while (!(tileElement++)->IsLastForTile());
}
return nullptr;
}

View File

@ -13,8 +13,11 @@
#include "../world/Banner.h"
#include "../world/MapAnimation.h"
#include "../world/Scenery.h"
#include "../world/TileElementsView.h"
#include "GameAction.h"
using namespace OpenRCT2;
BannerRemoveAction::BannerRemoveAction(const CoordsXYZD& loc)
: _loc(loc)
{
@ -124,24 +127,18 @@ GameActions::Result::Ptr BannerRemoveAction::Execute() const
BannerElement* BannerRemoveAction::GetBannerElementAt() const
{
TileElement* tileElement = map_get_first_element_at(_loc);
// Find the banner element at known z and position
do
for (auto* bannerElement : TileElementsView<BannerElement>(_loc))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_BANNER)
if (bannerElement->GetBaseZ() != _loc.z)
continue;
if (tileElement->GetBaseZ() != _loc.z)
if (bannerElement->IsGhost() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST))
continue;
if (tileElement->IsGhost() && !(GetFlags() & GAME_COMMAND_FLAG_GHOST))
continue;
if (tileElement->AsBanner()->GetPosition() != _loc.direction)
if (bannerElement->GetPosition() != _loc.direction)
continue;
return tileElement->AsBanner();
} while (!(tileElement++)->IsLastForTile());
return bannerElement;
}
return nullptr;
}

View File

@ -20,8 +20,11 @@
#include "../world/Park.h"
#include "../world/Scenery.h"
#include "../world/Surface.h"
#include "../world/TileElementsView.h"
#include "../world/Wall.h"
using namespace OpenRCT2;
FootpathPlaceAction::FootpathPlaceAction(const CoordsXYZ& loc, uint8_t slope, ObjectEntryIndex type, Direction direction)
: _loc(loc)
, _slope(slope)
@ -435,20 +438,19 @@ void FootpathPlaceAction::RemoveIntersectingWalls(PathElement* pathElement) cons
PathElement* FootpathPlaceAction::map_get_footpath_element_slope(const CoordsXYZ& footpathPos, int32_t slope) const
{
TileElement* tileElement;
bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
const bool isSloped = slope & FOOTPATH_PROPERTIES_FLAG_IS_SLOPED;
const auto slopeDirection = slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK;
tileElement = map_get_first_element_at(footpathPos);
do
for (auto* pathElement : TileElementsView<PathElement>(footpathPos))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH && tileElement->GetBaseZ() == footpathPos.z
&& (tileElement->AsPath()->IsSloped() == isSloped)
&& (tileElement->AsPath()->GetSlopeDirection() == (slope & FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK)))
{
return tileElement->AsPath();
}
} while (!(tileElement++)->IsLastForTile());
if (pathElement->GetBaseZ() != footpathPos.z)
continue;
if (pathElement->IsSloped() != isSloped)
continue;
if (pathElement->GetSlopeDirection() != slopeDirection)
continue;
return pathElement;
}
return nullptr;
}

View File

@ -22,6 +22,9 @@
#include "../world/SmallScenery.h"
#include "../world/Sprite.h"
#include "../world/Surface.h"
#include "../world/TileElementsView.h"
using namespace OpenRCT2;
LandSetHeightAction::LandSetHeightAction(const CoordsXY& coords, uint8_t height, uint8_t style)
: _coords(coords)
@ -211,43 +214,40 @@ rct_string_id LandSetHeightAction::CheckParameters() const
TileElement* LandSetHeightAction::CheckTreeObstructions() const
{
TileElement* tileElement = map_get_first_element_at(_coords);
do
for (auto* sceneryElement : TileElementsView<SmallSceneryElement>(_coords))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
if (_height > sceneryElement->clearance_height)
continue;
if (_height > tileElement->clearance_height)
if (_height + 4 < sceneryElement->base_height)
continue;
if (_height + 4 < tileElement->base_height)
rct_scenery_entry* sceneryEntry = sceneryElement->GetEntry();
if (!scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE))
continue;
rct_scenery_entry* sceneryEntry = tileElement->AsSmallScenery()->GetEntry();
if (scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE))
{
return tileElement;
}
} while (!(tileElement++)->IsLastForTile());
return sceneryElement->as<TileElement>();
}
return nullptr;
}
money32 LandSetHeightAction::GetSmallSceneryRemovalCost() const
{
money32 cost{ 0 };
TileElement* tileElement = map_get_first_element_at(_coords);
do
for (auto* sceneryElement : TileElementsView<SmallSceneryElement>(_coords))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
if (_height > sceneryElement->clearance_height)
continue;
if (_height > tileElement->clearance_height)
if (_height + 4 < sceneryElement->base_height)
continue;
if (_height + 4 < tileElement->base_height)
rct_scenery_entry* sceneryEntry = sceneryElement->GetEntry();
if (sceneryEntry == nullptr)
continue;
rct_scenery_entry* sceneryEntry = tileElement->AsSmallScenery()->GetEntry();
cost += MONEY(sceneryEntry->small_scenery.removal_price, 0);
} while (!(tileElement++)->IsLastForTile());
}
return cost;
}
@ -270,34 +270,30 @@ void LandSetHeightAction::SmallSceneryRemoval() const
rct_string_id LandSetHeightAction::CheckRideSupports() const
{
TileElement* tileElement = map_get_first_element_at(_coords);
do
for (auto* trackElement : TileElementsView<TrackElement>(_coords))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK)
ride_id_t rideIndex = trackElement->GetRideIndex();
auto ride = get_ride(rideIndex);
if (ride == nullptr)
continue;
rct_ride_entry* rideEntry = ride->GetRideEntry();
if (rideEntry == nullptr)
continue;
int32_t maxHeight = rideEntry->max_height;
if (maxHeight == 0)
{
ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex();
auto ride = get_ride(rideIndex);
if (ride != nullptr)
{
rct_ride_entry* rideEntry = ride->GetRideEntry();
if (rideEntry != nullptr)
{
int32_t maxHeight = rideEntry->max_height;
if (maxHeight == 0)
{
maxHeight = ride->GetRideTypeDescriptor().Heights.MaxHeight;
}
int32_t zDelta = tileElement->clearance_height - _height;
if (zDelta >= 0 && zDelta / 2 > maxHeight)
{
return STR_SUPPORTS_CANT_BE_EXTENDED;
}
}
}
maxHeight = ride->GetRideTypeDescriptor().Heights.MaxHeight;
}
} while (!(tileElement++)->IsLastForTile());
int32_t zDelta = trackElement->clearance_height - _height;
if (zDelta >= 0 && zDelta / 2 > maxHeight)
{
return STR_SUPPORTS_CANT_BE_EXTENDED;
}
}
return STR_NONE;
}
@ -327,11 +323,8 @@ TileElement* LandSetHeightAction::CheckFloatingStructures(TileElement* surfaceEl
TileElement* LandSetHeightAction::CheckUnremovableObstructions(TileElement* surfaceElement, uint8_t zCorner) const
{
TileElement* tileElement = map_get_first_element_at(_coords);
do
for (auto* tileElement : TileElementsView(_coords))
{
if (tileElement == nullptr)
break;
int32_t elementType = tileElement->GetType();
// Wall's and Small Scenery are removed and therefore do not need checked
@ -355,7 +348,7 @@ TileElement* LandSetHeightAction::CheckUnremovableObstructions(TileElement* surf
{
return tileElement;
}
} while (!(tileElement++)->IsLastForTile());
}
return nullptr;
}

View File

@ -24,6 +24,9 @@
#include "../world/Scenery.h"
#include "../world/Sprite.h"
#include "../world/Surface.h"
#include "../world/TileElementsView.h"
using namespace OpenRCT2;
LandSetRightsAction::LandSetRightsAction(const MapRange& range, LandSetRightSetting setting, uint8_t ownership)
: _range(range)
@ -160,16 +163,9 @@ GameActions::Result::Ptr LandSetRightsAction::map_buy_land_rights_for_tile(const
return res;
}
TileElement* tileElement = map_get_first_element_at(loc);
do
for (auto* entranceElement : TileElementsView<EntranceElement>(loc))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
continue;
if (tileElement->AsEntrance()->GetEntranceType() != ENTRANCE_TYPE_PARK_ENTRANCE)
if (entranceElement->GetEntranceType() != ENTRANCE_TYPE_PARK_ENTRANCE)
continue;
// Do not allow ownership of park entrance.
@ -180,11 +176,13 @@ GameActions::Result::Ptr LandSetRightsAction::map_buy_land_rights_for_tile(const
// There is no need to check the height if _ownership is 0 (unowned and no rights available).
if (_ownership == OWNERSHIP_CONSTRUCTION_RIGHTS_OWNED || _ownership == OWNERSHIP_CONSTRUCTION_RIGHTS_AVAILABLE)
{
if (tileElement->base_height - 3 > surfaceElement->base_height
|| tileElement->base_height < surfaceElement->base_height)
if (entranceElement->base_height - 3 > surfaceElement->base_height
|| entranceElement->base_height < surfaceElement->base_height)
{
return res;
}
}
} while (!(tileElement++)->IsLastForTile());
}
res->Cost = gLandPrice;
if (isExecuting)

View File

@ -21,6 +21,9 @@
#include "../world/Park.h"
#include "../world/SmallScenery.h"
#include "../world/Sprite.h"
#include "../world/TileElementsView.h"
using namespace OpenRCT2;
LargeSceneryRemoveAction::LargeSceneryRemoveAction(const CoordsXYZD& location, uint16_t tileIndex)
: _loc(location)
@ -59,7 +62,7 @@ GameActions::Result::Ptr LargeSceneryRemoveAction::Query() const
res->Expenditure = ExpenditureType::Landscaping;
res->Cost = 0;
TileElement* tileElement = FindLargeSceneryElement();
TileElement* tileElement = FindLargeSceneryElement(_loc, _tileIndex);
if (tileElement == nullptr)
{
log_warning("Invalid game command for scenery removal, x = %d, y = %d", _loc.x, _loc.y);
@ -123,8 +126,6 @@ GameActions::Result::Ptr LargeSceneryRemoveAction::Execute() const
{
GameActions::Result::Ptr res = std::make_unique<GameActions::Result>();
const uint32_t flags = GetFlags();
int32_t z = tile_element_height(_loc);
res->Position.x = _loc.x + 16;
res->Position.y = _loc.y + 16;
@ -132,7 +133,7 @@ GameActions::Result::Ptr LargeSceneryRemoveAction::Execute() const
res->Expenditure = ExpenditureType::Landscaping;
res->Cost = 0;
TileElement* tileElement = FindLargeSceneryElement();
TileElement* tileElement = FindLargeSceneryElement(_loc, _tileIndex);
if (tileElement == nullptr)
{
log_warning("Invalid game command for scenery removal, x = %d, y = %d", _loc.x, _loc.y);
@ -171,37 +172,13 @@ GameActions::Result::Ptr LargeSceneryRemoveAction::Execute() const
}
}
TileElement* sceneryElement = map_get_first_element_at(currentTile);
bool element_found = false;
auto* sceneryElement = FindLargeSceneryElement(currentTile, i);
if (sceneryElement != nullptr)
{
do
{
if (sceneryElement->GetType() != TILE_ELEMENT_TYPE_LARGE_SCENERY)
continue;
if (sceneryElement->GetDirection() != _loc.direction)
continue;
if (sceneryElement->AsLargeScenery()->GetSequenceIndex() != i)
continue;
if (sceneryElement->GetBaseZ() != currentTile.z)
continue;
// If we are removing ghost elements
if ((flags & GAME_COMMAND_FLAG_GHOST) && sceneryElement->IsGhost() == false)
continue;
map_invalidate_tile_full(currentTile);
tile_element_remove(sceneryElement);
element_found = true;
break;
} while (!(sceneryElement++)->IsLastForTile());
map_invalidate_tile_full(currentTile);
tile_element_remove(sceneryElement);
}
if (element_found == false)
else
{
log_error("Tile not found when trying to remove element!");
}
@ -212,33 +189,25 @@ GameActions::Result::Ptr LargeSceneryRemoveAction::Execute() const
return res;
}
TileElement* LargeSceneryRemoveAction::FindLargeSceneryElement() const
TileElement* LargeSceneryRemoveAction::FindLargeSceneryElement(const CoordsXYZ& pos, int32_t sequenceIndex) const
{
TileElement* tileElement = map_get_first_element_at(_loc);
if (tileElement == nullptr)
return nullptr;
do
for (auto* sceneryElement : TileElementsView<LargeSceneryElement>(pos))
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_LARGE_SCENERY)
continue;
if (tileElement->GetBaseZ() != _loc.z)
continue;
if (tileElement->AsLargeScenery()->GetSequenceIndex() != _tileIndex)
continue;
if (tileElement->GetDirection() != _loc.direction)
continue;
// If we are removing ghost elements
if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && tileElement->IsGhost() == false)
if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && sceneryElement->IsGhost() == false)
continue;
return tileElement;
if (sceneryElement->GetDirection() != _loc.direction)
continue;
} while (!(tileElement++)->IsLastForTile());
if (sceneryElement->GetSequenceIndex() != sequenceIndex)
continue;
if (sceneryElement->GetBaseZ() != pos.z)
continue;
return sceneryElement->as<TileElement>();
}
return nullptr;
}

View File

@ -30,5 +30,5 @@ public:
GameActions::Result::Ptr Execute() const override;
private:
TileElement* FindLargeSceneryElement() const;
TileElement* FindLargeSceneryElement(const CoordsXYZ& pos, int32_t sequenceIndex) const;
};

View File

@ -12,6 +12,9 @@
#include "../ride/Ride.h"
#include "../ride/Station.h"
#include "../world/Entrance.h"
#include "../world/TileElementsView.h"
using namespace OpenRCT2;
RideEntranceExitRemoveAction::RideEntranceExitRemoveAction(
const CoordsXY& loc, ride_id_t rideIndex, StationIndex stationNum, bool isExit)
@ -42,6 +45,28 @@ void RideEntranceExitRemoveAction::Serialise(DataSerialiser& stream)
stream << DS_TAG(_loc) << DS_TAG(_rideIndex) << DS_TAG(_stationNum) << DS_TAG(_isExit);
}
static TileElement* FindEntranceElement(
const CoordsXY& loc, ride_id_t rideIndex, int32_t stationNum, int32_t entranceType, bool ghost)
{
for (auto* entranceElement : TileElementsView<EntranceElement>(loc))
{
if (entranceElement->IsGhost() != ghost)
continue;
if (entranceElement->GetRideIndex() != rideIndex)
continue;
if (entranceElement->GetStationIndex() != stationNum)
continue;
if (entranceElement->GetEntranceType() != entranceType)
continue;
return entranceElement->as<TileElement>();
}
return nullptr;
}
GameActions::Result::Ptr RideEntranceExitRemoveAction::Query() const
{
auto ride = get_ride(_rideIndex);
@ -66,40 +91,12 @@ GameActions::Result::Ptr RideEntranceExitRemoveAction::Query() const
return MakeResult(GameActions::Status::InvalidParameters, STR_LAND_NOT_OWNED_BY_PARK);
}
bool found = false;
TileElement* tileElement = map_get_first_element_at(_loc);
const bool isGhost = GetFlags() & GAME_COMMAND_FLAG_GHOST;
do
{
if (tileElement == nullptr)
break;
auto* entranceElement = FindEntranceElement(
_loc, _rideIndex, _stationNum, _isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE, isGhost);
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
continue;
if (tileElement->GetRideIndex() != _rideIndex)
continue;
if (tileElement->AsEntrance()->GetStationIndex() != _stationNum)
continue;
if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && !(tileElement->IsGhost()))
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE)
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE && _isExit)
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT && !_isExit)
continue;
found = true;
break;
} while (!(tileElement++)->IsLastForTile());
if (!found)
if (entranceElement == nullptr)
{
log_warning(
"Track Element not found. x = %d, y = %d, ride = %d, station = %d", _loc.x, _loc.y,
@ -119,47 +116,18 @@ GameActions::Result::Ptr RideEntranceExitRemoveAction::Execute() const
return std::make_unique<GameActions::Result>(GameActions::Status::InvalidParameters, STR_NONE);
}
if (!(GetFlags() & GAME_COMMAND_FLAG_GHOST))
const bool isGhost = GetFlags() & GAME_COMMAND_FLAG_GHOST;
if (!isGhost)
{
ride_clear_for_construction(ride);
ride_remove_peeps(ride);
invalidate_test_results(ride);
}
bool found = false;
TileElement* tileElement = map_get_first_element_at(_loc);
auto* entranceElement = FindEntranceElement(
_loc, _rideIndex, _stationNum, _isExit ? ENTRANCE_TYPE_RIDE_EXIT : ENTRANCE_TYPE_RIDE_ENTRANCE, isGhost);
do
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE)
continue;
if (tileElement->GetRideIndex() != _rideIndex)
continue;
if (tileElement->AsEntrance()->GetStationIndex() != _stationNum)
continue;
if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && !tileElement->IsGhost())
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_PARK_ENTRANCE)
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_RIDE_ENTRANCE && _isExit)
continue;
if (tileElement->AsEntrance()->GetEntranceType() == ENTRANCE_TYPE_RIDE_EXIT && !_isExit)
continue;
found = true;
break;
} while (!(tileElement++)->IsLastForTile());
if (!found)
if (entranceElement == nullptr)
{
log_warning(
"Track Element not found. x = %d, y = %d, ride = %d, station = %d", _loc.x, _loc.y,
@ -173,10 +141,10 @@ GameActions::Result::Ptr RideEntranceExitRemoveAction::Execute() const
res->Position.z = tile_element_height(res->Position);
footpath_queue_chain_reset();
maze_entrance_hedge_replacement({ _loc, tileElement });
footpath_remove_edges_at(_loc, tileElement);
maze_entrance_hedge_replacement({ _loc, entranceElement });
footpath_remove_edges_at(_loc, entranceElement);
tile_element_remove(tileElement);
tile_element_remove(entranceElement);
if (_isExit)
{

View File

@ -21,9 +21,12 @@
#include "../world/Park.h"
#include "../world/SmallScenery.h"
#include "../world/Sprite.h"
#include "../world/TileElementsView.h"
#include "GameAction.h"
#include "SmallSceneryPlaceAction.h"
using namespace OpenRCT2;
SmallSceneryRemoveAction::SmallSceneryRemoveAction(const CoordsXYZ& location, uint8_t quadrant, ObjectEntryIndex sceneryType)
: _loc(location)
, _quadrant(quadrant)
@ -132,26 +135,18 @@ GameActions::Result::Ptr SmallSceneryRemoveAction::Execute() const
TileElement* SmallSceneryRemoveAction::FindSceneryElement() const
{
TileElement* tileElement = map_get_first_element_at(_loc);
if (!tileElement)
return nullptr;
do
const bool isGhost = GetFlags() & GAME_COMMAND_FLAG_GHOST;
for (auto* sceneryElement : TileElementsView<SmallSceneryElement>(_loc))
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY)
if (sceneryElement->IsGhost() != isGhost)
continue;
if ((tileElement->AsSmallScenery()->GetSceneryQuadrant()) != _quadrant)
if (sceneryElement->GetSceneryQuadrant() != _quadrant)
continue;
if (tileElement->GetBaseZ() != _loc.z)
if (sceneryElement->GetBaseZ() != _loc.z)
continue;
if (tileElement->AsSmallScenery()->GetEntryIndex() != _sceneryType)
if (sceneryElement->GetEntryIndex() != _sceneryType)
continue;
if ((GetFlags() & GAME_COMMAND_FLAG_GHOST) && tileElement->IsGhost() == false)
continue;
return tileElement;
} while (!(tileElement++)->IsLastForTile());
return sceneryElement->as<TileElement>();
}
return nullptr;
}

View File

@ -16,8 +16,11 @@
#include "../localisation/StringIds.h"
#include "../management/Finance.h"
#include "../world/Location.hpp"
#include "../world/TileElementsView.h"
#include "../world/Wall.h"
using namespace OpenRCT2;
WallRemoveAction::WallRemoveAction(const CoordsXYZD& loc)
: _loc(loc)
{
@ -93,22 +96,16 @@ GameActions::Result::Ptr WallRemoveAction::Execute() const
TileElement* WallRemoveAction::GetFirstWallElementAt(const CoordsXYZD& location, bool isGhost) const
{
TileElement* tileElement = map_get_first_element_at(location);
if (!tileElement)
return nullptr;
do
for (auto* wallElement : TileElementsView<WallElement>(location))
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_WALL)
if (wallElement->GetBaseZ() != location.z)
continue;
if (tileElement->GetBaseZ() != location.z)
if (wallElement->GetDirection() != location.direction)
continue;
if (tileElement->GetDirection() != location.direction)
continue;
if (tileElement->IsGhost() != isGhost)
if (wallElement->IsGhost() != isGhost)
continue;
return tileElement;
} while (!(tileElement++)->IsLastForTile());
return wallElement->as<TileElement>();
}
return nullptr;
}

View File

@ -17,6 +17,7 @@
#include "../util/Util.h"
#include "../world/Location.hpp"
#include "../world/Map.h"
#include "../world/TileElementsView.h"
#include "Paint.h"
#include "VirtualFloor.h"
#include "tile_element/Paint.TileElement.h"
@ -24,6 +25,8 @@
#include <algorithm>
#include <limits>
using namespace OpenRCT2;
static uint16_t _virtualFloorBaseSize = 5 * 32;
static uint16_t _virtualFloorHeight = 0;
static CoordsXYZ _virtualFloorLastMinPos;
@ -241,10 +244,7 @@ static void virtual_floor_get_tile_properties(
// * Surfaces, which may put us underground
// * Walls / banners, which are displayed as occupied edges
// * Ghost objects, which are displayed as lit squares
TileElement* tileElement = map_get_first_element_at(loc);
if (tileElement == nullptr)
return;
do
for (auto* tileElement : TileElementsView(loc))
{
int32_t elementType = tileElement->GetType();
@ -285,7 +285,7 @@ static void virtual_floor_get_tile_properties(
}
*outOccupied = true;
} while (!(tileElement++)->IsLastForTile());
}
}
void virtual_floor_paint(paint_session* session)

View File

@ -36,6 +36,7 @@
#include "../world/Scenery.h"
#include "../world/Sprite.h"
#include "../world/Surface.h"
#include "../world/TileElementsView.h"
#include "GuestPathfinding.h"
#include "Peep.h"
#include "Staff.h"
@ -43,6 +44,8 @@
#include <algorithm>
#include <iterator>
using namespace OpenRCT2;
// Locations of the spiral slide platform that a peep walks from the entrance of the ride to the
// entrance of the slide. Up to 4 waypoints for each 4 sides that an ride entrance can be located
// and 4 different rotations of the ride. 4 * 4 * 4 = 64 locations.
@ -944,29 +947,24 @@ void Guest::Tick128UpdateGuest(int32_t index)
{
/* Peep happiness is affected once the peep has been waiting
* too long in a queue. */
TileElement* tileElement = map_get_first_element_at(NextLoc);
bool found = false;
do
for (auto* pathElement : TileElementsView<PathElement>(NextLoc))
{
if (tileElement == nullptr)
break;
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
continue;
if (tileElement->GetBaseZ() != NextLoc.z)
if (pathElement->GetBaseZ() != NextLoc.z)
continue;
// Check if the footpath has a queue line TV monitor on it
if (tileElement->AsPath()->HasAddition() && !tileElement->AsPath()->AdditionIsGhost())
if (pathElement->HasAddition() && !pathElement->AdditionIsGhost())
{
auto pathSceneryIndex = tileElement->AsPath()->GetAdditionEntryIndex();
auto pathSceneryIndex = pathElement->GetAdditionEntryIndex();
rct_scenery_entry* sceneryEntry = get_footpath_item_entry(pathSceneryIndex);
if (sceneryEntry != nullptr && sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_QUEUE_SCREEN)
if (sceneryEntry != nullptr && (sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_QUEUE_SCREEN))
{
found = true;
}
}
break;
} while (!(tileElement++)->IsLastForTile());
}
if (found)
{
@ -1678,20 +1676,14 @@ std::bitset<MAX_RIDES> Guest::FindRidesToGoOn()
{
for (int32_t tileY = cy - radius; tileY <= cy + radius; tileY += COORDS_XY_STEP)
{
if (map_is_location_valid({ tileX, tileY }))
auto location = CoordsXY{ tileX, tileY };
if (!map_is_location_valid(location))
continue;
for (auto* trackElement : TileElementsView<TrackElement>(location))
{
auto tileElement = map_get_first_element_at({ tileX, tileY });
if (tileElement != nullptr)
{
do
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK)
{
auto rideIndex = tileElement->AsTrack()->GetRideIndex();
rideConsideration[rideIndex] = true;
}
} while (!(tileElement++)->IsLastForTile());
}
auto rideIndex = trackElement->GetRideIndex();
rideConsideration[rideIndex] = true;
}
}
}
@ -2705,10 +2697,7 @@ static PeepThoughtType peep_assess_surroundings(int16_t centre_x, int16_t centre
{
for (int16_t y = initial_y; y < final_y; y += COORDS_XY_STEP)
{
TileElement* tileElement = map_get_first_element_at({ x, y });
if (tileElement == nullptr)
continue;
do
for (auto* tileElement : TileElementsView({ x, y }))
{
Ride* ride;
rct_scenery_entry* scenery;
@ -2770,7 +2759,7 @@ static PeepThoughtType peep_assess_surroundings(int16_t centre_x, int16_t centre
}
break;
}
} while (!(tileElement++)->IsLastForTile());
}
}
}
@ -2939,24 +2928,21 @@ template<typename T> static void peep_head_for_nearest_ride(Guest* peep, bool co
{
for (auto y = cy - searchRadius; y <= cy + searchRadius; y += COORDS_XY_STEP)
{
if (map_is_location_valid({ x, y }))
auto location = CoordsXY{ x, y };
if (!map_is_location_valid(location))
continue;
for (auto* trackElement : TileElementsView<TrackElement>(location))
{
auto tileElement = map_get_first_element_at({ x, y });
if (tileElement != nullptr)
{
do
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK)
{
auto rideIndex = tileElement->AsTrack()->GetRideIndex();
auto ride = get_ride(rideIndex);
if (ride != nullptr && predicate(*ride))
{
rideConsideration[rideIndex] = true;
}
}
} while (!(tileElement++)->IsLastForTile());
}
auto rideIndex = trackElement->GetRideIndex();
auto ride = get_ride(rideIndex);
if (ride == nullptr)
continue;
if (!predicate(*ride))
continue;
rideConsideration[rideIndex] = true;
}
}
}
@ -3936,19 +3922,20 @@ void Guest::UpdateRideLeaveVehicle()
if (trackType == TrackElemType::Flat || trackType > TrackElemType::MiddleStation)
continue;
TileElement* inner_map = map_get_first_element_at(vehicle->TrackLocation);
if (inner_map == nullptr)
continue;
for (;; inner_map++)
bool foundStation = false;
for (auto* trackElement : TileElementsView<TrackElement>(vehicle->TrackLocation))
{
if (inner_map->GetType() != TILE_ELEMENT_TYPE_TRACK)
if (trackElement->GetBaseZ() != vehicle->TrackLocation.z)
continue;
if (inner_map->GetBaseZ() == vehicle->TrackLocation.z)
break;
if (trackElement->GetStationIndex() != CurrentRideStation)
continue;
foundStation = true;
break;
}
auto stationIndex = inner_map->AsTrack()->GetStationIndex();
if (stationIndex == CurrentRideStation)
if (foundStation)
break;
}
@ -4773,17 +4760,10 @@ void Guest::UpdateRideLeaveExit()
CoordsXY targetLoc = { x, y };
// Find the station track element
TileElement* tileElement = map_get_first_element_at(targetLoc);
if (tileElement == nullptr)
return;
do
for (auto* pathElement : TileElementsView<PathElement>(targetLoc))
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
continue;
int16_t height = map_height_from_slope(
targetLoc, tileElement->AsPath()->GetSlopeDirection(), tileElement->AsPath()->IsSloped());
height += tileElement->GetBaseZ();
int16_t height = map_height_from_slope(targetLoc, pathElement->GetSlopeDirection(), pathElement->IsSloped());
height += pathElement->GetBaseZ();
int16_t z_diff = z - height;
if (z_diff > 0 || z_diff < -16)
@ -4791,7 +4771,7 @@ void Guest::UpdateRideLeaveExit()
MoveTo({ x, y, height });
return;
} while (!(tileElement++)->IsLastForTile());
}
}
/**
@ -5598,51 +5578,30 @@ void Guest::UpdateUsingBin()
return;
}
TileElement* tileElement = map_get_first_element_at(NextLoc);
if (tileElement == nullptr)
return;
bool found = false;
do
PathElement* foundElement = nullptr;
for (auto* pathElement : TileElementsView<PathElement>(NextLoc))
{
if (tileElement->GetType() != TILE_ELEMENT_TYPE_PATH)
{
if (pathElement->GetBaseZ() != NextLoc.z)
continue;
}
if (tileElement->GetBaseZ() == NextLoc.z)
{
found = true;
if (!pathElement->HasAddition())
break;
}
} while (!(tileElement++)->IsLastForTile());
if (!found)
{
StateReset();
return;
rct_scenery_entry* sceneryEntry = pathElement->GetAdditionEntry();
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN))
break;
if (pathElement->IsBroken())
break;
if (pathElement->AdditionIsGhost())
break;
foundElement = pathElement;
break;
}
if (!tileElement->AsPath()->HasAddition())
{
StateReset();
return;
}
rct_scenery_entry* sceneryEntry = tileElement->AsPath()->GetAdditionEntry();
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN))
{
StateReset();
return;
}
if (tileElement->AsPath()->IsBroken())
{
StateReset();
return;
}
if (tileElement->AsPath()->AdditionIsGhost())
if (foundElement == nullptr)
{
StateReset();
return;
@ -5652,7 +5611,7 @@ void Guest::UpdateUsingBin()
uint8_t selectedBin = Var37 * 2;
// This counts down 2 = No rubbish, 0 = full
uint8_t spaceLeftInBin = 0x3 & (tileElement->AsPath()->GetAdditionStatus() >> selectedBin);
uint8_t spaceLeftInBin = 0x3 & (foundElement->GetAdditionStatus() >> selectedBin);
uint64_t emptyContainers = GetEmptyContainerFlags();
for (uint8_t curContainer = 0; curContainer < 64; curContainer++)
@ -5686,14 +5645,14 @@ void Guest::UpdateUsingBin()
UpdateSpriteType();
}
uint8_t additionStatus = tileElement->AsPath()->GetAdditionStatus();
uint8_t additionStatus = foundElement->GetAdditionStatus();
// Place new amount in bin by first clearing the value
additionStatus &= ~(3 << selectedBin);
// Then placing the new value.
additionStatus |= spaceLeftInBin << selectedBin;
tileElement->AsPath()->SetAdditionStatus(additionStatus);
foundElement->SetAdditionStatus(additionStatus);
map_invalidate_tile_zoom0({ NextLoc, tileElement->GetBaseZ(), tileElement->GetClearanceZ() });
map_invalidate_tile_zoom0({ NextLoc, foundElement->GetBaseZ(), foundElement->GetClearanceZ() });
StateReset();
break;
}
@ -5730,6 +5689,32 @@ bool Guest::ShouldFindBench()
return !GetNextIsSurface() && !GetNextIsSloped();
}
static PathElement* FindBench(const CoordsXYZ& loc)
{
for (auto* pathElement : TileElementsView<PathElement>(loc))
{
if (pathElement->GetBaseZ() != loc.z)
continue;
if (!pathElement->HasAddition())
continue;
rct_scenery_entry* sceneryEntry = pathElement->GetAdditionEntry();
if (sceneryEntry == nullptr || !(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BENCH))
continue;
if (pathElement->IsBroken())
continue;
if (pathElement->AdditionIsGhost())
continue;
return pathElement;
}
return nullptr;
}
/**
*
* rct2: 0x00690582
@ -5740,40 +5725,13 @@ bool Guest::UpdateWalkingFindBench()
if (!ShouldFindBench())
return false;
TileElement* tileElement = map_get_first_element_at(NextLoc);
if (tileElement == nullptr)
auto* pathElement = FindBench(NextLoc);
if (pathElement == nullptr)
return false;
for (;; tileElement++)
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
{
if (NextLoc.z == tileElement->GetBaseZ())
break;
}
if (tileElement->IsLastForTile())
{
return false;
}
}
if (!tileElement->AsPath()->HasAddition())
return false;
rct_scenery_entry* sceneryEntry = tileElement->AsPath()->GetAdditionEntry();
if (sceneryEntry == nullptr || !(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BENCH))
return false;
if (tileElement->AsPath()->IsBroken())
return false;
if (tileElement->AsPath()->AdditionIsGhost())
return false;
int32_t edges = (tileElement->AsPath()->GetEdges()) ^ 0xF;
int32_t edges = pathElement->GetEdges() ^ 0xF;
if (edges == 0)
return false;
uint8_t chosen_edge = scenario_rand() & 0x3;
for (; !(edges & (1 << chosen_edge));)
@ -5822,6 +5780,32 @@ bool Guest::UpdateWalkingFindBench()
return true;
}
static PathElement* FindBin(const CoordsXYZ& loc)
{
for (auto* pathElement : TileElementsView<PathElement>(loc))
{
if (pathElement->GetBaseZ() != loc.z)
continue;
if (!pathElement->HasAddition())
continue;
rct_scenery_entry* sceneryEntry = pathElement->GetAdditionEntry();
if (sceneryEntry == nullptr || !(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN))
continue;
if (pathElement->IsBroken())
continue;
if (pathElement->AdditionIsGhost())
continue;
return pathElement;
}
return nullptr;
}
bool Guest::UpdateWalkingFindBin()
{
auto peep = this;
@ -5831,48 +5815,18 @@ bool Guest::UpdateWalkingFindBin()
if (peep->GetNextIsSurface())
return false;
TileElement* tileElement = map_get_first_element_at(peep->NextLoc);
if (tileElement == nullptr)
auto* pathElement = FindBin(peep->NextLoc);
if (pathElement == nullptr)
return false;
for (;; tileElement++)
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
{
if (peep->NextLoc.z == tileElement->GetBaseZ())
break;
}
if (tileElement->IsLastForTile())
{
return false;
}
}
if (!tileElement->AsPath()->HasAddition())
return false;
rct_scenery_entry* sceneryEntry = tileElement->AsPath()->GetAdditionEntry();
if (sceneryEntry == nullptr)
{
return false;
}
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_IS_BIN))
return false;
if (tileElement->AsPath()->IsBroken())
return false;
if (tileElement->AsPath()->AdditionIsGhost())
return false;
int32_t edges = (tileElement->AsPath()->GetEdges()) ^ 0xF;
int32_t edges = (pathElement->GetEdges()) ^ 0xF;
if (edges == 0)
return false;
uint8_t chosen_edge = scenario_rand() & 0x3;
// Note: Bin quantity is inverted 0 = full, 3 = empty
uint8_t bin_quantities = tileElement->AsPath()->GetAdditionStatus();
uint8_t bin_quantities = pathElement->GetAdditionStatus();
// Rotate the bin to the correct edge. Makes it easier for next calc.
bin_quantities = ror8(ror8(bin_quantities, chosen_edge), chosen_edge);
@ -5906,6 +5860,32 @@ bool Guest::UpdateWalkingFindBin()
return true;
}
static PathElement* FindBreakableElement(const CoordsXYZ& loc)
{
for (auto* pathElement : TileElementsView<PathElement>(loc))
{
if (pathElement->GetBaseZ() != loc.z)
continue;
if (!pathElement->HasAddition())
continue;
rct_scenery_entry* sceneryEntry = pathElement->GetAdditionEntry();
if (sceneryEntry == nullptr || !(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_BREAKABLE))
continue;
if (pathElement->IsBroken())
continue;
if (pathElement->AdditionIsGhost())
continue;
return pathElement;
}
return nullptr;
}
/**
*
* rct2: 0x00690848
@ -5934,37 +5914,11 @@ static void peep_update_walking_break_scenery(Peep* peep)
if (peep->GetNextIsSurface())
return;
TileElement* tileElement = map_get_first_element_at(peep->NextLoc);
auto* tileElement = FindBreakableElement(peep->NextLoc);
if (tileElement == nullptr)
return;
for (;; tileElement++)
{
if (tileElement->GetType() == TILE_ELEMENT_TYPE_PATH)
{
if (peep->NextLoc.z == tileElement->GetBaseZ())
break;
}
if (tileElement->IsLastForTile())
{
return;
}
}
if (!tileElement->AsPath()->HasAddition())
return;
rct_scenery_entry* sceneryEntry = tileElement->AsPath()->GetAdditionEntry();
if (!(sceneryEntry->path_bit.flags & PATH_BIT_FLAG_BREAKABLE))
return;
if (tileElement->AsPath()->IsBroken())
return;
if (tileElement->AsPath()->AdditionIsGhost())
return;
int32_t edges = tileElement->AsPath()->GetEdges();
int32_t edges = tileElement->GetEdges();
if (edges == 0xF)
return;
@ -5994,7 +5948,7 @@ static void peep_update_walking_break_scenery(Peep* peep)
return;
}
tileElement->AsPath()->SetIsBroken(true);
tileElement->SetIsBroken(true);
map_invalidate_tile_zoom1({ peep->NextLoc, tileElement->GetBaseZ(), tileElement->GetBaseZ() + 32 });