OpenRCT2/src/openrct2/world/Map.h

259 lines
10 KiB
C++

/*****************************************************************************
* Copyright (c) 2014-2024 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "../common.h"
#include "Location.hpp"
#include "TileElement.h"
#include <initializer_list>
#include <vector>
constexpr uint8_t kMinimumLandHeight = 2;
constexpr uint8_t kMaximumLandHeight = 254;
constexpr uint8_t kMinimumWaterHeight = 2;
constexpr uint8_t kMaximumWaterHeight = 254;
/**
* The land height that counts as 0 metres/feet for the land height labels and altitude graphs.
*/
constexpr uint8_t kMapBaseZ = 7;
constexpr uint8_t kMinimumMapSizeTechnical = 5;
constexpr uint16_t kMaximumMapSizeTechnical = 1001;
constexpr int16_t kMinimumMapSizePractical = (kMinimumMapSizeTechnical - 2);
constexpr int16_t kMaximumMapSizePractical = (kMaximumMapSizeTechnical - 2);
constexpr const int32_t MAXIMUM_MAP_SIZE_BIG = COORDS_XY_STEP * kMaximumMapSizeTechnical;
constexpr int32_t MAXIMUM_TILE_START_XY = MAXIMUM_MAP_SIZE_BIG - COORDS_XY_STEP;
constexpr const int32_t LAND_HEIGHT_STEP = 2 * COORDS_Z_STEP;
constexpr const int32_t WATER_HEIGHT_STEP = 2 * COORDS_Z_STEP;
constexpr const int32_t kMinimumLandZ = kMinimumLandHeight * COORDS_Z_STEP;
constexpr TileCoordsXY DEFAULT_MAP_SIZE = { 150, 150 };
// How high construction has to be off the ground when the player owns construction rights, in tile coords.
constexpr uint8_t ConstructionRightsClearanceSmall = 3;
// Same as previous, but in big coords.
constexpr const uint8_t ConstructionRightsClearanceBig = 3 * COORDS_Z_STEP;
constexpr int16_t kMapMinimumXY = (-kMaximumMapSizeTechnical);
constexpr uint32_t MAX_TILE_ELEMENTS_WITH_SPARE_ROOM = 0x1000000;
constexpr uint32_t MAX_TILE_ELEMENTS = MAX_TILE_ELEMENTS_WITH_SPARE_ROOM - 512;
using PeepSpawn = CoordsXYZD;
struct CoordsXYE : public CoordsXY
{
CoordsXYE() = default;
constexpr CoordsXYE(int32_t _x, int32_t _y, TileElement* _e)
: CoordsXY(_x, _y)
, element(_e)
{
}
constexpr CoordsXYE(const CoordsXY& c, TileElement* _e)
: CoordsXY(c)
, element(_e)
{
}
TileElement* element = nullptr;
};
enum
{
MAP_SELECT_FLAG_ENABLE = 1 << 0,
MAP_SELECT_FLAG_ENABLE_CONSTRUCT = 1 << 1,
MAP_SELECT_FLAG_ENABLE_ARROW = 1 << 2,
MAP_SELECT_FLAG_GREEN = 1 << 3,
};
enum
{
MAP_SELECT_TYPE_CORNER_0,
MAP_SELECT_TYPE_CORNER_1,
MAP_SELECT_TYPE_CORNER_2,
MAP_SELECT_TYPE_CORNER_3,
MAP_SELECT_TYPE_FULL,
MAP_SELECT_TYPE_FULL_WATER,
MAP_SELECT_TYPE_FULL_LAND_RIGHTS,
MAP_SELECT_TYPE_QUARTER_0,
MAP_SELECT_TYPE_QUARTER_1,
MAP_SELECT_TYPE_QUARTER_2,
MAP_SELECT_TYPE_QUARTER_3,
MAP_SELECT_TYPE_EDGE_0,
MAP_SELECT_TYPE_EDGE_1,
MAP_SELECT_TYPE_EDGE_2,
MAP_SELECT_TYPE_EDGE_3,
};
// Used when calling MapCanConstructWithClearAt();
// This assumes that the caller has already done the check on the element it wants to place,
// as this function can only check the element the player wants to build through.
enum
{
CREATE_CROSSING_MODE_NONE,
CREATE_CROSSING_MODE_TRACK_OVER_PATH,
CREATE_CROSSING_MODE_PATH_OVER_TRACK,
};
extern const std::array<CoordsXY, 8> CoordsDirectionDelta;
extern const TileCoordsXY TileDirectionDelta[];
CoordsXY GetMapSizeUnits();
CoordsXY GetMapSizeMinus2();
CoordsXY GetMapSizeMaxXY();
extern uint16_t gMapSelectFlags;
extern uint16_t gMapSelectType;
extern CoordsXY gMapSelectPositionA;
extern CoordsXY gMapSelectPositionB;
extern CoordsXYZ gMapSelectArrowPosition;
extern uint8_t gMapSelectArrowDirection;
extern std::vector<CoordsXY> gMapSelectionTiles;
// Used in the land tool window to enable mountain tool / land smoothing
extern bool gLandMountainMode;
// Used in the land tool window to allow dragging and changing land styles
extern bool gLandPaintMode;
// Used in the clear scenery tool
extern bool gClearSmallScenery;
extern bool gClearLargeScenery;
extern bool gClearFootpath;
extern uint32_t gLandRemainingOwnershipSales;
extern uint32_t gLandRemainingConstructionSales;
extern bool gMapLandRightsUpdateSuccess;
void ReorganiseTileElements();
const std::vector<TileElement>& GetTileElements();
void SetTileElements(std::vector<TileElement>&& tileElements);
void StashMap();
void UnstashMap();
std::vector<TileElement> GetReorganisedTileElementsWithoutGhosts();
void MapInit(const TileCoordsXY& size);
void MapCountRemainingLandRights();
void MapStripGhostFlagFromElements();
TileElement* MapGetFirstElementAt(const CoordsXY& tilePos);
TileElement* MapGetFirstElementAt(const TileCoordsXY& tilePos);
TileElement* MapGetNthElementAt(const CoordsXY& coords, int32_t n);
TileElement* MapGetFirstTileElementWithBaseHeightBetween(const TileCoordsXYRangedZ& loc, TileElementType type);
void MapSetTileElement(const TileCoordsXY& tilePos, TileElement* elements);
int32_t MapHeightFromSlope(const CoordsXY& coords, int32_t slopeDirection, bool isSloped);
BannerElement* MapGetBannerElementAt(const CoordsXYZ& bannerPos, uint8_t direction);
SurfaceElement* MapGetSurfaceElementAt(const TileCoordsXY& coords);
SurfaceElement* MapGetSurfaceElementAt(const CoordsXY& coords);
PathElement* MapGetPathElementAt(const TileCoordsXYZ& loc);
WallElement* MapGetWallElementAt(const CoordsXYZD& wallCoords);
WallElement* MapGetWallElementAt(const CoordsXYRangedZ& coords);
SmallSceneryElement* MapGetSmallSceneryElementAt(const CoordsXYZ& sceneryCoords, int32_t type, uint8_t quadrant);
EntranceElement* MapGetParkEntranceElementAt(const CoordsXYZ& entranceCoords, bool ghost);
EntranceElement* MapGetRideEntranceElementAt(const CoordsXYZ& entranceCoords, bool ghost);
EntranceElement* MapGetRideExitElementAt(const CoordsXYZ& exitCoords, bool ghost);
uint8_t MapGetHighestLandHeight(const MapRange& range);
uint8_t MapGetLowestLandHeight(const MapRange& range);
bool MapCoordIsConnected(const TileCoordsXYZ& loc, uint8_t faceDirection);
void MapRemoveProvisionalElements();
void MapRestoreProvisionalElements();
void MapUpdatePathWideFlags();
bool MapIsLocationValid(const CoordsXY& coords);
bool MapIsEdge(const CoordsXY& coords);
bool MapCanBuildAt(const CoordsXYZ& loc);
bool MapIsLocationOwned(const CoordsXYZ& loc);
bool MapIsLocationInPark(const CoordsXY& coords);
bool MapIsLocationOwnedOrHasRights(const CoordsXY& loc);
bool MapSurfaceIsBlocked(const CoordsXY& mapCoords);
void MapRemoveAllRides();
void MapInvalidateMapSelectionTiles();
void MapInvalidateSelectionRect();
bool MapCheckCapacityAndReorganise(const CoordsXY& loc, size_t numElements = 1);
int16_t TileElementHeight(const CoordsXY& loc);
int16_t TileElementHeight(const CoordsXYZ& loc, uint8_t slope);
int16_t TileElementWaterHeight(const CoordsXY& loc);
void TileElementRemove(TileElement* tileElement);
TileElement* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type);
template<typename T = TileElement> T* MapGetFirstTileElementWithBaseHeightBetween(const TileCoordsXYRangedZ& loc)
{
auto* element = MapGetFirstTileElementWithBaseHeightBetween(loc, T::ElementType);
return element != nullptr ? element->template as<T>() : nullptr;
}
template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants)
{
auto* element = TileElementInsert(loc, occupiedQuadrants, T::ElementType);
return (element != nullptr) ? element->template as<T>() : nullptr;
}
struct TileElementIterator
{
int32_t x;
int32_t y;
TileElement* element;
};
#ifdef PLATFORM_32BIT
assert_struct_size(TileElementIterator, 12);
#endif
void TileElementIteratorBegin(TileElementIterator* it);
int32_t TileElementIteratorNext(TileElementIterator* it);
void TileElementIteratorRestartForTile(TileElementIterator* it);
void MapUpdateTiles();
int32_t MapGetHighestZ(const CoordsXY& loc);
bool TileElementWantsPathConnectionTowards(const TileCoordsXYZD& coords, const TileElement* const elementToBeRemoved);
void MapRemoveOutOfRangeElements();
void MapExtendBoundarySurfaceX();
void MapExtendBoundarySurfaceY();
bool MapLargeScenerySignSetColour(const CoordsXYZD& signPos, int32_t sequence, uint8_t mainColour, uint8_t textColour);
void WallRemoveAt(const CoordsXYRangedZ& wallPos);
void WallRemoveAtZ(const CoordsXYZ& wallPos);
void WallRemoveIntersectingWalls(const CoordsXYRangedZ& wallPos, Direction direction);
void MapInvalidateTile(const CoordsXYRangedZ& tilePos);
void MapInvalidateTileZoom1(const CoordsXYRangedZ& tilePos);
void MapInvalidateTileZoom0(const CoordsXYRangedZ& tilePos);
void MapInvalidateTileFull(const CoordsXY& tilePos);
void MapInvalidateElement(const CoordsXY& elementPos, TileElement* tileElement);
void MapInvalidateRegion(const CoordsXY& mins, const CoordsXY& maxs);
int32_t MapGetTileSide(const CoordsXY& mapPos);
int32_t MapGetTileQuadrant(const CoordsXY& mapPos);
int32_t MapGetCornerHeight(int32_t z, int32_t slope, int32_t direction);
int32_t TileElementGetCornerHeight(const SurfaceElement* surfaceElement, int32_t direction);
void MapClearAllElements();
LargeSceneryElement* MapGetLargeScenerySegment(const CoordsXYZD& sceneryPos, int32_t sequence);
std::optional<CoordsXYZ> MapLargeSceneryGetOrigin(
const CoordsXYZD& sceneryPos, int32_t sequence, LargeSceneryElement** outElement);
TrackElement* MapGetTrackElementAt(const CoordsXYZ& trackPos);
TileElement* MapGetTrackElementAtOfType(const CoordsXYZ& trackPos, track_type_t trackType);
TileElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZ& trackPos, track_type_t trackType, int32_t sequence);
TrackElement* MapGetTrackElementAtOfType(const CoordsXYZD& location, track_type_t trackType);
TrackElement* MapGetTrackElementAtOfTypeSeq(const CoordsXYZD& location, track_type_t trackType, int32_t sequence);
TileElement* MapGetTrackElementAtOfTypeFromRide(const CoordsXYZ& trackPos, track_type_t trackType, RideId rideIndex);
TileElement* MapGetTrackElementAtFromRide(const CoordsXYZ& trackPos, RideId rideIndex);
TileElement* MapGetTrackElementAtWithDirectionFromRide(const CoordsXYZD& trackPos, RideId rideIndex);
bool MapIsLocationAtEdge(const CoordsXY& loc);
uint16_t CheckMaxAllowableLandRightsForTile(const CoordsXYZ& tileMapPos);
void FixLandOwnershipTiles(std::initializer_list<TileCoordsXY> tiles);
void FixLandOwnershipTilesWithOwnership(
std::initializer_list<TileCoordsXY> tiles, uint8_t ownership, bool doNotDowngrade = false);
MapRange ClampRangeWithinMap(const MapRange& range);