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 #include "T6Exporter.h"
11
12 #include "../Context.h"
13 #include "../core/FileStream.h"
14 #include "../core/MemoryStream.h"
15 #include "../localisation/Localisation.h"
16 #include "../localisation/StringIds.h"
17 #include "../object/ObjectList.h"
18 #include "../rct12/SawyerChunkWriter.h"
19 #include "../ride/Ride.h"
20 #include "../ride/Station.h"
21 #include "../ride/Track.h"
22 #include "../ride/TrackData.h"
23 #include "../ride/TrackDesign.h"
24 #include "../ride/TrackDesignRepository.h"
25 #include "../windows/Intent.h"
26
27 #include <functional>
28
T6Exporter(TrackDesign * trackDesign)29 T6Exporter::T6Exporter(TrackDesign* trackDesign)
30 : _trackDesign(trackDesign)
31 {
32 }
33
SaveTrack(const utf8 * path)34 bool T6Exporter::SaveTrack(const utf8* path)
35 {
36 try
37 {
38 auto fs = OpenRCT2::FileStream(path, OpenRCT2::FILE_MODE_WRITE);
39 return SaveTrack(&fs);
40 }
41 catch (const std::exception& e)
42 {
43 log_error("Unable to save track design: %s", e.what());
44 return false;
45 }
46 }
47
SaveTrack(OpenRCT2::IStream * stream)48 bool T6Exporter::SaveTrack(OpenRCT2::IStream* stream)
49 {
50 OpenRCT2::MemoryStream tempStream;
51 tempStream.WriteValue<uint8_t>(OpenRCT2RideTypeToRCT2RideType(_trackDesign->type));
52 tempStream.WriteValue<uint8_t>(_trackDesign->vehicle_type);
53 tempStream.WriteValue<uint32_t>(_trackDesign->flags);
54 tempStream.WriteValue<uint8_t>(static_cast<uint8_t>(_trackDesign->ride_mode));
55 tempStream.WriteValue<uint8_t>((_trackDesign->colour_scheme & 0x3) | (2 << 2));
56 tempStream.WriteArray(_trackDesign->vehicle_colours.data(), RCT12_MAX_VEHICLE_COLOURS);
57 tempStream.WriteValue<uint8_t>(0);
58 tempStream.WriteValue<uint8_t>(_trackDesign->entrance_style);
59 tempStream.WriteValue<uint8_t>(_trackDesign->total_air_time);
60 tempStream.WriteValue<uint8_t>(_trackDesign->depart_flags);
61 tempStream.WriteValue<uint8_t>(_trackDesign->number_of_trains);
62 tempStream.WriteValue<uint8_t>(_trackDesign->number_of_cars_per_train);
63 tempStream.WriteValue<uint8_t>(_trackDesign->min_waiting_time);
64 tempStream.WriteValue<uint8_t>(_trackDesign->max_waiting_time);
65 tempStream.WriteValue<uint8_t>(_trackDesign->operation_setting);
66 tempStream.WriteValue<int8_t>(_trackDesign->max_speed);
67 tempStream.WriteValue<int8_t>(_trackDesign->average_speed);
68 tempStream.WriteValue<uint16_t>(_trackDesign->ride_length);
69 tempStream.WriteValue<uint8_t>(_trackDesign->max_positive_vertical_g);
70 tempStream.WriteValue<int8_t>(_trackDesign->max_negative_vertical_g);
71 tempStream.WriteValue<uint8_t>(_trackDesign->max_lateral_g);
72 tempStream.WriteValue<uint8_t>(_trackDesign->type == RIDE_TYPE_MINI_GOLF ? _trackDesign->holes : _trackDesign->inversions);
73 tempStream.WriteValue<uint8_t>(_trackDesign->drops);
74 tempStream.WriteValue<uint8_t>(_trackDesign->highest_drop_height);
75 tempStream.WriteValue<uint8_t>(_trackDesign->excitement);
76 tempStream.WriteValue<uint8_t>(_trackDesign->intensity);
77 tempStream.WriteValue<uint8_t>(_trackDesign->nausea);
78 tempStream.WriteValue<money16>(_trackDesign->upkeep_cost);
79 tempStream.WriteArray(_trackDesign->track_spine_colour, RCT12_NUM_COLOUR_SCHEMES);
80 tempStream.WriteArray(_trackDesign->track_rail_colour, RCT12_NUM_COLOUR_SCHEMES);
81 tempStream.WriteArray(_trackDesign->track_support_colour, RCT12_NUM_COLOUR_SCHEMES);
82 tempStream.WriteValue<uint32_t>(_trackDesign->flags2);
83 tempStream.Write(&_trackDesign->vehicle_object.Entry, sizeof(rct_object_entry));
84 tempStream.WriteValue<uint8_t>(_trackDesign->space_required_x);
85 tempStream.WriteValue<uint8_t>(_trackDesign->space_required_y);
86 tempStream.WriteArray(_trackDesign->vehicle_additional_colour, RCT2_MAX_CARS_PER_TRAIN);
87 tempStream.WriteValue<uint8_t>(_trackDesign->lift_hill_speed | (_trackDesign->num_circuits << 5));
88
89 if (_trackDesign->type == RIDE_TYPE_MAZE)
90 {
91 for (const auto& mazeElement : _trackDesign->maze_elements)
92 {
93 tempStream.WriteValue<uint32_t>(mazeElement.all);
94 }
95
96 tempStream.WriteValue<uint32_t>(0);
97 }
98 else
99 {
100 for (const auto& trackElement : _trackDesign->track_elements)
101 {
102 auto trackType = OpenRCT2TrackTypeToRCT2(trackElement.type);
103 if (trackType == TrackElemType::MultiDimInvertedUp90ToFlatQuarterLoop)
104 {
105 trackType = TrackElemType::InvertedUp90ToFlatQuarterLoopAlias;
106 }
107 tempStream.WriteValue<uint8_t>(static_cast<uint8_t>(trackType));
108 tempStream.WriteValue<uint8_t>(trackElement.flags);
109 }
110
111 tempStream.WriteValue<uint8_t>(0xFF);
112
113 for (const auto& entranceElement : _trackDesign->entrance_elements)
114 {
115 tempStream.WriteValue<uint8_t>(entranceElement.z == -1 ? static_cast<uint8_t>(0x80) : entranceElement.z);
116 tempStream.WriteValue<uint8_t>(entranceElement.direction | (entranceElement.isExit << 7));
117 tempStream.WriteValue<int16_t>(entranceElement.x);
118 tempStream.WriteValue<int16_t>(entranceElement.y);
119 }
120
121 tempStream.WriteValue<uint8_t>(0xFF);
122 }
123
124 for (const auto& sceneryElement : _trackDesign->scenery_elements)
125 {
126 tempStream.Write(&sceneryElement.scenery_object.Entry, sizeof(rct_object_entry));
127 tempStream.WriteValue<int8_t>(sceneryElement.x);
128 tempStream.WriteValue<int8_t>(sceneryElement.y);
129 tempStream.WriteValue<int8_t>(sceneryElement.z);
130 tempStream.WriteValue<uint8_t>(sceneryElement.flags);
131 tempStream.WriteValue<uint8_t>(sceneryElement.primary_colour);
132 tempStream.WriteValue<uint8_t>(sceneryElement.secondary_colour);
133 }
134
135 tempStream.WriteValue<uint8_t>(0xFF);
136
137 SawyerChunkWriter sawyerCoding(stream);
138 sawyerCoding.WriteChunkTrack(tempStream.GetData(), tempStream.GetLength());
139 return true;
140 }
141