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 "../world/Location.hpp" 14 #include "../world/ScenerySelection.h" 15 #include "TileElement.h" 16 17 #include <limits> 18 19 #define SCENERY_WITHER_AGE_THRESHOLD_1 0x28 20 #define SCENERY_WITHER_AGE_THRESHOLD_2 0x37 21 22 struct LargeSceneryText; 23 24 #pragma pack(push, 1) 25 26 struct SceneryEntryBase 27 { 28 rct_string_id name; 29 uint32_t image; 30 }; 31 32 struct rct_large_scenery_tile 33 { 34 int16_t x_offset; 35 int16_t y_offset; 36 int16_t z_offset; 37 uint8_t z_clearance; 38 // CCCC WWWW 0SS0 0000 39 uint16_t flags; 40 }; 41 assert_struct_size(rct_large_scenery_tile, 9); 42 43 enum 44 { 45 LARGE_SCENERY_TILE_FLAG_NO_SUPPORTS = 0x20, 46 LARGE_SCENERY_TILE_FLAG_ALLOW_SUPPORTS_ABOVE = 0x40, 47 }; 48 49 struct rct_large_scenery_text_glyph 50 { 51 uint8_t image_offset; 52 uint8_t width; 53 uint8_t height; 54 uint8_t pad_3; 55 }; 56 assert_struct_size(rct_large_scenery_text_glyph, 4); 57 58 struct rct_large_scenery_text 59 { 60 struct 61 { 62 int16_t x, y; 63 } offset[2]; // 0x0 64 uint16_t max_width; // 0x8 65 uint16_t pad_A; // 0xA 66 uint8_t flags; // 0xC 67 uint8_t num_images; // 0xD 68 rct_large_scenery_text_glyph glyphs[256]; // 0xE 69 }; 70 assert_struct_size(rct_large_scenery_text, 14 + 4 * 256); 71 72 enum LARGE_SCENERY_TEXT_FLAGS 73 { 74 LARGE_SCENERY_TEXT_FLAG_VERTICAL = (1 << 0), // 0x1 75 LARGE_SCENERY_TEXT_FLAG_TWO_LINE = (1 << 1), // 0x2 76 }; 77 78 struct LargeSceneryEntry : SceneryEntryBase 79 { 80 CursorID tool_id; 81 uint8_t flags; 82 int16_t price; 83 int16_t removal_price; 84 rct_large_scenery_tile* tiles; 85 ObjectEntryIndex scenery_tab_id; 86 uint8_t scrolling_mode; 87 LargeSceneryText* text; 88 uint32_t text_image; 89 }; 90 91 enum LARGE_SCENERY_FLAGS 92 { 93 LARGE_SCENERY_FLAG_HAS_PRIMARY_COLOUR = (1 << 0), // 0x1 94 LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR = (1 << 1), // 0x2 95 LARGE_SCENERY_FLAG_3D_TEXT = (1 << 2), // 0x4 96 LARGE_SCENERY_FLAG_ANIMATED = (1 << 3), // 0x8 97 LARGE_SCENERY_FLAG_PHOTOGENIC = (1 << 4), // 0x10 98 LARGE_SCENERY_FLAG_IS_TREE = (1 << 5), // 0x20 99 }; 100 101 enum WALL_SCENERY_FLAGS 102 { 103 WALL_SCENERY_HAS_PRIMARY_COLOUR = (1 << 0), // 0x1 104 WALL_SCENERY_HAS_GLASS = (1 << 1), // 0x2 105 WALL_SCENERY_CANT_BUILD_ON_SLOPE = (1 << 2), // 0x4 106 WALL_SCENERY_IS_DOUBLE_SIDED = (1 << 3), // 0x8 107 WALL_SCENERY_IS_DOOR = (1 << 4), // 0x10 108 WALL_SCENERY_LONG_DOOR_ANIMATION = (1 << 5), // 0x20 109 WALL_SCENERY_HAS_SECONDARY_COLOUR = (1 << 6), // 0x40 110 WALL_SCENERY_HAS_TERNARY_COLOUR = (1 << 7), // 0x80 111 }; 112 113 enum WALL_SCENERY_2_FLAGS 114 { 115 WALL_SCENERY_2_NO_SELECT_PRIMARY_COLOUR = (1 << 0), // 0x1 116 WALL_SCENERY_2_DOOR_SOUND_MASK = 0x6, 117 WALL_SCENERY_2_DOOR_SOUND_SHIFT = 1, 118 WALL_SCENERY_2_IS_OPAQUE = (1 << 3), // 0x8 119 WALL_SCENERY_2_ANIMATED = (1 << 4), // 0x10 120 }; 121 122 struct SmallSceneryEntry : SceneryEntryBase 123 { 124 uint32_t flags; 125 uint8_t height; 126 CursorID tool_id; 127 int16_t price; 128 int16_t removal_price; 129 uint8_t* frame_offsets; 130 uint16_t animation_delay; 131 uint16_t animation_mask; 132 uint16_t num_frames; 133 ObjectEntryIndex scenery_tab_id; 134 HasFlagSmallSceneryEntry135 constexpr bool HasFlag(const uint32_t _flags) const 136 { 137 return (flags & _flags) != 0; 138 } 139 }; 140 141 struct WallSceneryEntry : SceneryEntryBase 142 { 143 CursorID tool_id; 144 uint8_t flags; 145 uint8_t height; 146 uint8_t flags2; 147 int16_t price; 148 ObjectEntryIndex scenery_tab_id; 149 uint8_t scrolling_mode; 150 }; 151 enum class PathBitDrawType : uint8_t; 152 153 struct PathBitEntry : SceneryEntryBase 154 { 155 uint16_t flags; 156 PathBitDrawType draw_type; 157 CursorID tool_id; 158 int16_t price; 159 ObjectEntryIndex scenery_tab_id; 160 }; 161 162 struct BannerSceneryEntry : SceneryEntryBase 163 { 164 uint8_t scrolling_mode; 165 uint8_t flags; 166 int16_t price; 167 ObjectEntryIndex scenery_tab_id; 168 }; 169 170 #pragma pack(pop) 171 172 struct LargeSceneryText 173 { 174 CoordsXY offset[2]; 175 uint16_t max_width; 176 uint8_t flags; 177 uint16_t num_images; 178 rct_large_scenery_text_glyph glyphs[256]; 179 180 LargeSceneryText() = default; 181 LargeSceneryTextLargeSceneryText182 explicit LargeSceneryText(const rct_large_scenery_text& original) 183 { 184 for (size_t i = 0; i < std::size(original.offset); i++) 185 { 186 offset[i].x = original.offset[i].x; 187 offset[i].y = original.offset[i].y; 188 } 189 max_width = original.max_width; 190 flags = original.flags; 191 num_images = original.num_images; 192 for (size_t i = 0; i < std::size(original.glyphs); i++) 193 { 194 glyphs[i] = original.glyphs[i]; 195 } 196 } 197 }; 198 199 struct rct_scenery_group_entry 200 { 201 rct_string_id name; 202 uint32_t image; 203 ScenerySelection scenery_entries[0x80]; 204 uint8_t entry_count; 205 uint8_t priority; 206 uint32_t entertainer_costumes; 207 }; 208 209 enum 210 { 211 PATH_BIT_FLAG_IS_BIN = 1 << 0, 212 PATH_BIT_FLAG_IS_BENCH = 1 << 1, 213 PATH_BIT_FLAG_BREAKABLE = 1 << 2, 214 PATH_BIT_FLAG_LAMP = 1 << 3, 215 PATH_BIT_FLAG_JUMPING_FOUNTAIN_WATER = 1 << 4, 216 PATH_BIT_FLAG_JUMPING_FOUNTAIN_SNOW = 1 << 5, 217 PATH_BIT_FLAG_DONT_ALLOW_ON_QUEUE = 1 << 6, 218 PATH_BIT_FLAG_DONT_ALLOW_ON_SLOPE = 1 << 7, 219 PATH_BIT_FLAG_IS_QUEUE_SCREEN = 1 << 8 220 }; 221 222 enum class PathBitDrawType : uint8_t 223 { 224 Light, 225 Bin, 226 Bench, 227 JumpingFountain, 228 }; 229 230 enum 231 { 232 SCENERY_TYPE_SMALL, 233 SCENERY_TYPE_PATH_ITEM, 234 SCENERY_TYPE_WALL, 235 SCENERY_TYPE_LARGE, 236 SCENERY_TYPE_BANNER, 237 238 SCENERY_TYPE_COUNT, 239 }; 240 241 enum 242 { 243 SCENERY_GHOST_FLAG_0 = (1 << SCENERY_TYPE_SMALL), 244 SCENERY_GHOST_FLAG_1 = (1 << SCENERY_TYPE_PATH_ITEM), 245 SCENERY_GHOST_FLAG_2 = (1 << SCENERY_TYPE_WALL), 246 SCENERY_GHOST_FLAG_3 = (1 << SCENERY_TYPE_LARGE), 247 SCENERY_GHOST_FLAG_4 = (1 << SCENERY_TYPE_BANNER) 248 }; 249 250 enum 251 { 252 BANNER_ENTRY_FLAG_HAS_PRIMARY_COLOUR = (1 << 0), 253 }; 254 255 enum class ScatterToolDensity : uint8_t 256 { 257 LowDensity, 258 MediumDensity, 259 HighDensity 260 }; 261 262 extern uint8_t gSceneryQuadrant; 263 264 extern money32 gSceneryPlaceCost; 265 extern ScenerySelection gSceneryPlaceObject; 266 extern uint16_t gSceneryPlaceObjectEntryIndex; 267 extern int16_t gSceneryPlaceZ; 268 extern uint8_t gSceneryPlaceRotation; 269 270 extern uint8_t gSceneryGhostType; 271 extern CoordsXYZ gSceneryGhostPosition; 272 extern uint8_t gSceneryGhostWallRotation; 273 274 extern int16_t gSceneryShiftPressed; 275 extern int16_t gSceneryShiftPressX; 276 extern int16_t gSceneryShiftPressY; 277 extern int16_t gSceneryShiftPressZOffset; 278 279 extern int16_t gSceneryCtrlPressed; 280 extern int16_t gSceneryCtrlPressZ; 281 282 extern const CoordsXY SceneryQuadrantOffsets[]; 283 284 extern money64 gClearSceneryCost; 285 286 void init_scenery(); 287 void scenery_update_tile(const CoordsXY& sceneryPos); 288 void scenery_set_default_placement_configuration(); 289 void scenery_remove_ghost_tool_placement(); 290 291 WallSceneryEntry* get_wall_entry(ObjectEntryIndex entryIndex); 292 BannerSceneryEntry* get_banner_entry(ObjectEntryIndex entryIndex); 293 PathBitEntry* get_footpath_item_entry(ObjectEntryIndex entryIndex); 294 rct_scenery_group_entry* get_scenery_group_entry(ObjectEntryIndex entryIndex); 295 296 int32_t wall_entry_get_door_sound(const WallSceneryEntry* wallEntry); 297 298 bool IsSceneryAvailableToBuild(const ScenerySelection& item); 299 300 bool IsSceneryItemRestricted(const ScenerySelection& item); 301 void ClearRestrictedScenery(); 302 void RestrictAllMiscScenery(); 303 std::vector<ScenerySelection>& GetRestrictedScenery(); 304