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 // Structures shared between both RCT1 and RCT2.
13 
14 #include "../common.h"
15 #include "../object/Object.h"
16 #include "../ride/RideTypes.h"
17 
18 #include <string>
19 #include <string_view>
20 #include <vector>
21 
22 class ObjectList;
23 
24 using track_type_t = uint16_t;
25 using RCT12TrackType = uint8_t;
26 
27 constexpr uint8_t RCT2_STRING_FORMAT_ARG_START = 123;
28 constexpr uint8_t RCT2_STRING_FORMAT_ARG_END = 141;
29 constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_START = 142;
30 constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_END = 156;
31 
32 constexpr const uint8_t RCT12_MAX_RIDE_OBJECTS = 128;
33 
34 constexpr const uint8_t RCT12_MAX_RIDES_IN_PARK = 255;
35 constexpr const uint8_t RCT12_MAX_AWARDS = 4;
36 constexpr const uint8_t RCT12_MAX_NEWS_ITEMS = 61;
37 constexpr const uint8_t RCT12_MAX_STATIONS_PER_RIDE = 4;
38 constexpr const uint8_t RCT12_MAX_PEEP_SPAWNS = 2;
39 constexpr const uint8_t RCT12_MAX_PARK_ENTRANCES = 4;
40 // The number of elements in the patrol_areas array per staff member. Every bit in the array represents a 4x4 square.
41 // In RCT1, that's an 8-bit array. 8 * 128 = 1024 bits, which is also the number of 4x4 squares on a 128x128 map.
42 // For RCT2, it's a 32-bit array. 32 * 128 = 4096 bits, which is also the number of 4x4 squares on a 256x256 map.
43 constexpr const uint8_t RCT12_PATROL_AREA_SIZE = 128;
44 constexpr const uint8_t RCT12_STAFF_TYPE_COUNT = 4;
45 constexpr const uint8_t RCT12_NUM_COLOUR_SCHEMES = 4;
46 constexpr const uint8_t RCT12_MAX_VEHICLE_COLOURS = 32;
47 constexpr const uint8_t RCT12_SOUND_ID_NULL = 0xFF;
48 
49 constexpr const uint8_t RCT12_EXPENDITURE_TABLE_MONTH_COUNT = 16;
50 constexpr const uint8_t RCT12_EXPENDITURE_TYPE_COUNT = 14;
51 constexpr const uint8_t RCT12_FINANCE_GRAPH_SIZE = 128;
52 
53 constexpr const uint16_t RCT12_MAX_USER_STRINGS = 1024;
54 constexpr const uint8_t RCT12_USER_STRING_MAX_LENGTH = 32;
55 
56 constexpr const uint8_t RCT12_PEEP_MAX_THOUGHTS = 5;
57 
58 using RCT12RideId = uint8_t;
59 constexpr const RCT12RideId RCT12_RIDE_ID_NULL = 255;
60 constexpr const uint16_t RCT12_RIDE_MEASUREMENT_MAX_ITEMS = 4800;
61 
62 constexpr uint16_t const RCT12_MAX_INVERSIONS = 31;
63 constexpr uint16_t const RCT12_MAX_GOLF_HOLES = 31;
64 constexpr uint16_t const RCT12_MAX_HELICES = 31;
65 
66 constexpr uint8_t RCT12_BANNER_INDEX_NULL = std::numeric_limits<uint8_t>::max();
67 
68 constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_EDGE_STYLE_MASK = 0xE0;   // in RCT12TileElement.properties.surface.slope
69 constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK = 0x1F; // in RCT12TileElement.properties.surface.terrain
70 constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_TERRAIN_MASK = 0xE0;      // in RCT12TileElement.properties.surface.terrain
71 
72 constexpr const uint16_t RCT12_TILE_ELEMENT_LARGE_TYPE_MASK = 0x3FF;
73 
74 constexpr uint16_t const RCT12_XY8_UNDEFINED = 0xFFFF;
75 
76 using RCT12ObjectEntryIndex = uint8_t;
77 constexpr const RCT12ObjectEntryIndex RCT12_OBJECT_ENTRY_INDEX_NULL = 255;
78 
79 // Everything before this point has been researched
80 constexpr const uint32_t RCT12_RESEARCHED_ITEMS_SEPARATOR = 0xFFFFFFFF;
81 // Everything before this point and after separator still requires research
82 constexpr const uint32_t RCT12_RESEARCHED_ITEMS_END = 0xFFFFFFFE;
83 // Extra end of list entry. Leftover from RCT1.
84 constexpr const uint32_t RCT12_RESEARCHED_ITEMS_END_2 = 0xFFFFFFFD;
85 
86 constexpr const uint8_t RCT12_MAX_ELEMENT_HEIGHT = 255;
87 
88 constexpr const uint16_t RCT12_PEEP_SPAWN_UNDEFINED = 0xFFFF;
89 
90 constexpr const uint16_t RCT12VehicleTrackDirectionMask = 0b0000000000000011;
91 constexpr const uint16_t RCT12VehicleTrackTypeMask = 0b1111111111111100;
92 
93 constexpr const uint8_t RCT12PeepThoughtItemNone = std::numeric_limits<uint8_t>::max();
94 
95 constexpr const uint8_t RCT12GuestsInParkHistoryFactor = 20;
96 constexpr const uint8_t RCT12ParkHistoryUndefined = std::numeric_limits<uint8_t>::max();
97 
98 enum class RCT12TrackDesignVersion : uint8_t
99 {
100     TD4,
101     TD4_AA,
102     TD6,
103     unknown
104 };
105 
106 enum
107 {
108     RCT12_SURFACE_ELEMENT_TYPE_SURFACE_MASK = 0b00000011,
109     RCT12_SURFACE_ELEMENT_TYPE_EDGE_MASK = 0b01000000,
110 };
111 
112 enum
113 {
114     RCT12_TILE_ELEMENT_FLAG_GHOST = (1 << 4),
115     RCT12_TILE_ELEMENT_FLAG_BROKEN = (1 << 5),
116     RCT12_TILE_ELEMENT_FLAG_BLOCK_BRAKE_CLOSED = (1 << 5),
117     RCT12_TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE = (1 << 6),
118     RCT12_TILE_ELEMENT_FLAG_BLOCKED_BY_VEHICLE = (1 << 6),
119     RCT12_TILE_ELEMENT_FLAG_LARGE_SCENERY_ACCOUNTED = (1 << 6),
120     RCT12_TILE_ELEMENT_FLAG_LAST_TILE = (1 << 7)
121 };
122 
123 enum
124 {
125     RCT12_TRACK_ELEMENT_TYPE_FLAG_CHAIN_LIFT = 1 << 7,
126 };
127 
128 enum
129 {
130     RCT12_TRACK_ELEMENT_SEQUENCE_STATION_INDEX_MASK = 0b01110000,
131     RCT12_TRACK_ELEMENT_SEQUENCE_SEQUENCE_MASK = 0b00001111,
132     RCT12_TRACK_ELEMENT_SEQUENCE_TAKING_PHOTO_MASK = 0b11110000,
133 };
134 
135 enum
136 {
137     // Not anything to do with colour but uses
138     // that field in the tile element
139 
140     // Used for multi-dimension coaster
141     RCT12_TRACK_ELEMENT_COLOUR_FLAG_INVERTED = (1 << 2),
142 
143     // Used for giga coaster
144     RCT12_TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT = (1 << 3),
145 
146     RCT12_TRACK_ELEMENT_DOOR_A_MASK = 0b00011100,
147     RCT12_TRACK_ELEMENT_DOOR_B_MASK = 0b11100000,
148 };
149 
150 // Masks and flags for values stored in TileElement.properties.path.type
151 enum
152 {
153     RCT12_FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1),
154     RCT12_FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2),
155     RCT12_FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3),
156     RCT12_FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
157 };
158 
159 // Masks and flags for values stored in RCT12TileElement.properties.path.additions
160 enum
161 {
162     RCT12_FOOTPATH_PROPERTIES_ADDITIONS_TYPE_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
163     // The most significant bit in this mask will always be zero, since rides can only have 4 stations
164     RCT12_FOOTPATH_PROPERTIES_ADDITIONS_STATION_INDEX_MASK = (1 << 4) | (1 << 5) | (1 << 6),
165     RCT12_FOOTPATH_PROPERTIES_ADDITIONS_FLAG_GHOST = (1 << 7),
166 };
167 
168 enum
169 {
170     RCT12_STATION_STYLE_PLAIN,
171     RCT12_STATION_STYLE_WOODEN,
172     RCT12_STATION_STYLE_CANVAS_TENT,
173     RCT12_STATION_STYLE_CASTLE_GREY,
174     RCT12_STATION_STYLE_CASTLE_BROWN,
175     RCT12_STATION_STYLE_JUNGLE,
176     RCT12_STATION_STYLE_LOG_CABIN,
177     RCT12_STATION_STYLE_CLASSICAL,
178     RCT12_STATION_STYLE_ABSTRACT,
179     RCT12_STATION_STYLE_SNOW,
180     RCT12_STATION_STYLE_PAGODA,
181     RCT12_STATION_STYLE_SPACE,
182 
183     RCT12_STATION_STYLE_INVISIBLE, // Added by OpenRCT2
184 };
185 
186 enum
187 {
188     RCT12_SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE = 1 << 7,
189 };
190 
191 #pragma pack(push, 1)
192 
193 struct RCT12xy8
194 {
195     union
196     {
197         struct
198         {
199             uint8_t x, y;
200         };
201         uint16_t xy;
202     };
203 
IsNullRCT12xy8204     bool IsNull() const
205     {
206         return xy == RCT12_XY8_UNDEFINED;
207     }
208 
SetNullRCT12xy8209     void SetNull()
210     {
211         xy = RCT12_XY8_UNDEFINED;
212     }
213 };
214 assert_struct_size(RCT12xy8, 2);
215 
216 /* Maze Element entry   size: 0x04 */
217 struct rct_td46_maze_element
218 {
219     union
220     {
221         uint32_t all;
222         struct
223         {
224             int8_t x;
225             int8_t y;
226             union
227             {
228                 uint16_t maze_entry;
229                 struct
230                 {
231                     uint8_t direction;
232                     uint8_t type;
233                 };
234             };
235         };
236     };
237 };
238 assert_struct_size(rct_td46_maze_element, 0x04);
239 
240 /* Track Element entry  size: 0x02 */
241 struct rct_td46_track_element
242 {
243     uint8_t type;  // 0x00
244     uint8_t flags; // 0x01
245 };
246 assert_struct_size(rct_td46_track_element, 0x02);
247 
248 struct rct12_award
249 {
250     uint16_t time;
251     uint16_t type;
252 };
253 assert_struct_size(rct12_award, 4);
254 
255 /**
256  * A single news item / message.
257  * size: 0x10C
258  */
259 struct rct12_news_item
260 {
261     uint8_t Type;
262     uint8_t Flags;
263     uint32_t Assoc;
264     uint16_t Ticks;
265     uint16_t MonthYear;
266     uint8_t Day;
267     uint8_t pad_0B;
268     char Text[256];
269 };
270 assert_struct_size(rct12_news_item, 0x10C);
271 
272 struct rct12_xyzd8
273 {
274     uint8_t x, y, z, direction;
275 };
276 assert_struct_size(rct12_xyzd8, 4);
277 
278 struct rct12_peep_spawn
279 {
280     uint16_t x;
281     uint16_t y;
282     uint8_t z;
283     uint8_t direction;
284 };
285 assert_struct_size(rct12_peep_spawn, 6);
286 
287 enum class RCT12TileElementType : uint8_t
288 {
289     Surface = (0 << 2),
290     Path = (1 << 2),
291     Track = (2 << 2),
292     SmallScenery = (3 << 2),
293     Entrance = (4 << 2),
294     Wall = (5 << 2),
295     LargeScenery = (6 << 2),
296     Banner = (7 << 2),
297     Corrupt = (8 << 2),
298     EightCarsCorrupt14 = (14 << 2),
299     EightCarsCorrupt15 = (15 << 2),
300 };
301 struct RCT12SurfaceElement;
302 struct RCT12PathElement;
303 struct RCT12TrackElement;
304 struct RCT12SmallSceneryElement;
305 struct RCT12LargeSceneryElement;
306 struct RCT12WallElement;
307 struct RCT12EntranceElement;
308 struct RCT12BannerElement;
309 struct RCT12CorruptElement;
310 struct RCT12EightCarsCorruptElement14;
311 struct RCT12EightCarsCorruptElement15;
312 
313 struct RCT12TileElementBase
314 {
315     uint8_t type;             // 0
316     uint8_t flags;            // 1. Upper nibble: flags. Lower nibble: occupied quadrants (one bit per quadrant).
317     uint8_t base_height;      // 2
318     uint8_t clearance_height; // 3
319     uint8_t GetType() const;
320     uint8_t GetDirection() const;
321     void SetDirection(uint8_t direction);
322 
323     uint8_t GetOccupiedQuadrants() const;
324     void SetOccupiedQuadrants(uint8_t quadrants);
325 
326     bool IsLastForTile() const;
327     void SetLastForTile(bool on);
328     bool IsGhost() const;
329     void SetGhost(bool isGhost);
330 };
331 /**
332  * Map element structure
333  * size: 0x08
334  */
335 struct RCT12TileElement : public RCT12TileElementBase
336 {
337     uint8_t pad_04[4];
asRCT12TileElement338     template<typename TType, RCT12TileElementType TClass> const TType* as() const
339     {
340         return static_cast<RCT12TileElementType>(GetType()) == TClass ? reinterpret_cast<const TType*>(this) : nullptr;
341     }
asRCT12TileElement342     template<typename TType, RCT12TileElementType TClass> TType* as()
343     {
344         return static_cast<RCT12TileElementType>(GetType()) == TClass ? reinterpret_cast<TType*>(this) : nullptr;
345     }
346 
AsSurfaceRCT12TileElement347     const RCT12SurfaceElement* AsSurface() const
348     {
349         return as<RCT12SurfaceElement, RCT12TileElementType::Surface>();
350     }
AsSurfaceRCT12TileElement351     RCT12SurfaceElement* AsSurface()
352     {
353         return as<RCT12SurfaceElement, RCT12TileElementType::Surface>();
354     }
AsPathRCT12TileElement355     const RCT12PathElement* AsPath() const
356     {
357         return as<RCT12PathElement, RCT12TileElementType::Path>();
358     }
AsPathRCT12TileElement359     RCT12PathElement* AsPath()
360     {
361         return as<RCT12PathElement, RCT12TileElementType::Path>();
362     }
AsTrackRCT12TileElement363     const RCT12TrackElement* AsTrack() const
364     {
365         return as<RCT12TrackElement, RCT12TileElementType::Track>();
366     }
AsTrackRCT12TileElement367     RCT12TrackElement* AsTrack()
368     {
369         return as<RCT12TrackElement, RCT12TileElementType::Track>();
370     }
AsSmallSceneryRCT12TileElement371     const RCT12SmallSceneryElement* AsSmallScenery() const
372     {
373         return as<RCT12SmallSceneryElement, RCT12TileElementType::SmallScenery>();
374     }
AsSmallSceneryRCT12TileElement375     RCT12SmallSceneryElement* AsSmallScenery()
376     {
377         return as<RCT12SmallSceneryElement, RCT12TileElementType::SmallScenery>();
378     }
AsLargeSceneryRCT12TileElement379     const RCT12LargeSceneryElement* AsLargeScenery() const
380     {
381         return as<RCT12LargeSceneryElement, RCT12TileElementType::LargeScenery>();
382     }
AsLargeSceneryRCT12TileElement383     RCT12LargeSceneryElement* AsLargeScenery()
384     {
385         return as<RCT12LargeSceneryElement, RCT12TileElementType::LargeScenery>();
386     }
AsWallRCT12TileElement387     const RCT12WallElement* AsWall() const
388     {
389         return as<RCT12WallElement, RCT12TileElementType::Wall>();
390     }
AsWallRCT12TileElement391     RCT12WallElement* AsWall()
392     {
393         return as<RCT12WallElement, RCT12TileElementType::Wall>();
394     }
AsEntranceRCT12TileElement395     const RCT12EntranceElement* AsEntrance() const
396     {
397         return as<RCT12EntranceElement, RCT12TileElementType::Entrance>();
398     }
AsEntranceRCT12TileElement399     RCT12EntranceElement* AsEntrance()
400     {
401         return as<RCT12EntranceElement, RCT12TileElementType::Entrance>();
402     }
AsBannerRCT12TileElement403     const RCT12BannerElement* AsBanner() const
404     {
405         return as<RCT12BannerElement, RCT12TileElementType::Banner>();
406     }
AsBannerRCT12TileElement407     RCT12BannerElement* AsBanner()
408     {
409         return as<RCT12BannerElement, RCT12TileElementType::Banner>();
410     }
411     void ClearAs(uint8_t newType);
412     uint8_t GetBannerIndex();
413 };
414 assert_struct_size(RCT12TileElement, 8);
415 struct RCT12SurfaceElement : RCT12TileElementBase
416 {
417 private:
418     uint8_t slope;        // 4 0xE0 Edge Style, 0x1F Slope
419     uint8_t terrain;      // 5 0xE0 Terrain Style, 0x1F Water height
420     uint8_t grass_length; // 6
421     uint8_t ownership;    // 7
422 public:
423     uint8_t GetSlope() const;
424     uint32_t GetSurfaceStyle() const;
425     uint32_t GetEdgeStyle() const;
426     uint8_t GetGrassLength() const;
427     uint8_t GetOwnership() const;
428     uint32_t GetWaterHeight() const;
429     uint8_t GetParkFences() const;
430     bool HasTrackThatNeedsWater() const;
431 
432     void SetSlope(uint8_t newSlope);
433     void SetSurfaceStyle(uint32_t newStyle);
434     void SetEdgeStyle(uint32_t newStyle);
435     void SetGrassLength(uint8_t newLength);
436     void SetOwnership(uint8_t newOwnership);
437     void SetWaterHeight(uint32_t newWaterHeight);
438     void SetParkFences(uint8_t newParkFences);
439     void SetHasTrackThatNeedsWater(bool on);
440 };
441 assert_struct_size(RCT12SurfaceElement, 8);
442 struct RCT12PathElement : RCT12TileElementBase
443 {
444 private:
445     uint8_t entryIndex; // 4, 0xF0 Path type, 0x08 Ride sign, 0x04 Set when path is sloped, 0x03 Rotation
446     uint8_t additions;  // 5, 0bGSSSAAAA: G = Ghost, S = station index, A = addition (0 means no addition)
447     uint8_t edges;      // 6
448     union
449     {
450         uint8_t additionStatus; // 7
451         uint8_t rideIndex;
452     };
453 
454 public:
455     RCT12ObjectEntryIndex GetEntryIndex() const;
456     uint8_t GetQueueBannerDirection() const;
457     bool IsSloped() const;
458     uint8_t GetSlopeDirection() const;
459     uint8_t GetRideIndex() const;
460     uint8_t GetStationIndex() const;
461     bool IsWide() const;
462     bool IsQueue() const;
463     bool HasQueueBanner() const;
464     uint8_t GetEdges() const;
465     uint8_t GetCorners() const;
466     uint8_t GetAddition() const;
467     bool AdditionIsGhost() const;
468     uint8_t GetAdditionStatus() const;
469     uint8_t GetRCT1PathType() const;
470     uint8_t GetRCT1SupportType() const;
471 
472     void SetPathEntryIndex(RCT12ObjectEntryIndex newIndex);
473     void SetQueueBannerDirection(uint8_t direction);
474     void SetSloped(bool isSloped);
475     void SetSlopeDirection(uint8_t newSlope);
476     void SetRideIndex(uint8_t newRideIndex);
477     void SetStationIndex(uint8_t newStationIndex);
478     void SetWide(bool isWide);
479     void SetIsQueue(bool isQueue);
480     void SetHasQueueBanner(bool hasQueueBanner);
481     void SetEdges(uint8_t newEdges);
482     void SetCorners(uint8_t newCorners);
483     void SetAddition(uint8_t newAddition);
484     void SetAdditionIsGhost(bool isGhost);
485     void SetAdditionStatus(uint8_t newStatus);
486 
487     bool IsBroken() const;
488     void SetIsBroken(bool isBroken);
489 
490     bool IsBlockedByVehicle() const;
491     void SetIsBlockedByVehicle(bool isBlocked);
492 };
493 assert_struct_size(RCT12PathElement, 8);
494 struct RCT12TrackElement : RCT12TileElementBase
495 {
496 private:
497     uint8_t trackType; // 4
498     union
499     {
500         struct
501         {
502             // The lower 4 bits are the track sequence.
503             // The upper 4 bits are either station bits or on-ride photo bits.
504             //
505             // Station bits:
506             // - Bit 8 marks green light
507             // - Bit 5-7 are station index.
508             //
509             // On-ride photo bits:
510             // - Bits 7 and 8 are never set
511             // - Bits 5 and 6 are set when a vehicle triggers the on-ride photo and act like a countdown from 3.
512             // - If any of the bits 5-8 are set, the game counts it as a photo being taken.
513             uint8_t sequence; // 5.
514             uint8_t colour;   // 6
515         };
516         uint16_t mazeEntry; // 5
517     };
518     uint8_t rideIndex; // 7
519 public:
520     uint8_t GetTrackType() const;
521     uint8_t GetSequenceIndex() const;
522     uint8_t GetRideIndex() const;
523     uint8_t GetColourScheme() const;
524     uint8_t GetStationIndex() const;
525     bool HasChain() const;
526     bool HasCableLift() const;
527     bool IsInverted() const;
528     uint8_t GetBrakeBoosterSpeed() const;
529     bool HasGreenLight() const;
530     uint8_t GetSeatRotation() const;
531     uint16_t GetMazeEntry() const;
532     uint8_t GetPhotoTimeout() const;
533     // RCT1 feature, reintroduced by OpenRCT2. See https://github.com/OpenRCT2/OpenRCT2/issues/7059
534     uint8_t GetDoorAState() const;
535     uint8_t GetDoorBState() const;
536     void SetDoorAState(uint8_t newState);
537     void SetDoorBState(uint8_t newState);
538 
539     void SetTrackType(uint8_t newEntryIndex);
540     void SetSequenceIndex(uint8_t newSequenceIndex);
541     void SetRideIndex(uint8_t newRideIndex);
542     void SetColourScheme(uint8_t newColourScheme);
543     void SetStationIndex(uint8_t newStationIndex);
544     void SetHasChain(bool on);
545     void SetHasCableLift(bool on);
546     void SetInverted(bool inverted);
547     bool BlockBrakeClosed() const;
548     void SetBlockBrakeClosed(bool isClosed);
549     void SetBrakeBoosterSpeed(uint8_t speed);
550     void SetHasGreenLight(uint8_t greenLight);
551     void SetSeatRotation(uint8_t newSeatRotation);
552     void SetMazeEntry(uint16_t newMazeEntry);
553     void SetPhotoTimeout(uint8_t newValue);
554 
555     bool IsIndestructible() const;
556     void SetIsIndestructible(bool isIndestructible);
557 };
558 assert_struct_size(RCT12TrackElement, 8);
559 struct RCT12SmallSceneryElement : RCT12TileElementBase
560 {
561 private:
562     uint8_t entryIndex; // 4
563     uint8_t age;        // 5
564     uint8_t colour_1;   // 6
565     uint8_t colour_2;   // 7
566 public:
567     RCT12ObjectEntryIndex GetEntryIndex() const;
568     uint8_t GetAge() const;
569     uint8_t GetSceneryQuadrant() const;
570     colour_t GetPrimaryColour() const;
571     colour_t GetSecondaryColour() const;
572     bool NeedsSupports() const;
573 
574     void SetEntryIndex(RCT12ObjectEntryIndex newIndex);
575     void SetAge(uint8_t newAge);
576     void SetSceneryQuadrant(uint8_t newQuadrant);
577     void SetPrimaryColour(colour_t colour);
578     void SetSecondaryColour(colour_t colour);
579     void SetNeedsSupports();
580 };
581 assert_struct_size(RCT12SmallSceneryElement, 8);
582 struct RCT12LargeSceneryElement : RCT12TileElementBase
583 {
584 private:
585     uint16_t entryIndex; // 4
586     uint8_t colour[2];   // 6
587 public:
588     uint32_t GetEntryIndex() const;
589     uint16_t GetSequenceIndex() const;
590     colour_t GetPrimaryColour() const;
591     colour_t GetSecondaryColour() const;
592     uint8_t GetBannerIndex() const;
593 
594     void SetEntryIndex(uint32_t newIndex);
595     void SetSequenceIndex(uint16_t sequence);
596     void SetPrimaryColour(colour_t colour);
597     void SetSecondaryColour(colour_t colour);
598     void SetBannerIndex(uint8_t newIndex);
599 };
600 assert_struct_size(RCT12LargeSceneryElement, 8);
601 struct RCT12WallElement : RCT12TileElementBase
602 {
603 private:
604     uint8_t entryIndex; // 4
605     union
606     {
607         uint8_t colour_3;     // 5
608         uint8_t banner_index; // 5
609     };
610     uint8_t colour_1;  // 6 0b_2221_1111 2 = colour_2 (uses flags for rest of colour2), 1 = colour_1
611     uint8_t animation; // 7 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used)
612 public:
613     RCT12ObjectEntryIndex GetEntryIndex() const;
614     uint8_t GetSlope() const;
615     colour_t GetPrimaryColour() const;
616     colour_t GetSecondaryColour() const;
617     colour_t GetTertiaryColour() const;
618     uint8_t GetAnimationFrame() const;
619     uint8_t GetBannerIndex() const;
620     bool IsAcrossTrack() const;
621     bool AnimationIsBackwards() const;
622     int32_t GetRCT1WallType(int32_t edge) const;
623     colour_t GetRCT1WallColour() const;
624     uint8_t GetRCT1Slope() const;
625 
626     void SetEntryIndex(RCT12ObjectEntryIndex newIndex);
627     void SetSlope(uint8_t newslope);
628     void SetPrimaryColour(colour_t newColour);
629     void SetSecondaryColour(colour_t newColour);
630     void SetTertiaryColour(colour_t newColour);
631     void SetAnimationFrame(uint8_t frameNum);
632     void SetBannerIndex(uint8_t newIndex);
633     void SetAcrossTrack(bool acrossTrack);
634     void SetAnimationIsBackwards(bool isBackwards);
635 };
636 assert_struct_size(RCT12WallElement, 8);
637 struct RCT12EntranceElement : RCT12TileElementBase
638 {
639 private:
640     uint8_t entranceType; // 4
641     uint8_t index;        // 5. 0bUSSS????, S = station index.
642     uint8_t pathType;     // 6
643     uint8_t rideIndex;    // 7
644 public:
645     uint8_t GetEntranceType() const;
646     uint8_t GetRideIndex() const;
647     uint8_t GetStationIndex() const;
648     uint8_t GetSequenceIndex() const;
649     uint8_t GetPathType() const;
650 
651     void SetEntranceType(uint8_t newType);
652     void SetRideIndex(uint8_t newRideIndex);
653     void SetStationIndex(uint8_t stationIndex);
654     void SetSequenceIndex(uint8_t newSequenceIndex);
655     void SetPathType(uint8_t newPathType);
656 };
657 assert_struct_size(RCT12EntranceElement, 8);
658 struct RCT12BannerElement : RCT12TileElementBase
659 {
660 private:
661     uint8_t index;        // 4
662     uint8_t position;     // 5
663     uint8_t AllowedEdges; // 6
664 #pragma clang diagnostic push
665 #pragma clang diagnostic ignored "-Wunused-private-field"
666     uint8_t unused; // 7
667 #pragma clang diagnostic pop
668 public:
669     uint8_t GetIndex() const;
670     uint8_t GetPosition() const;
671     uint8_t GetAllowedEdges() const;
672 
673     void SetIndex(uint8_t newIndex);
674     void SetPosition(uint8_t newPosition);
675     void SetAllowedEdges(uint8_t newEdges);
676 };
677 assert_struct_size(RCT12BannerElement, 8);
678 
679 struct RCT12CorruptElement : RCT12TileElementBase
680 {
681     uint8_t pad[4];
682 };
683 assert_struct_size(RCT12CorruptElement, 8);
684 
685 struct RCT12EightCarsCorruptElement14 : RCT12TileElementBase
686 {
687     uint8_t pad[4];
688 };
689 assert_struct_size(RCT12EightCarsCorruptElement14, 8);
690 
691 struct RCT12EightCarsCorruptElement15 : RCT12TileElementBase
692 {
693     uint8_t pad[4];
694 };
695 assert_struct_size(RCT12EightCarsCorruptElement15, 8);
696 
697 // Offset into sprite_lists_head and sprite_lists_count
698 enum class RCT12EntityLinkListOffset : uint8_t
699 {
700     Free = 0,
701     TrainHead = 1 * sizeof(uint16_t),
702     Peep = 2 * sizeof(uint16_t),
703     Misc = 3 * sizeof(uint16_t),
704     Litter = 4 * sizeof(uint16_t),
705     Vehicle = 5 * sizeof(uint16_t),
706 };
707 
708 enum class RCT12SpriteIdentifier : uint8_t
709 {
710     Vehicle = 0,
711     Peep = 1,
712     Misc = 2,
713     Litter = 3,
714     Null = 255
715 };
716 
717 enum class RCT12MiscEntityType : uint8_t
718 {
719     SteamParticle,
720     MoneyEffect,
721     CrashedVehicleParticle,
722     ExplosionCloud,
723     CrashSplash,
724     ExplosionFlare,
725     JumpingFountainWater,
726     Balloon,
727     Duck,
728     JumpingFountainSnow
729 };
730 
731 enum class RCT12PeepType : uint8_t
732 {
733     Guest,
734     Staff,
735 
736     Invalid = 0xFF
737 };
738 
739 struct RCT12SpriteBase
740 {
741     RCT12SpriteIdentifier sprite_identifier;           // 0x00
742     uint8_t type;                                      // 0x01
743     uint16_t next_in_quadrant;                         // 0x02
744     uint16_t next;                                     // 0x04
745     uint16_t previous;                                 // 0x06
746     RCT12EntityLinkListOffset linked_list_type_offset; // 0x08
747     uint8_t sprite_height_negative;                    // 0x09
748     uint16_t sprite_index;                             // 0x0A
749     uint16_t flags;                                    // 0x0C
750     int16_t x;                                         // 0x0E
751     int16_t y;                                         // 0x10
752     int16_t z;                                         // 0x12
753     uint8_t sprite_width;                              // 0x14
754     uint8_t sprite_height_positive;                    // 0x15
755     int16_t sprite_left;                               // 0x16
756     int16_t sprite_top;                                // 0x18
757     int16_t sprite_right;                              // 0x1A
758     int16_t sprite_bottom;                             // 0x1C
759     uint8_t sprite_direction;                          // 0x1E
760 };
761 assert_struct_size(RCT12SpriteBase, 0x1F);
762 
763 struct RCT12SpriteBalloon : RCT12SpriteBase
764 {
765     uint8_t pad_1F[0x24 - 0x1F];
766     uint16_t popped;      // 0x24
767     uint8_t time_to_move; // 0x26
768     uint8_t frame;        // 0x27
769     uint8_t pad_28[4];
770     uint8_t colour; // 0x2C
771 };
772 assert_struct_size(RCT12SpriteBalloon, 0x2D);
773 
774 struct RCT12SpriteDuck : RCT12SpriteBase
775 {
776     uint8_t pad_1F[0x26 - 0x1F];
777     uint16_t frame; // 0x26
778     uint8_t pad_28[0x30 - 0x28];
779     int16_t target_x; // 0x30
780     int16_t target_y; // 0x32
781     uint8_t pad_34[0x14];
782     uint8_t state; // 0x48
783 };
784 assert_struct_size(RCT12SpriteDuck, 0x49);
785 
786 struct RCT12SpriteLitter : RCT12SpriteBase
787 {
788     uint8_t pad_1F[0x24 - 0x1F];
789     uint32_t creationTick; // 0x24
790 };
791 assert_struct_size(RCT12SpriteLitter, 0x28);
792 
793 struct RCT12SpriteParticle : RCT12SpriteBase
794 {
795     uint8_t pad_1F[0x26 - 0x1F];
796     uint16_t frame; // 0x26
797 };
798 assert_struct_size(RCT12SpriteParticle, 0x28);
799 
800 struct RCT12SpriteJumpingFountain : RCT12SpriteBase
801 {
802     uint8_t pad_1F[0x26 - 0x1F];
803     uint8_t num_ticks_alive; // 0x26
804     uint8_t frame;           // 0x27
805     uint8_t pad_28[0x2F - 0x28];
806     uint8_t fountain_flags; // 0x2F
807     int16_t target_x;       // 0x30
808     int16_t target_y;       // 0x32
809     uint8_t pad_34[0x46 - 0x34];
810     uint16_t iteration; // 0x46
811 };
812 assert_struct_size(RCT12SpriteJumpingFountain, 0x48);
813 
814 struct RCT12SpriteMoneyEffect : RCT12SpriteBase
815 {
816     uint8_t pad_1F[0x24 - 0x1F];
817     uint16_t move_delay;   // 0x24
818     uint8_t num_movements; // 0x26
819     uint8_t vertical;
820     money32 value; // 0x28
821     uint8_t pad_2C[0x44 - 0x2C];
822     int16_t offset_x; // 0x44
823     uint16_t wiggle;  // 0x46
824 };
825 assert_struct_size(RCT12SpriteMoneyEffect, 0x48);
826 
827 struct RCT12SpriteCrashedVehicleParticle : RCT12SpriteBase
828 {
829     uint8_t pad_1F[0x24 - 0x1F];
830     uint16_t time_to_live; // 0x24
831     uint16_t frame;        // 0x26
832     uint8_t pad_28[0x2C - 0x28];
833     uint8_t colour[2];            // 0x2C
834     uint16_t crashed_sprite_base; // 0x2E
835     int16_t velocity_x;           // 0x30
836     int16_t velocity_y;           // 0x32
837     int16_t velocity_z;           // 0x34
838     uint8_t pad_36[0x38 - 0x36];
839     int32_t acceleration_x; // 0x38
840     int32_t acceleration_y; // 0x3C
841     int32_t acceleration_z; // 0x40
842 };
843 assert_struct_size(RCT12SpriteCrashedVehicleParticle, 0x44);
844 
845 struct RCT12SpriteCrashSplash : RCT12SpriteBase
846 {
847     uint8_t pad_1F[0x26 - 0x1F];
848     uint16_t frame; // 0x26
849 };
850 assert_struct_size(RCT12SpriteCrashSplash, 0x28);
851 
852 struct RCT12SpriteSteamParticle : RCT12SpriteBase
853 {
854     uint8_t pad_1F[0x24 - 0x1F];
855     uint16_t time_to_move; // 0x24
856     uint16_t frame;        // 0x26
857 };
858 assert_struct_size(RCT12SpriteSteamParticle, 0x28);
859 
860 struct RCT12PeepThought
861 {
862     uint8_t type;
863     uint8_t item;
864     uint8_t freshness;
865     uint8_t fresh_timeout;
866 };
867 assert_struct_size(RCT12PeepThought, 4);
868 
869 struct RCT12RideMeasurement
870 {
871     uint8_t ride_index;                                 // 0x0000
872     uint8_t flags;                                      // 0x0001
873     uint32_t last_use_tick;                             // 0x0002
874     uint16_t num_items;                                 // 0x0006
875     uint16_t current_item;                              // 0x0008
876     uint8_t vehicle_index;                              // 0x000A
877     uint8_t current_station;                            // 0x000B
878     int8_t vertical[RCT12_RIDE_MEASUREMENT_MAX_ITEMS];  // 0x000C
879     int8_t lateral[RCT12_RIDE_MEASUREMENT_MAX_ITEMS];   // 0x12CC
880     uint8_t velocity[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x258C
881     uint8_t altitude[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x384C
882 };
883 assert_struct_size(RCT12RideMeasurement, 0x4B0C);
884 
885 struct RCT12Banner
886 {
887     RCT12ObjectEntryIndex type;
888     uint8_t flags;            // 0x01
889     rct_string_id string_idx; // 0x02
890     union
891     {
892         uint8_t colour;     // 0x04
893         uint8_t ride_index; // 0x04
894     };
895     uint8_t text_colour; // 0x05
896     uint8_t x;           // 0x06
897     uint8_t y;           // 0x07
898 };
899 assert_struct_size(RCT12Banner, 8);
900 
901 struct RCT12MapAnimation
902 {
903     uint8_t baseZ;
904     uint8_t type;
905     uint16_t x;
906     uint16_t y;
907 };
908 assert_struct_size(RCT12MapAnimation, 6);
909 
910 struct RCT12ResearchItem
911 {
912     // Bit 16 (0: scenery entry, 1: ride entry)
913     union
914     {
915         uint32_t rawValue;
916         struct
917         {
918             RCT12ObjectEntryIndex entryIndex;
919             uint8_t baseRideType;
920             uint8_t type; // 0: scenery entry, 1: ride entry
921             uint8_t flags;
922         };
923     };
924     uint8_t category;
925 
926     bool IsInventedEndMarker() const;
927     bool IsRandomEndMarker() const;
928     bool IsUninventedEndMarker() const;
929 };
930 assert_struct_size(RCT12ResearchItem, 5);
931 
932 #pragma pack(pop)
933 
934 ObjectEntryIndex RCTEntryIndexToOpenRCT2EntryIndex(const RCT12ObjectEntryIndex index);
935 RCT12ObjectEntryIndex OpenRCT2EntryIndexToRCTEntryIndex(const ObjectEntryIndex index);
936 ride_id_t RCT12RideIdToOpenRCT2RideId(const RCT12RideId rideId);
937 RCT12RideId OpenRCT2RideIdToRCT12RideId(const ride_id_t rideId);
938 bool IsLikelyUTF8(std::string_view s);
939 std::string RCT12RemoveFormattingUTF8(std::string_view s);
940 std::string ConvertFormattedStringToOpenRCT2(std::string_view buffer);
941 std::string ConvertFormattedStringToRCT2(std::string_view buffer, size_t maxLength);
942 std::string GetTruncatedRCT2String(std::string_view src, size_t maxLength);
943 track_type_t RCT12FlatTrackTypeToOpenRCT2(RCT12TrackType origTrackType);
944 RCT12TrackType OpenRCT2FlatTrackTypeToRCT12(track_type_t origTrackType);
945 std::string_view GetStationIdentifierFromStyle(uint8_t style);
946 std::optional<uint8_t> GetStyleFromMusicIdentifier(std::string_view identifier);
947 
948 static constexpr money32 RCT12_COMPANY_VALUE_ON_FAILED_OBJECTIVE = 0x80000001;
949 
950 money64 RCT12CompletedCompanyValueToOpenRCT2(money32 origValue);
951 money32 OpenRCT2CompletedCompanyValueToRCT12(money64 origValue);
952 
RCT12GetRideTypesBeenOn(T * srcPeep)953 template<typename T> std::vector<uint16_t> RCT12GetRideTypesBeenOn(T* srcPeep)
954 {
955     std::vector<uint16_t> ridesTypesBeenOn;
956     for (uint16_t i = 0; i < RCT12_MAX_RIDE_OBJECTS; i++)
957     {
958         if (srcPeep->ride_types_been_on[i / 8] & (1 << (i % 8)))
959         {
960             ridesTypesBeenOn.push_back(i);
961         }
962     }
963     return ridesTypesBeenOn;
964 }
RCT12GetRidesBeenOn(T * srcPeep)965 template<typename T> std::vector<ride_id_t> RCT12GetRidesBeenOn(T* srcPeep)
966 {
967     std::vector<ride_id_t> ridesBeenOn;
968     for (uint16_t i = 0; i < RCT12_MAX_RIDES_IN_PARK; i++)
969     {
970         if (srcPeep->rides_been_on[i / 8] & (1 << (i % 8)))
971         {
972             ridesBeenOn.push_back(static_cast<ride_id_t>(i));
973         }
974     }
975     return ridesBeenOn;
976 }
977