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 "../actions/GameActionResult.h"
13 #include "../common.h"
14 #include "../object/Object.h"
15 #include "../rct12/RCT12.h"
16 #include "../rct2/RCT2.h"
17 #include "../world/Map.h"
18 
19 struct Ride;
20 
21 #define TRACK_PREVIEW_IMAGE_SIZE (370 * 217)
22 
23 struct TrackDesignState
24 {
25     CoordsXYZ PreviewMin;
26     CoordsXYZ PreviewMax;
27     CoordsXYZ Origin;
28     uint8_t PlaceOperation{};
29     int16_t PlaceZ{};
30     int16_t PlaceSceneryZ{};
31     bool EntranceExitPlaced{};
32     bool HasScenery{};
33     bool PlaceScenery{};
34     bool IsReplay{};
35 };
36 
37 /* Track Entrance entry */
38 struct TrackDesignEntranceElement
39 {
40     int8_t z;
41     uint8_t direction;
42     int16_t x;
43     int16_t y;
44     bool isExit;
45 };
46 
47 /* Track Scenery entry  size: 0x16 */
48 struct TrackDesignSceneryElement
49 {
50     ObjectEntryDescriptor scenery_object;
51     int8_t x;
52     int8_t y;
53     int8_t z;
54     uint8_t flags;
55     uint8_t primary_colour;
56     uint8_t secondary_colour;
57 
IsQueueTrackDesignSceneryElement58     bool IsQueue() const
59     {
60         return (flags & (1 << 7)) != 0;
61     }
62 };
63 
64 /**
65  * Track design structure.
66  */
67 
68 /* Track Element entry  size: 0x03 */
69 struct TrackDesignTrackElement
70 {
71     track_type_t type; // 0x00
72     uint8_t flags;     // 0x02
73 };
74 
75 /* Maze Element entry   size: 0x04 */
76 struct TrackDesignMazeElement
77 {
78     union
79     {
80         uint32_t all;
81         struct
82         {
83             int8_t x;
84             int8_t y;
85             union
86             {
87                 uint16_t maze_entry;
88                 struct
89                 {
90                     uint8_t direction;
91                     uint8_t type;
92                 };
93             };
94         };
95     };
96 };
97 
98 class DataSerialiser;
99 enum class RideMode : uint8_t;
100 
101 struct TrackDesign
102 {
103     uint8_t type;
104     uint8_t vehicle_type;
105     money32 cost;
106     uint32_t flags;
107     RideMode ride_mode;
108     uint8_t track_flags;
109     uint8_t colour_scheme;
110     std::array<rct_vehicle_colour, RCT2_MAX_CARS_PER_TRAIN> vehicle_colours;
111     uint8_t entrance_style;
112     uint8_t total_air_time;
113     uint8_t depart_flags;
114     uint8_t number_of_trains;
115     uint8_t number_of_cars_per_train;
116     uint8_t min_waiting_time;
117     uint8_t max_waiting_time;
118     uint8_t operation_setting;
119     int8_t max_speed;
120     int8_t average_speed;
121     uint16_t ride_length;
122     uint8_t max_positive_vertical_g;
123     int8_t max_negative_vertical_g;
124     uint8_t max_lateral_g;
125     uint8_t inversions;
126     uint8_t holes;
127     uint8_t drops;
128     uint8_t highest_drop_height;
129     uint8_t excitement;
130     uint8_t intensity;
131     uint8_t nausea;
132     money16 upkeep_cost;
133     uint8_t track_spine_colour[RCT12_NUM_COLOUR_SCHEMES];
134     uint8_t track_rail_colour[RCT12_NUM_COLOUR_SCHEMES];
135     uint8_t track_support_colour[RCT12_NUM_COLOUR_SCHEMES];
136     uint32_t flags2;
137     ObjectEntryDescriptor vehicle_object;
138     uint8_t space_required_x;
139     uint8_t space_required_y;
140     uint8_t vehicle_additional_colour[RCT2_MAX_CARS_PER_TRAIN];
141     uint8_t lift_hill_speed;
142     uint8_t num_circuits;
143 
144     std::vector<TrackDesignMazeElement> maze_elements;
145     std::vector<TrackDesignTrackElement> track_elements;
146     std::vector<TrackDesignEntranceElement> entrance_elements;
147     std::vector<TrackDesignSceneryElement> scenery_elements;
148 
149     std::string name;
150 
151 public:
152     rct_string_id CreateTrackDesign(TrackDesignState& tds, const Ride& ride);
153     rct_string_id CreateTrackDesignScenery(TrackDesignState& tds);
154     void Serialise(DataSerialiser& stream);
155 
156 private:
157     uint8_t _saveDirection;
158     rct_string_id CreateTrackDesignTrack(TrackDesignState& tds, const Ride& ride);
159     rct_string_id CreateTrackDesignMaze(TrackDesignState& tds, const Ride& ride);
160     CoordsXYE MazeGetFirstElement(const Ride& ride);
161 };
162 
163 // Only written to in RCT2, not used in OpenRCT2. All of these are elements that had to be invented in RCT1.
164 enum : uint32_t
165 {
166     TRACK_FLAGS_CONTAINS_VERTICAL_LOOP = (1 << 7),
167     TRACK_FLAGS_CONTAINS_INLINE_TWIST = (1 << 17),
168     TRACK_FLAGS_CONTAINS_HALF_LOOP = (1 << 18),
169     TRACK_FLAGS_CONTAINS_CORKSCREW = (1 << 19),
170     TRACK_FLAGS_CONTAINS_WATER_SPLASH = (1 << 27),
171     TRACK_FLAGS_CONTAINS_BARREL_ROLL = (1 << 29),
172     TRACK_FLAGS_CONTAINS_POWERED_LIFT = (1 << 30),
173     TRACK_FLAGS_CONTAINS_LARGE_HALF_LOOP = (1u << 31),
174 };
175 
176 enum : uint32_t
177 {
178     TRACK_FLAGS2_CONTAINS_LOG_FLUME_REVERSER = (1 << 1),
179     TRACK_FLAGS2_SIX_FLAGS_RIDE_DEPRECATED = (1u << 31) // Not used anymore.
180 };
181 
182 enum
183 {
184     TDPF_PLACE_SCENERY = 1 << 0,
185 };
186 
187 enum
188 {
189     TRACK_DESIGN_FLAG_SCENERY_UNAVAILABLE = (1 << 0),
190     TRACK_DESIGN_FLAG_HAS_SCENERY = (1 << 1),
191     TRACK_DESIGN_FLAG_VEHICLE_UNAVAILABLE = (1 << 2),
192 };
193 
194 enum
195 {
196     PTD_OPERATION_DRAW_OUTLINES,
197     PTD_OPERATION_PLACE_QUERY,
198     PTD_OPERATION_PLACE,
199     PTD_OPERATION_GET_PLACE_Z,
200     PTD_OPERATION_PLACE_GHOST,
201     PTD_OPERATION_PLACE_TRACK_PREVIEW,
202     PTD_OPERATION_REMOVE_GHOST,
203 };
204 
205 static constexpr uint8_t PTD_OPERATION_FLAG_IS_REPLAY = (1 << 7);
206 
207 enum
208 {
209     MAZE_ELEMENT_TYPE_MAZE_TRACK = 0,
210     MAZE_ELEMENT_TYPE_ENTRANCE = (1 << 3),
211     MAZE_ELEMENT_TYPE_EXIT = (1 << 7)
212 };
213 
214 static constexpr ride_id_t PreviewRideId = static_cast<ride_id_t>(0);
215 
216 extern bool gTrackDesignSceneryToggle;
217 
218 extern bool _trackDesignDrawingPreview;
219 
220 extern bool _trackDesignPlaceStateSceneryUnavailable;
221 extern bool gTrackDesignSaveMode;
222 extern ride_id_t gTrackDesignSaveRideIndex;
223 
224 [[nodiscard]] std::unique_ptr<TrackDesign> TrackDesignImport(const utf8* path);
225 
226 void TrackDesignMirror(TrackDesign* td6);
227 
228 GameActions::Result::Ptr TrackDesignPlace(
229     TrackDesign* td6, uint32_t flags, bool placeScenery, Ride* ride, const CoordsXYZ& coords);
230 void TrackDesignPreviewRemoveGhosts(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
231 void TrackDesignPreviewDrawOutlines(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
232 int32_t TrackDesignGetZPlacement(TrackDesign* td6, Ride* ride, const CoordsXYZ& coords);
233 
234 ///////////////////////////////////////////////////////////////////////////////
235 // Track design preview
236 ///////////////////////////////////////////////////////////////////////////////
237 void TrackDesignDrawPreview(TrackDesign* td6, uint8_t* pixels);
238 
239 ///////////////////////////////////////////////////////////////////////////////
240 // Track design saving
241 ///////////////////////////////////////////////////////////////////////////////
242 void track_design_save_init();
243 void track_design_save_reset_scenery();
244 bool track_design_save_contains_tile_element(const TileElement* tileElement);
245 void track_design_save_select_nearby_scenery(ride_id_t rideIndex);
246 void track_design_save_select_tile_element(
247     ViewportInteractionItem interactionType, const CoordsXY& loc, TileElement* tileElement, bool collect);
248 
249 bool track_design_are_entrance_and_exit_placed();
250 
251 extern std::vector<TrackDesignSceneryElement> _trackSavedTileElementsDesc;
252 extern std::vector<const TileElement*> _trackSavedTileElements;
253