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 "../../config/Config.h"
12 #include "../../interface/Viewport.h"
13 #include "../../paint/Paint.h"
14 #include "../../paint/Supports.h"
15 #include "../Track.h"
16 #include "../TrackPaint.h"
17 #include "../Vehicle.h"
18 #include "../VehiclePaint.h"
19
20 enum
21 {
22 SPR_LAUNCHED_FREEFALL_TOWER_BASE = 14564,
23 SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT = 14565,
24 SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT_TOP = 14566,
25 };
26
27 /**
28 *
29 * rct2: 0x006D5FAB
30 */
vehicle_visual_launched_freefall(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_launched_freefall(
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 auto imageFlags = SPRITE_ID_PALETTE_COLOUR_2(vehicle->colours.body_colour, vehicle->colours.trim_colour);
36 if (vehicle->IsGhost())
37 {
38 imageFlags = CONSTRUCTION_MARKER;
39 }
40
41 // Draw back:
42 int32_t baseImage_id = vehicleEntry->base_image_id + ((vehicle->restraints_position / 64) * 2);
43 auto image_id = (baseImage_id + 2) | imageFlags;
44 PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 2, 2, 41 }, { -11, -11, z + 1 });
45
46 // Draw front:
47 image_id = (baseImage_id + 1) | imageFlags;
48 PaintAddImageAsParent(session, image_id, { 0, 0, z }, { 16, 16, 41 }, { -5, -5, z + 1 });
49
50 // Draw peeps:
51 if (session->DPI.zoom_level < 2 && vehicle->num_peeps > 0 && !vehicle->IsGhost())
52 {
53 baseImage_id = vehicleEntry->base_image_id + 9;
54 if ((vehicle->restraints_position / 64) == 3)
55 {
56 baseImage_id += 2; // Draw peeps sitting without transparent area between them for restraints
57 }
58 auto directionOffset = imageDirection / 8;
59 image_id = (baseImage_id + (((directionOffset + 0) & 3) * 3))
60 | SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[0], vehicle->peep_tshirt_colours[1]);
61 PaintAddImageAsChild(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
62 if (vehicle->num_peeps > 2)
63 {
64 image_id = (baseImage_id + (((directionOffset + 1) & 3) * 3))
65 | SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[2], vehicle->peep_tshirt_colours[3]);
66 PaintAddImageAsChild(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
67 }
68 if (vehicle->num_peeps > 4)
69 {
70 image_id = (baseImage_id + (((directionOffset + 2) & 3) * 3))
71 | SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[4], vehicle->peep_tshirt_colours[5]);
72 PaintAddImageAsChild(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
73 }
74 if (vehicle->num_peeps > 6)
75 {
76 image_id = (baseImage_id + (((directionOffset + 3) & 3) * 3))
77 | SPRITE_ID_PALETTE_COLOUR_2(vehicle->peep_tshirt_colours[6], vehicle->peep_tshirt_colours[7]);
78 PaintAddImageAsChild(session, image_id, 0, 0, 16, 16, 41, z, -5, -5, z + 1);
79 }
80 }
81
82 assert(vehicleEntry->effect_visual == 1);
83 }
84
85 /** rct2: 0x006FD1F8 */
paint_launched_freefall_base(paint_session * session,const Ride * ride,uint8_t trackSequence,uint8_t direction,int32_t height,const TrackElement & trackElement)86 static void paint_launched_freefall_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
94 wooden_a_supports_paint_setup(session, (direction & 1), 0, height, session->TrackColours[SCHEME_MISC]);
95
96 StationObject* stationObject = nullptr;
97 if (ride != nullptr)
98 stationObject = ride_get_station_object(ride);
99
100 track_paint_util_paint_floor(
101 session, edges, session->TrackColours[SCHEME_SUPPORTS], height, floorSpritesMetal, stationObject);
102
103 if (ride != nullptr)
104 {
105 track_paint_util_paint_fences(
106 session, edges, session->MapPosition, trackElement, ride, session->TrackColours[SCHEME_TRACK], height,
107 fenceSpritesMetal, session->CurrentRotation);
108 }
109
110 if (trackSequence == 0)
111 {
112 uint32_t imageId = SPR_LAUNCHED_FREEFALL_TOWER_BASE | session->TrackColours[SCHEME_TRACK];
113 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 27 }, { 8, 8, height + 3 });
114
115 height += 32;
116 imageId = SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
117 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 30 }, { 8, 8, height });
118
119 height += 32;
120 imageId = SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
121 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 30 }, { 8, 8, height });
122
123 paint_util_set_vertical_tunnel(session, height + 32);
124
125 height -= 64;
126 }
127
128 int32_t blockedSegments = 0;
129 switch (trackSequence)
130 {
131 case 0:
132 blockedSegments = SEGMENTS_ALL;
133 break;
134 case 1:
135 blockedSegments = SEGMENT_B8 | SEGMENT_C8 | SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC;
136 break;
137 case 2:
138 blockedSegments = SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC;
139 break;
140 case 3:
141 blockedSegments = SEGMENT_B4 | SEGMENT_CC | SEGMENT_BC | SEGMENT_D4 | SEGMENT_C0;
142 break;
143 case 4:
144 blockedSegments = SEGMENT_B4 | SEGMENT_C8 | SEGMENT_B8;
145 break;
146 case 5:
147 blockedSegments = SEGMENT_BC | SEGMENT_D4 | SEGMENT_C0;
148 break;
149 case 6:
150 blockedSegments = SEGMENT_B4 | SEGMENT_C8 | SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0;
151 break;
152 case 7:
153 blockedSegments = SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0 | SEGMENT_D4 | SEGMENT_BC;
154 break;
155 case 8:
156 blockedSegments = SEGMENT_B8 | SEGMENT_D0 | SEGMENT_C0;
157 break;
158 }
159 paint_util_set_segment_support_height(session, blockedSegments, 0xFFFF, 0);
160 paint_util_set_segment_support_height(session, SEGMENTS_ALL & ~blockedSegments, height + 2, 0x20);
161 paint_util_set_general_support_height(session, height + 32, 0x20);
162 }
163
164 /** rct2: 0x006FD208 */
paint_launched_freefall_tower_section(paint_session * session,const Ride * ride,uint8_t trackSequence,uint8_t direction,int32_t height,const TrackElement & trackElement)165 static void paint_launched_freefall_tower_section(
166 paint_session* session, const Ride* ride, uint8_t trackSequence, uint8_t direction, int32_t height,
167 const TrackElement& trackElement)
168 {
169 if (trackSequence == 1)
170 {
171 return;
172 }
173
174 uint32_t imageId = SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT | session->TrackColours[SCHEME_TRACK];
175 PaintAddImageAsParent(session, imageId, { 0, 0, height }, { 2, 2, 30 }, { 8, 8, height });
176
177 const TileElement* nextTileElement = reinterpret_cast<const TileElement*>(&trackElement) + 1;
178 if (trackElement.IsLastForTile() || trackElement.GetClearanceZ() != nextTileElement->GetBaseZ())
179 {
180 imageId = SPR_LAUNCHED_FREEFALL_TOWER_SEGMENT_TOP | session->TrackColours[SCHEME_TRACK];
181 PaintAddImageAsChild(session, imageId, 0, 0, 2, 2, 30, height, 8, 8, height);
182 }
183
184 paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0);
185
186 paint_util_set_vertical_tunnel(session, height + 32);
187 paint_util_set_general_support_height(session, height + 32, 0x20);
188 }
189
190 /**
191 * rct2: 0x006FD0E8
192 */
get_track_paint_function_launched_freefall(int32_t trackType)193 TRACK_PAINT_FUNCTION get_track_paint_function_launched_freefall(int32_t trackType)
194 {
195 switch (trackType)
196 {
197 case TrackElemType::TowerBase:
198 return paint_launched_freefall_base;
199
200 case TrackElemType::TowerSection:
201 return paint_launched_freefall_tower_section;
202 }
203
204 return nullptr;
205 }
206