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