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 "../interface/Viewport.h" 14 #include "../object/Object.h" 15 16 class FootpathObject; 17 class FootpathSurfaceObject; 18 class FootpathRailingsObject; 19 20 enum 21 { 22 PROVISIONAL_PATH_FLAG_SHOW_ARROW = (1 << 0), 23 PROVISIONAL_PATH_FLAG_1 = (1 << 1), 24 PROVISIONAL_PATH_FLAG_2 = (1 << 2), 25 }; 26 27 constexpr auto FootpathMaxHeight = 248 * COORDS_Z_STEP; 28 constexpr auto FootpathMinHeight = 2 * COORDS_Z_STEP; 29 constexpr auto PATH_HEIGHT_STEP = 2 * COORDS_Z_STEP; 30 constexpr auto PATH_CLEARANCE = 4 * COORDS_Z_STEP; 31 32 class FootpathObject; 33 34 enum class RailingEntrySupportType : uint8_t 35 { 36 Box = 0, 37 Pole = 1, 38 Count 39 }; 40 41 enum 42 { 43 FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR = (1 << 2), 44 FOOTPATH_ENTRY_FLAG_IS_QUEUE = (1 << 3), 45 FOOTPATH_ENTRY_FLAG_NO_SLOPE_RAILINGS = (1 << 4), 46 }; 47 48 #pragma pack(push, 1) 49 struct rct_footpath_entry 50 { 51 rct_string_id string_idx; // 0x00 52 uint32_t image; // 0x02 53 uint32_t bridge_image; // 0x06 54 RailingEntrySupportType support_type; // 0x0A 55 uint8_t flags; // 0x0B 56 uint8_t scrolling_mode; // 0x0C 57 GetQueueImagerct_footpath_entry58 constexpr uint32_t GetQueueImage() const 59 { 60 return image + 51; 61 } GetPreviewImagerct_footpath_entry62 constexpr uint32_t GetPreviewImage() const 63 { 64 return image + 71; 65 } GetQueuePreviewImagerct_footpath_entry66 constexpr uint32_t GetQueuePreviewImage() const 67 { 68 // Editor-only paths usually lack queue images. In this case, use the main path image. 69 if (flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR) 70 { 71 return GetPreviewImage(); 72 } 73 74 return image + 72; 75 } GetRailingsImagerct_footpath_entry76 constexpr uint32_t GetRailingsImage() const 77 { 78 return image + 73; 79 } 80 }; 81 assert_struct_size(rct_footpath_entry, 13); 82 #pragma pack(pop) 83 84 struct PathSurfaceDescriptor 85 { 86 rct_string_id Name; 87 uint32_t Image; 88 uint32_t PreviewImage; 89 uint8_t Flags; 90 IsEditorOnlyPathSurfaceDescriptor91 inline constexpr bool IsEditorOnly() const 92 { 93 return Flags & FOOTPATH_ENTRY_FLAG_SHOW_ONLY_IN_SCENARIO_EDITOR; 94 } 95 }; 96 97 struct PathRailingsDescriptor 98 { 99 rct_string_id Name; 100 uint32_t PreviewImage; 101 uint32_t BridgeImage; 102 uint32_t RailingsImage; 103 RailingEntrySupportType SupportType; 104 colour_t SupportColour; 105 uint8_t Flags; 106 uint8_t ScrollingMode; 107 }; 108 109 using PathConstructFlags = uint8_t; 110 namespace PathConstructFlag 111 { 112 constexpr PathConstructFlags IsQueue = 1 << 0; 113 constexpr PathConstructFlags IsLegacyPathObject = 1 << 1; 114 } // namespace PathConstructFlag 115 116 struct FootpathSelection 117 { 118 ObjectEntryIndex LegacyPath = OBJECT_ENTRY_INDEX_NULL; 119 ObjectEntryIndex NormalSurface = OBJECT_ENTRY_INDEX_NULL; 120 ObjectEntryIndex QueueSurface = OBJECT_ENTRY_INDEX_NULL; 121 ObjectEntryIndex Railings = OBJECT_ENTRY_INDEX_NULL; 122 bool IsQueueSelected{}; 123 GetSelectedSurfaceFootpathSelection124 ObjectEntryIndex GetSelectedSurface() const 125 { 126 return IsQueueSelected ? QueueSurface : NormalSurface; 127 } 128 }; 129 130 struct ProvisionalFootpath 131 { 132 ObjectEntryIndex Type; 133 CoordsXYZ Position; 134 uint8_t Slope; 135 uint8_t Flags; 136 ObjectEntryIndex SurfaceIndex; 137 ObjectEntryIndex RailingsIndex; 138 PathConstructFlags ConstructFlags; 139 }; 140 141 // Masks for values stored in TileElement.type 142 enum 143 { 144 FOOTPATH_ELEMENT_TYPE_FLAG_IS_QUEUE = (1 << 0), 145 FOOTPATH_ELEMENT_TYPE_FLAG_IS_WIDE = (1 << 1), 146 FOOTPATH_ELEMENT_TYPE_DIRECTION_MASK = (1 << 6) | (1 << 7), 147 }; 148 149 // Masks and flags for values stored in TileElement.properties.path.type 150 enum 151 { 152 FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1), 153 FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2), 154 FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3), 155 FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), 156 }; 157 158 // Masks and flags for values stored in TileElement.properties.path.edges 159 enum 160 { 161 FOOTPATH_PROPERTIES_EDGES_EDGES_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3), 162 FOOTPATH_PROPERTIES_EDGES_CORNERS_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7), 163 }; 164 165 enum 166 { 167 FOOTPATH_ELEMENT_FLAGS2_IS_SLOPED = 1 << 0, 168 FOOTPATH_ELEMENT_FLAGS2_HAS_QUEUE_BANNER = (1 << 1), 169 FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_GHOST = (1 << 2), 170 FOOTPATH_ELEMENT_FLAGS2_BLOCKED_BY_VEHICLE = (1 << 3), 171 FOOTPATH_ELEMENT_FLAGS2_ADDITION_IS_BROKEN = (1 << 4), 172 FOOTPATH_ELEMENT_FLAGS2_LEGACY_PATH_ENTRY = (1 << 5), 173 }; 174 175 enum 176 { 177 RAILING_ENTRY_FLAG_HAS_SUPPORT_BASE_SPRITE = (1 << 0), 178 RAILING_ENTRY_FLAG_DRAW_PATH_OVER_SUPPORTS = (1 << 1), // When elevated 179 }; 180 181 enum 182 { 183 FOOTPATH_SEARCH_SUCCESS, 184 FOOTPATH_SEARCH_NOT_FOUND, 185 FOOTPATH_SEARCH_INCOMPLETE, 186 FOOTPATH_SEARCH_TOO_COMPLEX 187 }; 188 189 enum 190 { 191 SLOPE_IS_IRREGULAR_FLAG = (1 << 3), // Flag set in `DefaultPathSlope[]` and checked in `footpath_place_real` 192 RAISE_FOOTPATH_FLAG = (1 << 4) 193 }; 194 195 enum 196 { 197 FOOTPATH_CORNER_0 = (1 << 0), 198 FOOTPATH_CORNER_1 = (1 << 1), 199 FOOTPATH_CORNER_2 = (1 << 2), 200 FOOTPATH_CORNER_3 = (1 << 3), 201 }; 202 203 enum 204 { 205 FOOTPATH_CONNECTION_S = (1 << 0), 206 FOOTPATH_CONNECTION_NE = (1 << 1), 207 FOOTPATH_CONNECTION_W = (1 << 2), 208 FOOTPATH_CONNECTION_SE = (1 << 3), 209 FOOTPATH_CONNECTION_N = (1 << 4), 210 FOOTPATH_CONNECTION_SW = (1 << 5), 211 FOOTPATH_CONNECTION_E = (1 << 6), 212 FOOTPATH_CONNECTION_NW = (1 << 7), 213 }; 214 215 enum 216 { 217 FOOTPATH_CONNECTED_MAP_EDGE_IGNORE_QUEUES = (1 << 0), 218 FOOTPATH_CONNECTED_MAP_EDGE_UNOWN = (1 << 5), 219 FOOTPATH_CONNECTED_MAP_EDGE_IGNORE_NO_ENTRY = (1 << 7) 220 }; 221 222 extern FootpathSelection gFootpathSelection; 223 extern ProvisionalFootpath gProvisionalFootpath; 224 extern uint16_t gFootpathSelectedId; 225 extern CoordsXYZ gFootpathConstructFromPosition; 226 extern uint8_t gFootpathConstructSlope; 227 extern uint8_t gFootpathGroundFlags; 228 229 // Given a direction, this will return how to increase/decrease the x and y coordinates. 230 extern const CoordsXY DirectionOffsets[NumOrthogonalDirections]; 231 extern const CoordsXY BinUseOffsets[NumOrthogonalDirections]; 232 extern const CoordsXY BenchUseOffsets[NumOrthogonalDirections * 2]; 233 234 TileElement* map_get_footpath_element(const CoordsXYZ& coords); 235 void footpath_interrupt_peeps(const CoordsXYZ& footpathPos); 236 money32 footpath_remove(const CoordsXYZ& footpathLoc, int32_t flags); 237 money32 footpath_provisional_set( 238 ObjectEntryIndex type, ObjectEntryIndex railingsType, const CoordsXYZ& footpathLoc, int32_t slope, 239 PathConstructFlags constructFlags); 240 void footpath_provisional_remove(); 241 void footpath_provisional_update(); 242 CoordsXY footpath_get_coordinates_from_pos(const ScreenCoordsXY& screenCoords, int32_t* direction, TileElement** tileElement); 243 CoordsXY footpath_bridge_get_info_from_pos(const ScreenCoordsXY& screenCoords, int32_t* direction, TileElement** tileElement); 244 void footpath_remove_litter(const CoordsXYZ& footpathPos); 245 void footpath_connect_edges(const CoordsXY& footpathPos, TileElement* tileElement, int32_t flags); 246 void footpath_update_queue_chains(); 247 bool fence_in_the_way(const CoordsXYRangedZ& fencePos, int32_t direction); 248 void footpath_chain_ride_queue( 249 ride_id_t rideIndex, int32_t entranceIndex, const CoordsXY& footpathPos, TileElement* tileElement, int32_t direction); 250 void footpath_update_path_wide_flags(const CoordsXY& footpathPos); 251 bool footpath_is_blocked_by_vehicle(const TileCoordsXYZ& position); 252 253 int32_t footpath_is_connected_to_map_edge(const CoordsXYZ& footpathPos, int32_t direction, int32_t flags); 254 void footpath_remove_edges_at(const CoordsXY& footpathPos, TileElement* tileElement); 255 256 const FootpathObject* GetLegacyFootpathEntry(ObjectEntryIndex entryIndex); 257 const FootpathSurfaceObject* GetPathSurfaceEntry(ObjectEntryIndex entryIndex); 258 const FootpathRailingsObject* GetPathRailingsEntry(ObjectEntryIndex entryIndex); 259 260 void footpath_queue_chain_reset(); 261 void footpath_queue_chain_push(ride_id_t rideIndex); 262