1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #pragma once
11 
12 #include "../common.h"
13 #include "Location.hpp"
14 #include "TileElement.h"
15 
16 #include <initializer_list>
17 #include <vector>
18 
19 #define MINIMUM_LAND_HEIGHT 2
20 #define MAXIMUM_LAND_HEIGHT 142
21 #define MINIMUM_WATER_HEIGHT 2
22 #define MAXIMUM_WATER_HEIGHT 58
23 
24 #define MINIMUM_MAP_SIZE_TECHNICAL 15
25 #define MAXIMUM_MAP_SIZE_TECHNICAL 256
26 #define MINIMUM_MAP_SIZE_PRACTICAL (MINIMUM_MAP_SIZE_TECHNICAL - 2)
27 #define MAXIMUM_MAP_SIZE_PRACTICAL (MAXIMUM_MAP_SIZE_TECHNICAL - 2)
28 constexpr const int32_t MAXIMUM_MAP_SIZE_BIG = COORDS_XY_STEP * MAXIMUM_MAP_SIZE_TECHNICAL;
29 constexpr const int32_t MAXIMUM_TILE_START_XY = MAXIMUM_MAP_SIZE_BIG - COORDS_XY_STEP;
30 constexpr const int32_t LAND_HEIGHT_STEP = 2 * COORDS_Z_STEP;
31 constexpr const int32_t MINIMUM_LAND_HEIGHT_BIG = MINIMUM_LAND_HEIGHT * COORDS_Z_STEP;
32 
33 #define MAP_MINIMUM_X_Y (-MAXIMUM_MAP_SIZE_TECHNICAL)
34 
35 constexpr const uint32_t MAX_TILE_ELEMENTS_WITH_SPARE_ROOM = 0x30000;
36 constexpr const uint32_t MAX_TILE_ELEMENTS = MAX_TILE_ELEMENTS_WITH_SPARE_ROOM - 512;
37 #define MAX_TILE_TILE_ELEMENT_POINTERS (MAXIMUM_MAP_SIZE_TECHNICAL * MAXIMUM_MAP_SIZE_TECHNICAL)
38 #define MAX_PEEP_SPAWNS 2
39 
40 #define TILE_UNDEFINED_TILE_ELEMENT NULL
41 
42 using PeepSpawn = CoordsXYZD;
43 
44 struct CoordsXYE : public CoordsXY
45 {
46     CoordsXYE() = default;
CoordsXYECoordsXYE47     constexpr CoordsXYE(int32_t _x, int32_t _y, TileElement* _e)
48         : CoordsXY(_x, _y)
49         , element(_e)
50     {
51     }
52 
CoordsXYECoordsXYE53     constexpr CoordsXYE(const CoordsXY& c, TileElement* _e)
54         : CoordsXY(c)
55         , element(_e)
56     {
57     }
58     TileElement* element = nullptr;
59 };
60 
61 enum
62 {
63     MAP_SELECT_FLAG_ENABLE = 1 << 0,
64     MAP_SELECT_FLAG_ENABLE_CONSTRUCT = 1 << 1,
65     MAP_SELECT_FLAG_ENABLE_ARROW = 1 << 2,
66     MAP_SELECT_FLAG_GREEN = 1 << 3,
67 };
68 
69 enum
70 {
71     MAP_SELECT_TYPE_CORNER_0,
72     MAP_SELECT_TYPE_CORNER_1,
73     MAP_SELECT_TYPE_CORNER_2,
74     MAP_SELECT_TYPE_CORNER_3,
75     MAP_SELECT_TYPE_FULL,
76     MAP_SELECT_TYPE_FULL_WATER,
77     MAP_SELECT_TYPE_QUARTER_0,
78     MAP_SELECT_TYPE_QUARTER_1,
79     MAP_SELECT_TYPE_QUARTER_2,
80     MAP_SELECT_TYPE_QUARTER_3,
81     MAP_SELECT_TYPE_EDGE_0,
82     MAP_SELECT_TYPE_EDGE_1,
83     MAP_SELECT_TYPE_EDGE_2,
84     MAP_SELECT_TYPE_EDGE_3,
85 };
86 
87 // Used when calling MapCanConstructWithClearAt();
88 // This assumes that the caller has already done the check on the element it wants to place,
89 // as this function can only check the element the player wants to build through.
90 enum
91 {
92     CREATE_CROSSING_MODE_NONE,
93     CREATE_CROSSING_MODE_TRACK_OVER_PATH,
94     CREATE_CROSSING_MODE_PATH_OVER_TRACK,
95 };
96 
97 extern const std::array<CoordsXY, 8> CoordsDirectionDelta;
98 extern const TileCoordsXY TileDirectionDelta[];
99 
100 extern TileCoordsXY gWidePathTileLoopPosition;
101 extern uint16_t gGrassSceneryTileLoopPosition;
102 
103 extern int32_t gMapSize;
104 extern int32_t gMapBaseZ;
105 
GetMapSizeUnits()106 inline int32_t GetMapSizeUnits()
107 {
108     return (gMapSize - 1) * COORDS_XY_STEP;
109 }
GetMapSizeMinus2()110 inline int32_t GetMapSizeMinus2()
111 {
112     return (gMapSize * COORDS_XY_STEP) + (8 * COORDS_XY_STEP - 2);
113 }
GetMapSizeMaxXY()114 inline int32_t GetMapSizeMaxXY()
115 {
116     return GetMapSizeUnits() - 1;
117 }
118 
119 extern uint16_t gMapSelectFlags;
120 extern uint16_t gMapSelectType;
121 extern CoordsXY gMapSelectPositionA;
122 extern CoordsXY gMapSelectPositionB;
123 extern CoordsXYZ gMapSelectArrowPosition;
124 extern uint8_t gMapSelectArrowDirection;
125 
126 extern std::vector<CoordsXY> gMapSelectionTiles;
127 extern std::vector<PeepSpawn> gPeepSpawns;
128 
129 // Used in the land tool window to enable mountain tool / land smoothing
130 extern bool gLandMountainMode;
131 // Used in the land tool window to allow dragging and changing land styles
132 extern bool gLandPaintMode;
133 // Used in the clear scenery tool
134 extern bool gClearSmallScenery;
135 extern bool gClearLargeScenery;
136 extern bool gClearFootpath;
137 
138 extern uint32_t gLandRemainingOwnershipSales;
139 extern uint32_t gLandRemainingConstructionSales;
140 
141 extern bool gMapLandRightsUpdateSuccess;
142 
143 constexpr auto SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT = 0x20;
144 extern const uint8_t tile_element_lower_styles[9][32];
145 extern const uint8_t tile_element_raise_styles[9][32];
146 
147 template<typename T> class TilePointerIndex
148 {
149     std::vector<T*> TilePointers;
150     uint16_t MapSize{};
151 
152 public:
153     TilePointerIndex() = default;
154 
TilePointerIndex(const uint16_t mapSize,T * tileElements)155     explicit TilePointerIndex(const uint16_t mapSize, T* tileElements)
156     {
157         MapSize = mapSize;
158         const uint16_t MaxTileElementPointers = MapSize * MapSize;
159         TilePointers.reserve(MaxTileElementPointers);
160 
161         T* tileElement = tileElements;
162         for (size_t y = 0; y < MapSize; y++)
163         {
164             for (size_t x = 0; x < MapSize; x++)
165             {
166                 TilePointers.emplace_back(tileElement);
167                 while (!(tileElement++)->IsLastForTile())
168                     ;
169             }
170         }
171     }
172 
GetFirstElementAt(TileCoordsXY coords)173     T* GetFirstElementAt(TileCoordsXY coords)
174     {
175         return TilePointers[coords.x + (coords.y * MapSize)];
176     }
177 
SetTile(TileCoordsXY coords,T * tileElement)178     void SetTile(TileCoordsXY coords, T* tileElement)
179     {
180         TilePointers[coords.x + (coords.y * MapSize)] = tileElement;
181     }
182 };
183 
184 void ReorganiseTileElements();
185 const std::vector<TileElement>& GetTileElements();
186 void SetTileElements(std::vector<TileElement>&& tileElements);
187 void StashMap();
188 void UnstashMap();
189 std::vector<TileElement> GetReorganisedTileElementsWithoutGhosts();
190 
191 void map_init(int32_t size);
192 
193 void map_count_remaining_land_rights();
194 void map_strip_ghost_flag_from_elements();
195 TileElement* map_get_first_element_at(const CoordsXY& tilePos);
196 TileElement* map_get_first_element_at(const TileCoordsXY& tilePos);
197 TileElement* map_get_nth_element_at(const CoordsXY& coords, int32_t n);
198 void map_set_tile_element(const TileCoordsXY& tilePos, TileElement* elements);
199 int32_t map_height_from_slope(const CoordsXY& coords, int32_t slopeDirection, bool isSloped);
200 BannerElement* map_get_banner_element_at(const CoordsXYZ& bannerPos, uint8_t direction);
201 SurfaceElement* map_get_surface_element_at(const CoordsXY& coords);
202 PathElement* map_get_path_element_at(const TileCoordsXYZ& loc);
203 WallElement* map_get_wall_element_at(const CoordsXYZD& wallCoords);
204 WallElement* map_get_wall_element_at(const CoordsXYRangedZ& coords);
205 SmallSceneryElement* map_get_small_scenery_element_at(const CoordsXYZ& sceneryCoords, int32_t type, uint8_t quadrant);
206 EntranceElement* map_get_park_entrance_element_at(const CoordsXYZ& entranceCoords, bool ghost);
207 EntranceElement* map_get_ride_entrance_element_at(const CoordsXYZ& entranceCoords, bool ghost);
208 EntranceElement* map_get_ride_exit_element_at(const CoordsXYZ& exitCoords, bool ghost);
209 int16_t tile_element_height(const CoordsXY& loc);
210 int16_t tile_element_water_height(const CoordsXY& loc);
211 uint8_t map_get_highest_land_height(const MapRange& range);
212 uint8_t map_get_lowest_land_height(const MapRange& range);
213 bool map_coord_is_connected(const TileCoordsXYZ& loc, uint8_t faceDirection);
214 void map_remove_provisional_elements();
215 void map_restore_provisional_elements();
216 void map_update_path_wide_flags();
217 bool map_is_location_valid(const CoordsXY& coords);
218 bool map_is_edge(const CoordsXY& coords);
219 bool map_can_build_at(const CoordsXYZ& loc);
220 bool map_is_location_owned(const CoordsXYZ& loc);
221 bool map_is_location_in_park(const CoordsXY& coords);
222 bool map_is_location_owned_or_has_rights(const CoordsXY& loc);
223 bool map_surface_is_blocked(const CoordsXY& mapCoords);
224 void tile_element_remove(TileElement* tileElement);
225 void map_remove_all_rides();
226 void map_invalidate_map_selection_tiles();
227 void map_invalidate_selection_rect();
228 bool MapCheckCapacityAndReorganise(const CoordsXY& loc, size_t numElements = 1);
229 TileElement* tile_element_insert(const CoordsXYZ& loc, int32_t occupiedQuadrants, TileElementType type);
230 
TileElementInsert(const CoordsXYZ & loc,int32_t occupiedQuadrants)231 template<typename T> T* TileElementInsert(const CoordsXYZ& loc, int32_t occupiedQuadrants)
232 {
233     auto* element = tile_element_insert(loc, occupiedQuadrants, T::ElementType);
234     return (element != nullptr) ? element->template as<T>() : nullptr;
235 }
236 
237 struct tile_element_iterator
238 {
239     int32_t x;
240     int32_t y;
241     TileElement* element;
242 };
243 #ifdef PLATFORM_32BIT
244 assert_struct_size(tile_element_iterator, 12);
245 #endif
246 
247 void tile_element_iterator_begin(tile_element_iterator* it);
248 int32_t tile_element_iterator_next(tile_element_iterator* it);
249 void tile_element_iterator_restart_for_tile(tile_element_iterator* it);
250 
251 void map_update_tiles();
252 int32_t map_get_highest_z(const CoordsXY& loc);
253 
254 bool tile_element_wants_path_connection_towards(const TileCoordsXYZD& coords, const TileElement* const elementToBeRemoved);
255 
256 void map_remove_out_of_range_elements();
257 void map_extend_boundary_surface();
258 
259 bool map_large_scenery_sign_set_colour(const CoordsXYZD& signPos, int32_t sequence, uint8_t mainColour, uint8_t textColour);
260 void wall_remove_at(const CoordsXYRangedZ& wallPos);
261 void wall_remove_at_z(const CoordsXYZ& wallPos);
262 void wall_remove_intersecting_walls(const CoordsXYRangedZ& wallPos, Direction direction);
263 
264 void map_invalidate_tile(const CoordsXYRangedZ& tilePos);
265 void map_invalidate_tile_zoom1(const CoordsXYRangedZ& tilePos);
266 void map_invalidate_tile_zoom0(const CoordsXYRangedZ& tilePos);
267 void map_invalidate_tile_full(const CoordsXY& tilePos);
268 void map_invalidate_element(const CoordsXY& elementPos, TileElement* tileElement);
269 void map_invalidate_region(const CoordsXY& mins, const CoordsXY& maxs);
270 
271 int32_t map_get_tile_side(const CoordsXY& mapPos);
272 int32_t map_get_tile_quadrant(const CoordsXY& mapPos);
273 int32_t map_get_corner_height(int32_t z, int32_t slope, int32_t direction);
274 int32_t tile_element_get_corner_height(const SurfaceElement* surfaceElement, int32_t direction);
275 
276 void map_clear_all_elements();
277 
278 LargeSceneryElement* map_get_large_scenery_segment(const CoordsXYZD& sceneryPos, int32_t sequence);
279 std::optional<CoordsXYZ> map_large_scenery_get_origin(
280     const CoordsXYZD& sceneryPos, int32_t sequence, LargeSceneryElement** outElement);
281 
282 ScreenCoordsXY translate_3d_to_2d_with_z(int32_t rotation, const CoordsXYZ& pos);
283 
284 TrackElement* map_get_track_element_at(const CoordsXYZ& trackPos);
285 TileElement* map_get_track_element_at_of_type(const CoordsXYZ& trackPos, track_type_t trackType);
286 TileElement* map_get_track_element_at_of_type_seq(const CoordsXYZ& trackPos, track_type_t trackType, int32_t sequence);
287 TrackElement* map_get_track_element_at_of_type(const CoordsXYZD& location, track_type_t trackType);
288 TrackElement* map_get_track_element_at_of_type_seq(const CoordsXYZD& location, track_type_t trackType, int32_t sequence);
289 TileElement* map_get_track_element_at_of_type_from_ride(const CoordsXYZ& trackPos, track_type_t trackType, ride_id_t rideIndex);
290 TileElement* map_get_track_element_at_from_ride(const CoordsXYZ& trackPos, ride_id_t rideIndex);
291 TileElement* map_get_track_element_at_with_direction_from_ride(const CoordsXYZD& trackPos, ride_id_t rideIndex);
292 
293 bool map_is_location_at_edge(const CoordsXY& loc);
294 
295 uint16_t check_max_allowable_land_rights_for_tile(const CoordsXYZ& tileMapPos);
296 
297 void FixLandOwnershipTiles(std::initializer_list<TileCoordsXY> tiles);
298 void FixLandOwnershipTilesWithOwnership(
299     std::initializer_list<TileCoordsXY> tiles, uint8_t ownership, bool doNotDowngrade = false);
300