mirror of https://github.com/OpenRCT2/OpenRCT2.git
979 lines
30 KiB
C++
979 lines
30 KiB
C++
/*****************************************************************************
|
|
* Copyright (c) 2014-2020 OpenRCT2 developers
|
|
*
|
|
* For a complete list of all authors, please refer to contributors.md
|
|
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
|
|
*
|
|
* OpenRCT2 is licensed under the GNU General Public License version 3.
|
|
*****************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
// Structures shared between both RCT1 and RCT2.
|
|
|
|
#include "../common.h"
|
|
#include "../object/Object.h"
|
|
#include "../ride/RideTypes.h"
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
|
|
class ObjectList;
|
|
|
|
using track_type_t = uint16_t;
|
|
using RCT12TrackType = uint8_t;
|
|
|
|
constexpr uint8_t RCT2_STRING_FORMAT_ARG_START = 123;
|
|
constexpr uint8_t RCT2_STRING_FORMAT_ARG_END = 141;
|
|
constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_START = 142;
|
|
constexpr uint8_t RCT2_STRING_FORMAT_COLOUR_END = 156;
|
|
|
|
constexpr const uint8_t RCT12_MAX_RIDE_OBJECTS = 128;
|
|
|
|
constexpr const uint8_t RCT12_MAX_RIDES_IN_PARK = 255;
|
|
constexpr const uint8_t RCT12_MAX_AWARDS = 4;
|
|
constexpr const uint8_t RCT12_MAX_NEWS_ITEMS = 61;
|
|
constexpr const uint8_t RCT12_MAX_STATIONS_PER_RIDE = 4;
|
|
constexpr const uint8_t RCT12_MAX_PEEP_SPAWNS = 2;
|
|
constexpr const uint8_t RCT12_MAX_PARK_ENTRANCES = 4;
|
|
// The number of elements in the patrol_areas array per staff member. Every bit in the array represents a 4x4 square.
|
|
// In RCT1, that's an 8-bit array. 8 * 128 = 1024 bits, which is also the number of 4x4 squares on a 128x128 map.
|
|
// For RCT2, it's a 32-bit array. 32 * 128 = 4096 bits, which is also the number of 4x4 squares on a 256x256 map.
|
|
constexpr const uint8_t RCT12_PATROL_AREA_SIZE = 128;
|
|
constexpr const uint8_t RCT12_STAFF_TYPE_COUNT = 4;
|
|
constexpr const uint8_t RCT12_NUM_COLOUR_SCHEMES = 4;
|
|
constexpr const uint8_t RCT12_MAX_VEHICLE_COLOURS = 32;
|
|
constexpr const uint8_t RCT12_SOUND_ID_NULL = 0xFF;
|
|
|
|
constexpr const uint8_t RCT12_EXPENDITURE_TABLE_MONTH_COUNT = 16;
|
|
constexpr const uint8_t RCT12_EXPENDITURE_TYPE_COUNT = 14;
|
|
constexpr const uint8_t RCT12_FINANCE_GRAPH_SIZE = 128;
|
|
|
|
constexpr const uint16_t RCT12_MAX_USER_STRINGS = 1024;
|
|
constexpr const uint8_t RCT12_USER_STRING_MAX_LENGTH = 32;
|
|
|
|
constexpr const uint8_t RCT12_PEEP_MAX_THOUGHTS = 5;
|
|
|
|
using RCT12RideId = uint8_t;
|
|
constexpr const RCT12RideId RCT12_RIDE_ID_NULL = 255;
|
|
constexpr const uint16_t RCT12_RIDE_MEASUREMENT_MAX_ITEMS = 4800;
|
|
|
|
constexpr uint16_t const RCT12_MAX_INVERSIONS = 31;
|
|
constexpr uint16_t const RCT12_MAX_GOLF_HOLES = 31;
|
|
constexpr uint16_t const RCT12_MAX_HELICES = 31;
|
|
|
|
constexpr uint8_t RCT12_BANNER_INDEX_NULL = std::numeric_limits<uint8_t>::max();
|
|
|
|
constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_EDGE_STYLE_MASK = 0xE0; // in RCT12TileElement.properties.surface.slope
|
|
constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_WATER_HEIGHT_MASK = 0x1F; // in RCT12TileElement.properties.surface.terrain
|
|
constexpr const uint8_t RCT12_TILE_ELEMENT_SURFACE_TERRAIN_MASK = 0xE0; // in RCT12TileElement.properties.surface.terrain
|
|
|
|
constexpr const uint16_t RCT12_TILE_ELEMENT_LARGE_TYPE_MASK = 0x3FF;
|
|
|
|
constexpr uint16_t const RCT12_XY8_UNDEFINED = 0xFFFF;
|
|
|
|
using RCT12ObjectEntryIndex = uint8_t;
|
|
constexpr const RCT12ObjectEntryIndex RCT12_OBJECT_ENTRY_INDEX_NULL = 255;
|
|
|
|
// Everything before this point has been researched
|
|
constexpr const uint32_t RCT12_RESEARCHED_ITEMS_SEPARATOR = 0xFFFFFFFF;
|
|
// Everything before this point and after separator still requires research
|
|
constexpr const uint32_t RCT12_RESEARCHED_ITEMS_END = 0xFFFFFFFE;
|
|
// Extra end of list entry. Leftover from RCT1.
|
|
constexpr const uint32_t RCT12_RESEARCHED_ITEMS_END_2 = 0xFFFFFFFD;
|
|
|
|
constexpr const uint8_t RCT12_MAX_ELEMENT_HEIGHT = 255;
|
|
|
|
constexpr const uint16_t RCT12_PEEP_SPAWN_UNDEFINED = 0xFFFF;
|
|
|
|
constexpr const uint16_t RCT12VehicleTrackDirectionMask = 0b0000000000000011;
|
|
constexpr const uint16_t RCT12VehicleTrackTypeMask = 0b1111111111111100;
|
|
|
|
constexpr const uint8_t RCT12PeepThoughtItemNone = std::numeric_limits<uint8_t>::max();
|
|
|
|
constexpr const uint8_t RCT12GuestsInParkHistoryFactor = 20;
|
|
constexpr const uint8_t RCT12ParkHistoryUndefined = std::numeric_limits<uint8_t>::max();
|
|
|
|
enum class RCT12TrackDesignVersion : uint8_t
|
|
{
|
|
TD4,
|
|
TD4_AA,
|
|
TD6,
|
|
unknown
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_SURFACE_ELEMENT_TYPE_SURFACE_MASK = 0b00000011,
|
|
RCT12_SURFACE_ELEMENT_TYPE_EDGE_MASK = 0b01000000,
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_TILE_ELEMENT_FLAG_GHOST = (1 << 4),
|
|
RCT12_TILE_ELEMENT_FLAG_BROKEN = (1 << 5),
|
|
RCT12_TILE_ELEMENT_FLAG_BLOCK_BRAKE_CLOSED = (1 << 5),
|
|
RCT12_TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE = (1 << 6),
|
|
RCT12_TILE_ELEMENT_FLAG_BLOCKED_BY_VEHICLE = (1 << 6),
|
|
RCT12_TILE_ELEMENT_FLAG_LARGE_SCENERY_ACCOUNTED = (1 << 6),
|
|
RCT12_TILE_ELEMENT_FLAG_LAST_TILE = (1 << 7)
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_TRACK_ELEMENT_TYPE_FLAG_CHAIN_LIFT = 1 << 7,
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_TRACK_ELEMENT_SEQUENCE_STATION_INDEX_MASK = 0b01110000,
|
|
RCT12_TRACK_ELEMENT_SEQUENCE_SEQUENCE_MASK = 0b00001111,
|
|
RCT12_TRACK_ELEMENT_SEQUENCE_TAKING_PHOTO_MASK = 0b11110000,
|
|
};
|
|
|
|
enum
|
|
{
|
|
// Not anything to do with colour but uses
|
|
// that field in the tile element
|
|
|
|
// Used for multi-dimension coaster
|
|
RCT12_TRACK_ELEMENT_COLOUR_FLAG_INVERTED = (1 << 2),
|
|
|
|
// Used for giga coaster
|
|
RCT12_TRACK_ELEMENT_COLOUR_FLAG_CABLE_LIFT = (1 << 3),
|
|
|
|
RCT12_TRACK_ELEMENT_DOOR_A_MASK = 0b00011100,
|
|
RCT12_TRACK_ELEMENT_DOOR_B_MASK = 0b11100000,
|
|
};
|
|
|
|
// Masks and flags for values stored in TileElement.properties.path.type
|
|
enum
|
|
{
|
|
RCT12_FOOTPATH_PROPERTIES_SLOPE_DIRECTION_MASK = (1 << 0) | (1 << 1),
|
|
RCT12_FOOTPATH_PROPERTIES_FLAG_IS_SLOPED = (1 << 2),
|
|
RCT12_FOOTPATH_PROPERTIES_FLAG_HAS_QUEUE_BANNER = (1 << 3),
|
|
RCT12_FOOTPATH_PROPERTIES_TYPE_MASK = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7),
|
|
};
|
|
|
|
// Masks and flags for values stored in RCT12TileElement.properties.path.additions
|
|
enum
|
|
{
|
|
RCT12_FOOTPATH_PROPERTIES_ADDITIONS_TYPE_MASK = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3),
|
|
// The most significant bit in this mask will always be zero, since rides can only have 4 stations
|
|
RCT12_FOOTPATH_PROPERTIES_ADDITIONS_STATION_INDEX_MASK = (1 << 4) | (1 << 5) | (1 << 6),
|
|
RCT12_FOOTPATH_PROPERTIES_ADDITIONS_FLAG_GHOST = (1 << 7),
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_STATION_STYLE_PLAIN,
|
|
RCT12_STATION_STYLE_WOODEN,
|
|
RCT12_STATION_STYLE_CANVAS_TENT,
|
|
RCT12_STATION_STYLE_CASTLE_GREY,
|
|
RCT12_STATION_STYLE_CASTLE_BROWN,
|
|
RCT12_STATION_STYLE_JUNGLE,
|
|
RCT12_STATION_STYLE_LOG_CABIN,
|
|
RCT12_STATION_STYLE_CLASSICAL,
|
|
RCT12_STATION_STYLE_ABSTRACT,
|
|
RCT12_STATION_STYLE_SNOW,
|
|
RCT12_STATION_STYLE_PAGODA,
|
|
RCT12_STATION_STYLE_SPACE,
|
|
|
|
RCT12_STATION_STYLE_INVISIBLE, // Added by OpenRCT2
|
|
};
|
|
|
|
enum
|
|
{
|
|
RCT12_SPRITE_FLAGS_IS_CRASHED_VEHICLE_SPRITE = 1 << 7,
|
|
};
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
struct RCT12xy8
|
|
{
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
uint8_t x, y;
|
|
};
|
|
uint16_t xy;
|
|
};
|
|
|
|
bool IsNull() const
|
|
{
|
|
return xy == RCT12_XY8_UNDEFINED;
|
|
}
|
|
|
|
void SetNull()
|
|
{
|
|
xy = RCT12_XY8_UNDEFINED;
|
|
}
|
|
};
|
|
assert_struct_size(RCT12xy8, 2);
|
|
|
|
/* Maze Element entry size: 0x04 */
|
|
struct rct_td46_maze_element
|
|
{
|
|
union
|
|
{
|
|
uint32_t all;
|
|
struct
|
|
{
|
|
int8_t x;
|
|
int8_t y;
|
|
union
|
|
{
|
|
uint16_t maze_entry;
|
|
struct
|
|
{
|
|
uint8_t direction;
|
|
uint8_t type;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
assert_struct_size(rct_td46_maze_element, 0x04);
|
|
|
|
/* Track Element entry size: 0x02 */
|
|
struct rct_td46_track_element
|
|
{
|
|
uint8_t type; // 0x00
|
|
uint8_t flags; // 0x01
|
|
};
|
|
assert_struct_size(rct_td46_track_element, 0x02);
|
|
|
|
struct rct12_award
|
|
{
|
|
uint16_t time;
|
|
uint16_t type;
|
|
};
|
|
assert_struct_size(rct12_award, 4);
|
|
|
|
/**
|
|
* A single news item / message.
|
|
* size: 0x10C
|
|
*/
|
|
struct rct12_news_item
|
|
{
|
|
uint8_t Type;
|
|
uint8_t Flags;
|
|
uint32_t Assoc;
|
|
uint16_t Ticks;
|
|
uint16_t MonthYear;
|
|
uint8_t Day;
|
|
uint8_t pad_0B;
|
|
char Text[256];
|
|
};
|
|
assert_struct_size(rct12_news_item, 0x10C);
|
|
|
|
struct rct12_xyzd8
|
|
{
|
|
uint8_t x, y, z, direction;
|
|
};
|
|
assert_struct_size(rct12_xyzd8, 4);
|
|
|
|
struct rct12_peep_spawn
|
|
{
|
|
uint16_t x;
|
|
uint16_t y;
|
|
uint8_t z;
|
|
uint8_t direction;
|
|
};
|
|
assert_struct_size(rct12_peep_spawn, 6);
|
|
|
|
enum class RCT12TileElementType : uint8_t
|
|
{
|
|
Surface = (0 << 2),
|
|
Path = (1 << 2),
|
|
Track = (2 << 2),
|
|
SmallScenery = (3 << 2),
|
|
Entrance = (4 << 2),
|
|
Wall = (5 << 2),
|
|
LargeScenery = (6 << 2),
|
|
Banner = (7 << 2),
|
|
Corrupt = (8 << 2),
|
|
EightCarsCorrupt14 = (14 << 2),
|
|
EightCarsCorrupt15 = (15 << 2),
|
|
};
|
|
struct RCT12SurfaceElement;
|
|
struct RCT12PathElement;
|
|
struct RCT12TrackElement;
|
|
struct RCT12SmallSceneryElement;
|
|
struct RCT12LargeSceneryElement;
|
|
struct RCT12WallElement;
|
|
struct RCT12EntranceElement;
|
|
struct RCT12BannerElement;
|
|
struct RCT12CorruptElement;
|
|
struct RCT12EightCarsCorruptElement14;
|
|
struct RCT12EightCarsCorruptElement15;
|
|
|
|
struct RCT12TileElementBase
|
|
{
|
|
uint8_t type; // 0
|
|
uint8_t flags; // 1. Upper nibble: flags. Lower nibble: occupied quadrants (one bit per quadrant).
|
|
uint8_t base_height; // 2
|
|
uint8_t clearance_height; // 3
|
|
uint8_t GetType() const;
|
|
uint8_t GetDirection() const;
|
|
void SetDirection(uint8_t direction);
|
|
|
|
uint8_t GetOccupiedQuadrants() const;
|
|
void SetOccupiedQuadrants(uint8_t quadrants);
|
|
|
|
bool IsLastForTile() const;
|
|
void SetLastForTile(bool on);
|
|
bool IsGhost() const;
|
|
void SetGhost(bool isGhost);
|
|
};
|
|
/**
|
|
* Map element structure
|
|
* size: 0x08
|
|
*/
|
|
struct RCT12TileElement : public RCT12TileElementBase
|
|
{
|
|
uint8_t pad_04[4];
|
|
template<typename TType, RCT12TileElementType TClass> const TType* as() const
|
|
{
|
|
return static_cast<RCT12TileElementType>(GetType()) == TClass ? reinterpret_cast<const TType*>(this) : nullptr;
|
|
}
|
|
template<typename TType, RCT12TileElementType TClass> TType* as()
|
|
{
|
|
return static_cast<RCT12TileElementType>(GetType()) == TClass ? reinterpret_cast<TType*>(this) : nullptr;
|
|
}
|
|
|
|
const RCT12SurfaceElement* AsSurface() const
|
|
{
|
|
return as<RCT12SurfaceElement, RCT12TileElementType::Surface>();
|
|
}
|
|
RCT12SurfaceElement* AsSurface()
|
|
{
|
|
return as<RCT12SurfaceElement, RCT12TileElementType::Surface>();
|
|
}
|
|
const RCT12PathElement* AsPath() const
|
|
{
|
|
return as<RCT12PathElement, RCT12TileElementType::Path>();
|
|
}
|
|
RCT12PathElement* AsPath()
|
|
{
|
|
return as<RCT12PathElement, RCT12TileElementType::Path>();
|
|
}
|
|
const RCT12TrackElement* AsTrack() const
|
|
{
|
|
return as<RCT12TrackElement, RCT12TileElementType::Track>();
|
|
}
|
|
RCT12TrackElement* AsTrack()
|
|
{
|
|
return as<RCT12TrackElement, RCT12TileElementType::Track>();
|
|
}
|
|
const RCT12SmallSceneryElement* AsSmallScenery() const
|
|
{
|
|
return as<RCT12SmallSceneryElement, RCT12TileElementType::SmallScenery>();
|
|
}
|
|
RCT12SmallSceneryElement* AsSmallScenery()
|
|
{
|
|
return as<RCT12SmallSceneryElement, RCT12TileElementType::SmallScenery>();
|
|
}
|
|
const RCT12LargeSceneryElement* AsLargeScenery() const
|
|
{
|
|
return as<RCT12LargeSceneryElement, RCT12TileElementType::LargeScenery>();
|
|
}
|
|
RCT12LargeSceneryElement* AsLargeScenery()
|
|
{
|
|
return as<RCT12LargeSceneryElement, RCT12TileElementType::LargeScenery>();
|
|
}
|
|
const RCT12WallElement* AsWall() const
|
|
{
|
|
return as<RCT12WallElement, RCT12TileElementType::Wall>();
|
|
}
|
|
RCT12WallElement* AsWall()
|
|
{
|
|
return as<RCT12WallElement, RCT12TileElementType::Wall>();
|
|
}
|
|
const RCT12EntranceElement* AsEntrance() const
|
|
{
|
|
return as<RCT12EntranceElement, RCT12TileElementType::Entrance>();
|
|
}
|
|
RCT12EntranceElement* AsEntrance()
|
|
{
|
|
return as<RCT12EntranceElement, RCT12TileElementType::Entrance>();
|
|
}
|
|
const RCT12BannerElement* AsBanner() const
|
|
{
|
|
return as<RCT12BannerElement, RCT12TileElementType::Banner>();
|
|
}
|
|
RCT12BannerElement* AsBanner()
|
|
{
|
|
return as<RCT12BannerElement, RCT12TileElementType::Banner>();
|
|
}
|
|
void ClearAs(uint8_t newType);
|
|
uint8_t GetBannerIndex();
|
|
};
|
|
assert_struct_size(RCT12TileElement, 8);
|
|
struct RCT12SurfaceElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t slope; // 4 0xE0 Edge Style, 0x1F Slope
|
|
uint8_t terrain; // 5 0xE0 Terrain Style, 0x1F Water height
|
|
uint8_t grass_length; // 6
|
|
uint8_t ownership; // 7
|
|
public:
|
|
uint8_t GetSlope() const;
|
|
uint32_t GetSurfaceStyle() const;
|
|
uint32_t GetEdgeStyle() const;
|
|
uint8_t GetGrassLength() const;
|
|
uint8_t GetOwnership() const;
|
|
uint32_t GetWaterHeight() const;
|
|
uint8_t GetParkFences() const;
|
|
bool HasTrackThatNeedsWater() const;
|
|
|
|
void SetSlope(uint8_t newSlope);
|
|
void SetSurfaceStyle(uint32_t newStyle);
|
|
void SetEdgeStyle(uint32_t newStyle);
|
|
void SetGrassLength(uint8_t newLength);
|
|
void SetOwnership(uint8_t newOwnership);
|
|
void SetWaterHeight(uint32_t newWaterHeight);
|
|
void SetParkFences(uint8_t newParkFences);
|
|
void SetHasTrackThatNeedsWater(bool on);
|
|
};
|
|
assert_struct_size(RCT12SurfaceElement, 8);
|
|
struct RCT12PathElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t entryIndex; // 4, 0xF0 Path type, 0x08 Ride sign, 0x04 Set when path is sloped, 0x03 Rotation
|
|
uint8_t additions; // 5, 0bGSSSAAAA: G = Ghost, S = station index, A = addition (0 means no addition)
|
|
uint8_t edges; // 6
|
|
union
|
|
{
|
|
uint8_t additionStatus; // 7
|
|
uint8_t rideIndex;
|
|
};
|
|
|
|
public:
|
|
RCT12ObjectEntryIndex GetEntryIndex() const;
|
|
uint8_t GetQueueBannerDirection() const;
|
|
bool IsSloped() const;
|
|
uint8_t GetSlopeDirection() const;
|
|
uint8_t GetRideIndex() const;
|
|
uint8_t GetStationIndex() const;
|
|
bool IsWide() const;
|
|
bool IsQueue() const;
|
|
bool HasQueueBanner() const;
|
|
uint8_t GetEdges() const;
|
|
uint8_t GetCorners() const;
|
|
uint8_t GetAddition() const;
|
|
bool AdditionIsGhost() const;
|
|
uint8_t GetAdditionStatus() const;
|
|
uint8_t GetRCT1PathType() const;
|
|
uint8_t GetRCT1SupportType() const;
|
|
|
|
void SetPathEntryIndex(RCT12ObjectEntryIndex newIndex);
|
|
void SetQueueBannerDirection(uint8_t direction);
|
|
void SetSloped(bool isSloped);
|
|
void SetSlopeDirection(uint8_t newSlope);
|
|
void SetRideIndex(uint8_t newRideIndex);
|
|
void SetStationIndex(uint8_t newStationIndex);
|
|
void SetWide(bool isWide);
|
|
void SetIsQueue(bool isQueue);
|
|
void SetHasQueueBanner(bool hasQueueBanner);
|
|
void SetEdges(uint8_t newEdges);
|
|
void SetCorners(uint8_t newCorners);
|
|
void SetAddition(uint8_t newAddition);
|
|
void SetAdditionIsGhost(bool isGhost);
|
|
void SetAdditionStatus(uint8_t newStatus);
|
|
|
|
bool IsBroken() const;
|
|
void SetIsBroken(bool isBroken);
|
|
|
|
bool IsBlockedByVehicle() const;
|
|
void SetIsBlockedByVehicle(bool isBlocked);
|
|
};
|
|
assert_struct_size(RCT12PathElement, 8);
|
|
struct RCT12TrackElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t trackType; // 4
|
|
union
|
|
{
|
|
struct
|
|
{
|
|
// The lower 4 bits are the track sequence.
|
|
// The upper 4 bits are either station bits or on-ride photo bits.
|
|
//
|
|
// Station bits:
|
|
// - Bit 8 marks green light
|
|
// - Bit 5-7 are station index.
|
|
//
|
|
// On-ride photo bits:
|
|
// - Bits 7 and 8 are never set
|
|
// - Bits 5 and 6 are set when a vehicle triggers the on-ride photo and act like a countdown from 3.
|
|
// - If any of the bits 5-8 are set, the game counts it as a photo being taken.
|
|
uint8_t sequence; // 5.
|
|
uint8_t colour; // 6
|
|
};
|
|
uint16_t mazeEntry; // 5
|
|
};
|
|
uint8_t rideIndex; // 7
|
|
public:
|
|
uint8_t GetTrackType() const;
|
|
uint8_t GetSequenceIndex() const;
|
|
uint8_t GetRideIndex() const;
|
|
uint8_t GetColourScheme() const;
|
|
uint8_t GetStationIndex() const;
|
|
bool HasChain() const;
|
|
bool HasCableLift() const;
|
|
bool IsInverted() const;
|
|
uint8_t GetBrakeBoosterSpeed() const;
|
|
bool HasGreenLight() const;
|
|
uint8_t GetSeatRotation() const;
|
|
uint16_t GetMazeEntry() const;
|
|
uint8_t GetPhotoTimeout() const;
|
|
// RCT1 feature, reintroduced by OpenRCT2. See https://github.com/OpenRCT2/OpenRCT2/issues/7059
|
|
uint8_t GetDoorAState() const;
|
|
uint8_t GetDoorBState() const;
|
|
void SetDoorAState(uint8_t newState);
|
|
void SetDoorBState(uint8_t newState);
|
|
|
|
void SetTrackType(uint8_t newEntryIndex);
|
|
void SetSequenceIndex(uint8_t newSequenceIndex);
|
|
void SetRideIndex(uint8_t newRideIndex);
|
|
void SetColourScheme(uint8_t newColourScheme);
|
|
void SetStationIndex(uint8_t newStationIndex);
|
|
void SetHasChain(bool on);
|
|
void SetHasCableLift(bool on);
|
|
void SetInverted(bool inverted);
|
|
bool BlockBrakeClosed() const;
|
|
void SetBlockBrakeClosed(bool isClosed);
|
|
void SetBrakeBoosterSpeed(uint8_t speed);
|
|
void SetHasGreenLight(uint8_t greenLight);
|
|
void SetSeatRotation(uint8_t newSeatRotation);
|
|
void SetMazeEntry(uint16_t newMazeEntry);
|
|
void SetPhotoTimeout(uint8_t newValue);
|
|
|
|
bool IsIndestructible() const;
|
|
void SetIsIndestructible(bool isIndestructible);
|
|
};
|
|
assert_struct_size(RCT12TrackElement, 8);
|
|
struct RCT12SmallSceneryElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t entryIndex; // 4
|
|
uint8_t age; // 5
|
|
uint8_t colour_1; // 6
|
|
uint8_t colour_2; // 7
|
|
public:
|
|
RCT12ObjectEntryIndex GetEntryIndex() const;
|
|
uint8_t GetAge() const;
|
|
uint8_t GetSceneryQuadrant() const;
|
|
colour_t GetPrimaryColour() const;
|
|
colour_t GetSecondaryColour() const;
|
|
bool NeedsSupports() const;
|
|
|
|
void SetEntryIndex(RCT12ObjectEntryIndex newIndex);
|
|
void SetAge(uint8_t newAge);
|
|
void SetSceneryQuadrant(uint8_t newQuadrant);
|
|
void SetPrimaryColour(colour_t colour);
|
|
void SetSecondaryColour(colour_t colour);
|
|
void SetNeedsSupports();
|
|
};
|
|
assert_struct_size(RCT12SmallSceneryElement, 8);
|
|
struct RCT12LargeSceneryElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint16_t entryIndex; // 4
|
|
uint8_t colour[2]; // 6
|
|
public:
|
|
uint32_t GetEntryIndex() const;
|
|
uint16_t GetSequenceIndex() const;
|
|
colour_t GetPrimaryColour() const;
|
|
colour_t GetSecondaryColour() const;
|
|
uint8_t GetBannerIndex() const;
|
|
|
|
void SetEntryIndex(uint32_t newIndex);
|
|
void SetSequenceIndex(uint16_t sequence);
|
|
void SetPrimaryColour(colour_t colour);
|
|
void SetSecondaryColour(colour_t colour);
|
|
void SetBannerIndex(uint8_t newIndex);
|
|
};
|
|
assert_struct_size(RCT12LargeSceneryElement, 8);
|
|
struct RCT12WallElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t entryIndex; // 4
|
|
union
|
|
{
|
|
uint8_t colour_3; // 5
|
|
uint8_t banner_index; // 5
|
|
};
|
|
uint8_t colour_1; // 6 0b_2221_1111 2 = colour_2 (uses flags for rest of colour2), 1 = colour_1
|
|
uint8_t animation; // 7 0b_dfff_ft00 d = direction, f = frame num, t = across track flag (not used)
|
|
public:
|
|
RCT12ObjectEntryIndex GetEntryIndex() const;
|
|
uint8_t GetSlope() const;
|
|
colour_t GetPrimaryColour() const;
|
|
colour_t GetSecondaryColour() const;
|
|
colour_t GetTertiaryColour() const;
|
|
uint8_t GetAnimationFrame() const;
|
|
uint8_t GetBannerIndex() const;
|
|
bool IsAcrossTrack() const;
|
|
bool AnimationIsBackwards() const;
|
|
int32_t GetRCT1WallType(int32_t edge) const;
|
|
colour_t GetRCT1WallColour() const;
|
|
uint8_t GetRCT1Slope() const;
|
|
|
|
void SetEntryIndex(RCT12ObjectEntryIndex newIndex);
|
|
void SetSlope(uint8_t newslope);
|
|
void SetPrimaryColour(colour_t newColour);
|
|
void SetSecondaryColour(colour_t newColour);
|
|
void SetTertiaryColour(colour_t newColour);
|
|
void SetAnimationFrame(uint8_t frameNum);
|
|
void SetBannerIndex(uint8_t newIndex);
|
|
void SetAcrossTrack(bool acrossTrack);
|
|
void SetAnimationIsBackwards(bool isBackwards);
|
|
};
|
|
assert_struct_size(RCT12WallElement, 8);
|
|
struct RCT12EntranceElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t entranceType; // 4
|
|
uint8_t index; // 5. 0bUSSS????, S = station index.
|
|
uint8_t pathType; // 6
|
|
uint8_t rideIndex; // 7
|
|
public:
|
|
uint8_t GetEntranceType() const;
|
|
uint8_t GetRideIndex() const;
|
|
uint8_t GetStationIndex() const;
|
|
uint8_t GetSequenceIndex() const;
|
|
uint8_t GetPathType() const;
|
|
|
|
void SetEntranceType(uint8_t newType);
|
|
void SetRideIndex(uint8_t newRideIndex);
|
|
void SetStationIndex(uint8_t stationIndex);
|
|
void SetSequenceIndex(uint8_t newSequenceIndex);
|
|
void SetPathType(uint8_t newPathType);
|
|
};
|
|
assert_struct_size(RCT12EntranceElement, 8);
|
|
struct RCT12BannerElement : RCT12TileElementBase
|
|
{
|
|
private:
|
|
uint8_t index; // 4
|
|
uint8_t position; // 5
|
|
uint8_t AllowedEdges; // 6
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wunused-private-field"
|
|
uint8_t unused; // 7
|
|
#pragma clang diagnostic pop
|
|
public:
|
|
uint8_t GetIndex() const;
|
|
uint8_t GetPosition() const;
|
|
uint8_t GetAllowedEdges() const;
|
|
|
|
void SetIndex(uint8_t newIndex);
|
|
void SetPosition(uint8_t newPosition);
|
|
void SetAllowedEdges(uint8_t newEdges);
|
|
};
|
|
assert_struct_size(RCT12BannerElement, 8);
|
|
|
|
struct RCT12CorruptElement : RCT12TileElementBase
|
|
{
|
|
uint8_t pad[4];
|
|
};
|
|
assert_struct_size(RCT12CorruptElement, 8);
|
|
|
|
struct RCT12EightCarsCorruptElement14 : RCT12TileElementBase
|
|
{
|
|
uint8_t pad[4];
|
|
};
|
|
assert_struct_size(RCT12EightCarsCorruptElement14, 8);
|
|
|
|
struct RCT12EightCarsCorruptElement15 : RCT12TileElementBase
|
|
{
|
|
uint8_t pad[4];
|
|
};
|
|
assert_struct_size(RCT12EightCarsCorruptElement15, 8);
|
|
|
|
// Offset into sprite_lists_head and sprite_lists_count
|
|
enum class RCT12EntityLinkListOffset : uint8_t
|
|
{
|
|
Free = 0,
|
|
TrainHead = 1 * sizeof(uint16_t),
|
|
Peep = 2 * sizeof(uint16_t),
|
|
Misc = 3 * sizeof(uint16_t),
|
|
Litter = 4 * sizeof(uint16_t),
|
|
Vehicle = 5 * sizeof(uint16_t),
|
|
};
|
|
|
|
enum class RCT12SpriteIdentifier : uint8_t
|
|
{
|
|
Vehicle = 0,
|
|
Peep = 1,
|
|
Misc = 2,
|
|
Litter = 3,
|
|
Null = 255
|
|
};
|
|
|
|
enum class RCT12MiscEntityType : uint8_t
|
|
{
|
|
SteamParticle,
|
|
MoneyEffect,
|
|
CrashedVehicleParticle,
|
|
ExplosionCloud,
|
|
CrashSplash,
|
|
ExplosionFlare,
|
|
JumpingFountainWater,
|
|
Balloon,
|
|
Duck,
|
|
JumpingFountainSnow
|
|
};
|
|
|
|
enum class RCT12PeepType : uint8_t
|
|
{
|
|
Guest,
|
|
Staff,
|
|
|
|
Invalid = 0xFF
|
|
};
|
|
|
|
struct RCT12SpriteBase
|
|
{
|
|
RCT12SpriteIdentifier sprite_identifier; // 0x00
|
|
uint8_t type; // 0x01
|
|
uint16_t next_in_quadrant; // 0x02
|
|
uint16_t next; // 0x04
|
|
uint16_t previous; // 0x06
|
|
RCT12EntityLinkListOffset linked_list_type_offset; // 0x08
|
|
uint8_t sprite_height_negative; // 0x09
|
|
uint16_t sprite_index; // 0x0A
|
|
uint16_t flags; // 0x0C
|
|
int16_t x; // 0x0E
|
|
int16_t y; // 0x10
|
|
int16_t z; // 0x12
|
|
uint8_t sprite_width; // 0x14
|
|
uint8_t sprite_height_positive; // 0x15
|
|
int16_t sprite_left; // 0x16
|
|
int16_t sprite_top; // 0x18
|
|
int16_t sprite_right; // 0x1A
|
|
int16_t sprite_bottom; // 0x1C
|
|
uint8_t sprite_direction; // 0x1E
|
|
};
|
|
assert_struct_size(RCT12SpriteBase, 0x1F);
|
|
|
|
struct RCT12SpriteBalloon : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x24 - 0x1F];
|
|
uint16_t popped; // 0x24
|
|
uint8_t time_to_move; // 0x26
|
|
uint8_t frame; // 0x27
|
|
uint8_t pad_28[4];
|
|
uint8_t colour; // 0x2C
|
|
};
|
|
assert_struct_size(RCT12SpriteBalloon, 0x2D);
|
|
|
|
struct RCT12SpriteDuck : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x26 - 0x1F];
|
|
uint16_t frame; // 0x26
|
|
uint8_t pad_28[0x30 - 0x28];
|
|
int16_t target_x; // 0x30
|
|
int16_t target_y; // 0x32
|
|
uint8_t pad_34[0x14];
|
|
uint8_t state; // 0x48
|
|
};
|
|
assert_struct_size(RCT12SpriteDuck, 0x49);
|
|
|
|
struct RCT12SpriteLitter : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x24 - 0x1F];
|
|
uint32_t creationTick; // 0x24
|
|
};
|
|
assert_struct_size(RCT12SpriteLitter, 0x28);
|
|
|
|
struct RCT12SpriteParticle : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x26 - 0x1F];
|
|
uint16_t frame; // 0x26
|
|
};
|
|
assert_struct_size(RCT12SpriteParticle, 0x28);
|
|
|
|
struct RCT12SpriteJumpingFountain : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x26 - 0x1F];
|
|
uint8_t num_ticks_alive; // 0x26
|
|
uint8_t frame; // 0x27
|
|
uint8_t pad_28[0x2F - 0x28];
|
|
uint8_t fountain_flags; // 0x2F
|
|
int16_t target_x; // 0x30
|
|
int16_t target_y; // 0x32
|
|
uint8_t pad_34[0x46 - 0x34];
|
|
uint16_t iteration; // 0x46
|
|
};
|
|
assert_struct_size(RCT12SpriteJumpingFountain, 0x48);
|
|
|
|
struct RCT12SpriteMoneyEffect : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x24 - 0x1F];
|
|
uint16_t move_delay; // 0x24
|
|
uint8_t num_movements; // 0x26
|
|
uint8_t vertical;
|
|
money32 value; // 0x28
|
|
uint8_t pad_2C[0x44 - 0x2C];
|
|
int16_t offset_x; // 0x44
|
|
uint16_t wiggle; // 0x46
|
|
};
|
|
assert_struct_size(RCT12SpriteMoneyEffect, 0x48);
|
|
|
|
struct RCT12SpriteCrashedVehicleParticle : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x24 - 0x1F];
|
|
uint16_t time_to_live; // 0x24
|
|
uint16_t frame; // 0x26
|
|
uint8_t pad_28[0x2C - 0x28];
|
|
uint8_t colour[2]; // 0x2C
|
|
uint16_t crashed_sprite_base; // 0x2E
|
|
int16_t velocity_x; // 0x30
|
|
int16_t velocity_y; // 0x32
|
|
int16_t velocity_z; // 0x34
|
|
uint8_t pad_36[0x38 - 0x36];
|
|
int32_t acceleration_x; // 0x38
|
|
int32_t acceleration_y; // 0x3C
|
|
int32_t acceleration_z; // 0x40
|
|
};
|
|
assert_struct_size(RCT12SpriteCrashedVehicleParticle, 0x44);
|
|
|
|
struct RCT12SpriteCrashSplash : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x26 - 0x1F];
|
|
uint16_t frame; // 0x26
|
|
};
|
|
assert_struct_size(RCT12SpriteCrashSplash, 0x28);
|
|
|
|
struct RCT12SpriteSteamParticle : RCT12SpriteBase
|
|
{
|
|
uint8_t pad_1F[0x24 - 0x1F];
|
|
uint16_t time_to_move; // 0x24
|
|
uint16_t frame; // 0x26
|
|
};
|
|
assert_struct_size(RCT12SpriteSteamParticle, 0x28);
|
|
|
|
struct RCT12PeepThought
|
|
{
|
|
uint8_t type;
|
|
uint8_t item;
|
|
uint8_t freshness;
|
|
uint8_t fresh_timeout;
|
|
};
|
|
assert_struct_size(RCT12PeepThought, 4);
|
|
|
|
struct RCT12RideMeasurement
|
|
{
|
|
uint8_t ride_index; // 0x0000
|
|
uint8_t flags; // 0x0001
|
|
uint32_t last_use_tick; // 0x0002
|
|
uint16_t num_items; // 0x0006
|
|
uint16_t current_item; // 0x0008
|
|
uint8_t vehicle_index; // 0x000A
|
|
uint8_t current_station; // 0x000B
|
|
int8_t vertical[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x000C
|
|
int8_t lateral[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x12CC
|
|
uint8_t velocity[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x258C
|
|
uint8_t altitude[RCT12_RIDE_MEASUREMENT_MAX_ITEMS]; // 0x384C
|
|
};
|
|
assert_struct_size(RCT12RideMeasurement, 0x4B0C);
|
|
|
|
struct RCT12Banner
|
|
{
|
|
RCT12ObjectEntryIndex type;
|
|
uint8_t flags; // 0x01
|
|
rct_string_id string_idx; // 0x02
|
|
union
|
|
{
|
|
uint8_t colour; // 0x04
|
|
uint8_t ride_index; // 0x04
|
|
};
|
|
uint8_t text_colour; // 0x05
|
|
uint8_t x; // 0x06
|
|
uint8_t y; // 0x07
|
|
};
|
|
assert_struct_size(RCT12Banner, 8);
|
|
|
|
struct RCT12MapAnimation
|
|
{
|
|
uint8_t baseZ;
|
|
uint8_t type;
|
|
uint16_t x;
|
|
uint16_t y;
|
|
};
|
|
assert_struct_size(RCT12MapAnimation, 6);
|
|
|
|
struct RCT12ResearchItem
|
|
{
|
|
// Bit 16 (0: scenery entry, 1: ride entry)
|
|
union
|
|
{
|
|
uint32_t rawValue;
|
|
struct
|
|
{
|
|
RCT12ObjectEntryIndex entryIndex;
|
|
uint8_t baseRideType;
|
|
uint8_t type; // 0: scenery entry, 1: ride entry
|
|
uint8_t flags;
|
|
};
|
|
};
|
|
uint8_t category;
|
|
|
|
bool IsInventedEndMarker() const;
|
|
bool IsRandomEndMarker() const;
|
|
bool IsUninventedEndMarker() const;
|
|
};
|
|
assert_struct_size(RCT12ResearchItem, 5);
|
|
|
|
#pragma pack(pop)
|
|
|
|
ObjectEntryIndex RCTEntryIndexToOpenRCT2EntryIndex(const RCT12ObjectEntryIndex index);
|
|
RCT12ObjectEntryIndex OpenRCT2EntryIndexToRCTEntryIndex(const ObjectEntryIndex index);
|
|
ride_id_t RCT12RideIdToOpenRCT2RideId(const RCT12RideId rideId);
|
|
RCT12RideId OpenRCT2RideIdToRCT12RideId(const ride_id_t rideId);
|
|
bool IsLikelyUTF8(std::string_view s);
|
|
std::string RCT12RemoveFormattingUTF8(std::string_view s);
|
|
std::string ConvertFormattedStringToOpenRCT2(std::string_view buffer);
|
|
std::string ConvertFormattedStringToRCT2(std::string_view buffer, size_t maxLength);
|
|
std::string GetTruncatedRCT2String(std::string_view src, size_t maxLength);
|
|
track_type_t RCT12FlatTrackTypeToOpenRCT2(RCT12TrackType origTrackType);
|
|
RCT12TrackType OpenRCT2FlatTrackTypeToRCT12(track_type_t origTrackType);
|
|
std::string_view GetStationIdentifierFromStyle(uint8_t style);
|
|
std::optional<uint8_t> GetStyleFromMusicIdentifier(std::string_view identifier);
|
|
void SetDefaultRCT2TerrainObjects(ObjectList& objectList);
|
|
void RCT12AddDefaultObjects(ObjectList& objectList);
|
|
|
|
static constexpr money32 RCT12_COMPANY_VALUE_ON_FAILED_OBJECTIVE = 0x80000001;
|
|
|
|
money64 RCT12CompletedCompanyValueToOpenRCT2(money32 origValue);
|
|
money32 OpenRCT2CompletedCompanyValueToRCT12(money64 origValue);
|
|
|
|
template<typename T> std::vector<uint16_t> RCT12GetRideTypesBeenOn(T* srcPeep)
|
|
{
|
|
std::vector<uint16_t> ridesTypesBeenOn;
|
|
for (uint16_t i = 0; i < RCT12_MAX_RIDE_OBJECTS; i++)
|
|
{
|
|
if (srcPeep->ride_types_been_on[i / 8] & (1 << (i % 8)))
|
|
{
|
|
ridesTypesBeenOn.push_back(i);
|
|
}
|
|
}
|
|
return ridesTypesBeenOn;
|
|
}
|
|
template<typename T> std::vector<ride_id_t> RCT12GetRidesBeenOn(T* srcPeep)
|
|
{
|
|
std::vector<ride_id_t> ridesBeenOn;
|
|
for (uint16_t i = 0; i < RCT12_MAX_RIDES_IN_PARK; i++)
|
|
{
|
|
if (srcPeep->rides_been_on[i / 8] & (1 << (i % 8)))
|
|
{
|
|
ridesBeenOn.push_back(static_cast<ride_id_t>(i));
|
|
}
|
|
}
|
|
return ridesBeenOn;
|
|
}
|