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 "../../common.h"
11 #include "../../interface/Viewport.h"
12 #include "../../paint/Paint.h"
13 #include "../../paint/Supports.h"
14 #include "../../world/Map.h"
15 #include "../Track.h"
16 #include "../TrackPaint.h"
17 #include "../Vehicle.h"
18 #include "../VehiclePaint.h"
19
20 enum
21 {
22 SPR_OBSERVATION_TOWER_SEGMENT_BASE = 14986,
23 SPR_OBSERVATION_TOWER_SEGMENT = 14987,
24 SPR_OBSERVATION_TOWER_SEGMENT_TOP = 14988,
25 };
26
27 /**
28 *
29 * rct2: 0x006D6258
30 */
vehicle_visual_observation_tower(paint_session * session,int32_t x,int32_t imageDirection,int32_t y,int32_t z,const Vehicle * vehicle,const rct_ride_entry_vehicle * vehicleEntry)31 void vehicle_visual_observation_tower(
32 paint_session* session, int32_t x, int32_t imageDirection, int32_t y, int32_t z, const Vehicle* vehicle,
33 const rct_ride_entry_vehicle* vehicleEntry)
34 {
35 int32_t image_id;
36 int32_t baseImage_id = (vehicle->restraints_position / 64);
37 if (vehicle->restraints_position >= 64)
38 {
39 auto directionOffset = imageDirection / 8;
40 if ((directionOffset == 0) || (directionOffset == 3))
41 {
42 baseImage_id = vehicleEntry->base_image_id + 8;
43 }
44 else
45 {
46 baseImage_id *= 2;
47 baseImage_id += vehicleEntry->base_image_id;
48 if (directionOffset == 1)
49 {
50 baseImage_id += 28;
51 }
52 else
53 {
54 baseImage_id += 22;
55 }
56 }
57 }
58 else
59 {
60 baseImage_id = (vehicle->animation_frame * 2) + vehicleEntry->base_image_id + 8;
61 }
62
63 image_id = baseImage_id | SPRITE_ID_PALETTE_COLOUR_3(vehicle->colours.body_colour, vehicle->colours.trim_colour);
64 if (vehicle->IsGhost())
65 {
66 image_id = (image_id & 0x7FFFF) | CONSTRUCTION_MARKER;
67 }
68 paint_struct* ps = PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 2, 2, 41 }, { -11, -11, z + 1 });
69 if (ps != nullptr)
70 {
71 ps->tertiary_colour = vehicle->colours_extended;
72 }
73
74 image_id++;
75
76 ps = PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 16, 16, 41 }, { -5, -5, z + 1 });
77 if (ps != nullptr)
78 {
79 ps->tertiary_colour = vehicle->colours_extended;
80 }
81
82 assert(vehicleEntry->effect_visual == 1);
83 }
84
85 /** rct2: 0x0070DD6C */
paint_observation_tower_base(paint_session * session,const Ride * ride,uint8_t trackSequence,uint8_t direction,int32_t height,const TrackElement & trackElement)86 static void paint_observation_tower_base(
87 paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height,
88 const TrackElement& trackElement)
89 {
90 trackSequence = track_map_3x3[direction][trackSequence];
91
92 int32_t edges = edges_3x3[trackSequence];
93 CoordsXY position = session->MapPosition;
94
95 wooden_a_supports_paint_setup(session, (direction & 1), 0, height, session->TrackColours[SCHEME_MISC]);
96
97 StationObject* stationObject = nullptr;
98 if (ride != nullptr)
99 stationObject = ride_get_station_object(ride);
100
101 track_paint_util_paint_floor(
102 session, edges, session->TrackColours[SCHEME_SUPPORTS], height, floorSpritesMetalB, stationObject);
103
104 if (ride != nullptr)
105 {
106 track_paint_util_paint_fences(
107 session, edges, position, trackElement, ride, session->TrackColours[SCHEME_TRACK], height, fenceSpritesMetalB,
108 session->CurrentRotation);
109 }
110
111 if (trackSequence == 0)
112 {
113 uint32_t imageId = SPR_OBSERVATION_TOWER_SEGMENT_BASE | session->TrackColours[SCHEME_TRACK];
114 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 27 }, { 8, 8, height + 3 });
115
116 imageId = SPR_OBSERVATION_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
117 PaintAddImageAsParent(session, imageId, { 0, 0, height + 32 }, { 2, 2, 30 }, { 8, 8, height + 32 });
118
119 imageId = SPR_OBSERVATION_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
120 PaintAddImageAsParent(session, imageId, { 0, 0, height + 64 }, { 2, 2, 30 }, { 8, 8, height + 64 });
121
122 paint_util_set_vertical_tunnel(session, height + 96);
123 paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
124
125 #ifdef __TESTPAINT__
126 paint_util_set_general_support_height(session, height + 32, 0x20);
127 #else
128 paint_util_set_general_support_height(session, height + 96, 0x20);
129 #endif
130 return;
131 }
132
133 int32_t blockedSegments = 0;
134 switch (trackSequence)
135 {
136 case 1:
137 blockedSegments = SEGMENT_B8 | SEGMENT_C8 | SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC;
138 break;
139 case 2:
140 blockedSegments = SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC;
141 break;
142 case 3:
143 blockedSegments = SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC | SEGMENT_D4 | SEGMENT_C0;
144 break;
145 case 4:
146 blockedSegments = SEGMENT_B4 | SEGMENT_C8 | SEGMENT_B8;
147 break;
148 case 5:
149 blockedSegments = SEGMENT_BC | SEGMENT_D4 | SEGMENT_C0;
150 break;
151 case 6:
152 blockedSegments = SEGMENT_B4 | SEGMENT_C8 | SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0;
153 break;
154 case 7:
155 blockedSegments = SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0 | SEGMENT_D4 | SEGMENT_BC;
156 break;
157 case 8:
158 blockedSegments = SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0;
159 break;
160 }
161 paint_util_set_segment_support_height(session, blockedSegments, 0xFFFF, 0);
162 paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~blockedSegments, height + 2, 0x20);
163 paint_util_set_general_support_height(session, height + 32, 0x20);
164 }
165
166 /** rct2: 0x0070DD7C */
paint_observation_tower_section(paint_session * session,const Ride * ride,uint8_t trackSequence,uint8_t direction,int32_t height,const TrackElement & trackElement)167 static void paint_observation_tower_section(
168 paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height,
169 const TrackElement& trackElement)
170 {
171 if (trackSequence == 1)
172 {
173 return;
174 }
175
176 uint32_t imageId = SPR_OBSERVATION_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
177 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 30 }, { 8, 8, height });
178
179 const TileElement* nextTileElement = reinterpret_cast<const TileElement*>(&trackElement) + 1;
180 if (trackElement.IsLastForTile() || trackElement.GetClearanceZ() != nextTileElement->GetBaseZ())
181 {
182 imageId = SPR_OBSERVATION_TOWER_SEGMENT_TOP | session->TrackColours[SCHEME_TRACK];
183 PaintAddImageAsChild(session, imageId, 0, 0, 2, 2, 30, height, 8, 8, height);
184 }
185
186 paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
187
188 paint_util_set_vertical_tunnel(session, height + 32);
189 paint_util_set_general_support_height(session, height + 32, 0x20);
190 }
191
192 /**
193 * rct2: 0x0070DC5C
194 */
get_track_paint_function_observation_tower(int32_t trackType)195 TRACK_PAINT_FUNCTION get_track_paint_function_observation_tower(int32_t trackType)
196 {
197 switch (trackType)
198 {
199 case TrackElemType::TowerBase:
200 return paint_observation_tower_base;
201
202 case TrackElemType::TowerSection:
203 return paint_observation_tower_section;
204 }
205
206 return nullptr;
207 }
208