diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0f62a0bb62..fb3af2fe45 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -64,9 +64,9 @@ set(TITLE_SEQUENCE_VERSION "0.4.6")
set(TITLE_SEQUENCE_URL "https://github.com/OpenRCT2/title-sequences/releases/download/v${TITLE_SEQUENCE_VERSION}/title-sequences.zip")
set(TITLE_SEQUENCE_SHA1 "80fefc6ebbabc42a6f4703412daa5c62f661420d")
-set(OBJECTS_VERSION "1.4.0")
+set(OBJECTS_VERSION "1.4.2")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v${OBJECTS_VERSION}/objects.zip")
-set(OBJECTS_SHA1 "f512e230ffa2f16109209e4f30e7d7bf4fe21fc0")
+set(OBJECTS_SHA1 "2adc4cb66a6446533d67097bdf44cd9c5882fea3")
set(OPENSFX_VERSION "1.0.5")
set(OPENSFX_URL "https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v${OPENSFX_VERSION}/opensound.zip")
diff --git a/data/language/en-GB.txt b/data/language/en-GB.txt
index b483ae466b..30b97ba615 100644
--- a/data/language/en-GB.txt
+++ b/data/language/en-GB.txt
@@ -98,6 +98,7 @@ STR_0093 :Hybrid Coaster
STR_0094 :Single Rail Roller Coaster
STR_0095 :Alpine Coaster
STR_0096 :Classic Wooden Roller Coaster
+STR_0097 :Classic Stand-up Roller Coaster
STR_0512 :A compact roller coaster with a spiral lift hill and smooth, twisting drops.
STR_0513 :A looping roller coaster where the riders ride in a standing position
STR_0514 :Trains suspended beneath the roller coaster track swing out to the side around corners
@@ -181,6 +182,7 @@ STR_0603 :A wooden style roller coaster with a steel track, allowing for stee
STR_0604 :Riders ride single file on a narrow monorail track, as they race through tight inversions and direction changes
STR_0605 :Riders toboggan down a meandering steel track, braking to control their speed
STR_0606 :An older-style wooden roller coaster with a fast and rough ride, with plenty of air-time, some lateral G’s, and designed to feel ‘out-of-control’
+STR_0607 :An intense, older-style steel looping roller coaster where the riders ride in a standing position
STR_0767 :Guest {INT32}
STR_0768 :Handyman {INT32}
STR_0769 :Mechanic {INT32}
diff --git a/distribution/changelog.txt b/distribution/changelog.txt
index 4e51bcc83e..e541bd8b81 100644
--- a/distribution/changelog.txt
+++ b/distribution/changelog.txt
@@ -1,9 +1,18 @@
0.4.10 (in development)
------------------------------------------------------------------------
+- Feature: [#18171] Add port of the RCT1 Stand-Up Roller Coaster.
- Feature: [#21636] Add shortcut key for sorting tile elements.
+- Feature: [objects#294] Add scenery versions of wooden truss supports.
+- Feature: [objects#295] Flipped version of wooden post.
- Improved: [#21424] Extra viewports can now rotate independently from the main viewport.
- Improved: [#21561, #21631] Enable more features in Android build (plugins, networking, multiplayer, audio formats).
- Improved: [#21599] Currency signs now use non-breaking spaces.
+- Improved: [objects#157] Added sloped images for many walls.
+- Improved: [objects#288] Better map colours and more sensible prices for RCT1 land surfaces.
+- Improved: [objects#292] Vehicle colour cleanups for WW/TT vehicles.
+- Improved: [objects#299] More accurate ratings modifiers for RCT1 vehicles.
+- Improved: [objects#309] Updated names for dodgems and flying saucers vehicles.
+- Improved: [objects#313] buildMenuPriority for dodgems and flying saucers vehicles.
- Change: [#21529] Classify “Southern Sands”, “Tiny Towers”, “Nevermore Park”, “Pacifica” as expert scenarios.
- Fix: [#910] Extra viewport does not preserve the location when rotating.
- Fix: [#18413] Crash when mouse over a hacked train.
@@ -13,6 +22,11 @@
- Fix: [#21543] Crash with creating a TrackIterator with invalid arguments.
- Fix: [#21635] Tile inspector hotkey can set wall slope for non-slopeable objects.
- Fix: [#21641] Crash when creating track iterator from an invalid tile element.
+- Fix: [objects#290] “Haunted Mansion” cars have a non-functional third remap colour.
+- Fix: [objects#296] Incorrect wall placement around large Kremlin/drab pieces.
+- Fix: [objects#300] Incorrect Colosseum and volcano corner clearances.
+- Fix: [objects#319] Incorrect diagonal slope images used for RCT1 corkscrew.
+- Fix: [objects#320] Incorrect Mandarin Duck boats capacity.
0.4.9 (2024-03-02)
------------------------------------------------------------------------
diff --git a/openrct2.proj b/openrct2.proj
index 05ee7c1376..d34fcceb46 100644
--- a/openrct2.proj
+++ b/openrct2.proj
@@ -45,8 +45,8 @@
bd338aa3da9a357fb996dcaa6cea02c4f906718c
https://github.com/OpenRCT2/title-sequences/releases/download/v0.4.6/title-sequences.zip
80fefc6ebbabc42a6f4703412daa5c62f661420d
- https://github.com/OpenRCT2/objects/releases/download/v1.4.0/objects.zip
- f512e230ffa2f16109209e4f30e7d7bf4fe21fc0
+ https://github.com/OpenRCT2/objects/releases/download/v1.4.2/objects.zip
+ 2adc4cb66a6446533d67097bdf44cd9c5882fea3
https://github.com/OpenRCT2/OpenSoundEffects/releases/download/v1.0.5/opensound.zip
b1b1f1b241d2cbff63a1889c4dc5a09bdf769bfb
https://github.com/OpenRCT2/OpenMusic/releases/download/v1.5/openmusic.zip
diff --git a/src/openrct2-ui/windows/NewRide.cpp b/src/openrct2-ui/windows/NewRide.cpp
index a3422995f2..2f43010cff 100644
--- a/src/openrct2-ui/windows/NewRide.cpp
+++ b/src/openrct2-ui/windows/NewRide.cpp
@@ -80,6 +80,7 @@ namespace OpenRCT2::Ui::Windows
RIDE_TYPE_MINE_TRAIN_COASTER,
RIDE_TYPE_LOOPING_ROLLER_COASTER,
RIDE_TYPE_STAND_UP_ROLLER_COASTER,
+ RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER,
RIDE_TYPE_CORKSCREW_ROLLER_COASTER,
RIDE_TYPE_HYPERCOASTER,
RIDE_TYPE_LIM_LAUNCHED_ROLLER_COASTER,
diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj
index 305315edf9..5bf4284f55 100644
--- a/src/openrct2/libopenrct2.vcxproj
+++ b/src/openrct2/libopenrct2.vcxproj
@@ -396,6 +396,7 @@
+
@@ -901,6 +902,7 @@
+
diff --git a/src/openrct2/localisation/StringIds.h b/src/openrct2/localisation/StringIds.h
index 07ed17fae4..c97e25eb74 100644
--- a/src/openrct2/localisation/StringIds.h
+++ b/src/openrct2/localisation/StringIds.h
@@ -113,6 +113,7 @@ enum : uint16_t
STR_RIDE_NAME_SINGLE_RAIL_ROLLER_COASTER = 94,
STR_RIDE_NAME_ALPINE_COASTER = 95,
STR_RIDE_NAME_CLASSIC_WOODEN_ROLLER_COASTER = 96,
+ STR_RIDE_NAME_CLASSIC_STAND_UP_ROLLER_COASTER = 97,
STR_RIDE_DESCRIPTION_SPIRAL_ROLLER_COASTER = 512,
STR_RIDE_DESCRIPTION_STAND_UP_ROLLER_COASTER = 513,
@@ -206,6 +207,7 @@ enum : uint16_t
STR_RIDE_DESCRIPTION_SINGLE_RAIL_ROLLER_COASTER = 604,
STR_RIDE_DESCRIPTION_ALPINE_COASTER = 605,
STR_RIDE_DESCRIPTION_CLASSIC_WOODEN_ROLLER_COASTER = 606,
+ STR_RIDE_DESCRIPTION_CLASSIC_STAND_UP_ROLLER_COASTER = 607,
STR_GUEST_X = 767,
STR_HANDYMAN_X = 768,
diff --git a/src/openrct2/paint/support/MetalSupports.cpp b/src/openrct2/paint/support/MetalSupports.cpp
index b9b15ab2c6..08f266f67e 100644
--- a/src/openrct2/paint/support/MetalSupports.cpp
+++ b/src/openrct2/paint/support/MetalSupports.cpp
@@ -178,6 +178,26 @@ static constexpr uint8_t metal_supports_slope_image_map[] = {
};
// clang-format on
+static constexpr MetalSupportPlace kMetalSupportPlacementRotated[][NumOrthogonalDirections] = {
+ { MetalSupportPlace::TopCorner, MetalSupportPlace::RightCorner, MetalSupportPlace::BottomCorner,
+ MetalSupportPlace::LeftCorner },
+ { MetalSupportPlace::LeftCorner, MetalSupportPlace::TopCorner, MetalSupportPlace::RightCorner,
+ MetalSupportPlace::BottomCorner },
+ { MetalSupportPlace::RightCorner, MetalSupportPlace::BottomCorner, MetalSupportPlace::LeftCorner,
+ MetalSupportPlace::TopCorner },
+ { MetalSupportPlace::BottomCorner, MetalSupportPlace::LeftCorner, MetalSupportPlace::TopCorner,
+ MetalSupportPlace::RightCorner },
+ { MetalSupportPlace::Centre, MetalSupportPlace::Centre, MetalSupportPlace::Centre, MetalSupportPlace::Centre },
+ { MetalSupportPlace::TopLeftSide, MetalSupportPlace::TopRightSide, MetalSupportPlace::BottomRightSide,
+ MetalSupportPlace::BottomLeftSide },
+ { MetalSupportPlace::TopRightSide, MetalSupportPlace::BottomRightSide, MetalSupportPlace::BottomLeftSide,
+ MetalSupportPlace::TopLeftSide },
+ { MetalSupportPlace::BottomLeftSide, MetalSupportPlace::BottomLeftSide, MetalSupportPlace::TopLeftSide,
+ MetalSupportPlace::TopRightSide },
+ { MetalSupportPlace::BottomRightSide, MetalSupportPlace::TopLeftSide, MetalSupportPlace::TopRightSide,
+ MetalSupportPlace::BottomRightSide },
+};
+
/**
* Metal pole supports
* @param supportType (edi)
@@ -374,6 +394,14 @@ bool MetalASupportsPaintSetup(
return true;
}
+bool MetalASupportsPaintSetupRotated(
+ PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, Direction direction,
+ int32_t special, int32_t height, ImageId imageTemplate)
+{
+ placement = kMetalSupportPlacementRotated[EnumValue(placement)][direction];
+ return MetalASupportsPaintSetup(session, supportTypeMember, placement, special, height, imageTemplate);
+}
+
/**
* Metal pole supports
* rct2: 0x00663584
@@ -559,6 +587,14 @@ bool MetalBSupportsPaintSetup(
return false; // AND
}
+bool MetalBSupportsPaintSetupRotated(
+ PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, Direction direction,
+ int32_t special, int32_t height, ImageId imageTemplate)
+{
+ placement = kMetalSupportPlacementRotated[EnumValue(placement)][direction];
+ return MetalBSupportsPaintSetup(session, supportTypeMember, placement, special, height, imageTemplate);
+}
+
constexpr uint8_t MetalSupportTypeCount = 13;
constexpr MetalSupportType RotatedMetalSupports[MetalSupportTypeCount][NumOrthogonalDirections] = {
{ MetalSupportType::Tubes, MetalSupportType::Tubes, MetalSupportType::Tubes, MetalSupportType::Tubes },
diff --git a/src/openrct2/paint/support/MetalSupports.h b/src/openrct2/paint/support/MetalSupports.h
index 40c74e4288..c1e3b95db1 100644
--- a/src/openrct2/paint/support/MetalSupports.h
+++ b/src/openrct2/paint/support/MetalSupports.h
@@ -95,9 +95,15 @@ struct PaintSession;
bool MetalASupportsPaintSetup(
PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, int32_t special, int32_t height,
ImageId imageTemplate);
+bool MetalASupportsPaintSetupRotated(
+ PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, Direction direction,
+ int32_t special, int32_t height, ImageId imageTemplate);
bool MetalBSupportsPaintSetup(
PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, int32_t special, int32_t height,
ImageId imageTemplate);
+bool MetalBSupportsPaintSetupRotated(
+ PaintSession& session, MetalSupportType supportTypeMember, MetalSupportPlace placement, Direction direction,
+ int32_t special, int32_t height, ImageId imageTemplate);
void DrawSupportsSideBySide(
PaintSession& session, Direction direction, uint16_t height, ImageId colour, MetalSupportType type, int32_t special = 0);
bool PathPoleSupportsPaintSetup(
diff --git a/src/openrct2/rct1/Tables.cpp b/src/openrct2/rct1/Tables.cpp
index 4a7bc17109..5b878a7495 100644
--- a/src/openrct2/rct1/Tables.cpp
+++ b/src/openrct2/rct1/Tables.cpp
@@ -173,7 +173,7 @@ namespace RCT1
static uint8_t map[] =
{
RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER,// RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER
- RIDE_TYPE_STAND_UP_ROLLER_COASTER, // RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER
+ RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER, // RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER
RIDE_TYPE_SUSPENDED_SWINGING_COASTER, // RCT1_RIDE_TYPE_SUSPENDED_ROLLER_COASTER
RIDE_TYPE_INVERTED_ROLLER_COASTER, // RCT1_RIDE_TYPE_INVERTED_ROLLER_COASTER
RIDE_TYPE_CLASSIC_MINI_ROLLER_COASTER, // RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER
@@ -275,7 +275,7 @@ namespace RCT1
{ COPY_COLOUR_1, COPY_COLOUR_2, COPY_COLOUR_2 }, // RCT1_VEHICLE_TYPE_INVERTED_COASTER_TRAIN, // Not in RCT2
{ COPY_COLOUR_1, COPY_COLOUR_2, COPY_COLOUR_2 }, // RCT1_VEHICLE_TYPE_SUSPENDED_SWINGING_CARS,
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_LADYBIRD_CARS,
- { COPY_COLOUR_1, COPY_COLOUR_1, COPY_COLOUR_2 }, // RCT1_VEHICLE_TYPE_STANDUP_ROLLER_COASTER_CARS,
+ { COPY_COLOUR_1, COPY_COLOUR_2, COPY_COLOUR_2 }, // RCT1_VEHICLE_TYPE_STANDUP_ROLLER_COASTER_CARS,
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_SPINNING_CARS,
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_SINGLE_PERSON_SWINGING_CHAIRS,
{ COPY_COLOUR_1, COPY_COLOUR_2, COLOUR_BLACK }, // RCT1_VEHICLE_TYPE_SWANS_PEDAL_BOATS,
@@ -705,7 +705,7 @@ namespace RCT1
static constexpr const char * map[] =
{
"rct1.ride.wooden_rc_trains", // RCT1_RIDE_TYPE_WOODEN_ROLLER_COASTER
- "rct2.ride.togst", // RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER
+ "rct1.ride.stand_up_trains", // RCT1_RIDE_TYPE_STAND_UP_STEEL_ROLLER_COASTER
"rct1.ride.suspended_swinging_cars", // RCT1_RIDE_TYPE_SUSPENDED_ROLLER_COASTER
"rct1ll.ride.4_across_inverted_trains", // RCT1_RIDE_TYPE_INVERTED_ROLLER_COASTER
"rct1.ride.ladybird_trains", // RCT1_RIDE_TYPE_STEEL_MINI_ROLLER_COASTER
@@ -807,7 +807,7 @@ namespace RCT1
"rct1.ride.inverted_trains", // VehicleType::InvertedCoasterTrain//NotinRCT2
"rct1.ride.suspended_swinging_cars", // VehicleType::SuspendedSwingingCars
"rct1.ride.ladybird_trains", // VehicleType::LadybirdCars
- "rct2.ride.togst", // VehicleType::StandupRollerCoasterCars
+ "rct1.ride.stand_up_trains", // VehicleType::StandupRollerCoasterCars
"rct2.ride.wmspin", // VehicleType::SpinningCars
"rct1.ride.single_person_swinging_cars", // VehicleType::SinglePersonSwingingChairs
"rct2.ride.swans", // VehicleType::SwansPedalBoats
diff --git a/src/openrct2/ride/Ride.h b/src/openrct2/ride/Ride.h
index 3669f0e84c..3615d13a89 100644
--- a/src/openrct2/ride/Ride.h
+++ b/src/openrct2/ride/Ride.h
@@ -611,6 +611,7 @@ enum
RIDE_TYPE_SINGLE_RAIL_ROLLER_COASTER,
RIDE_TYPE_ALPINE_COASTER,
RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER,
+ RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER,
RIDE_TYPE_COUNT
};
diff --git a/src/openrct2/ride/RideData.cpp b/src/openrct2/ride/RideData.cpp
index 623b742d6a..9741aa7dc7 100644
--- a/src/openrct2/ride/RideData.cpp
+++ b/src/openrct2/ride/RideData.cpp
@@ -34,6 +34,7 @@
#include "coaster/meta/AlpineCoaster.h"
#include "coaster/meta/BobsleighCoaster.h"
#include "coaster/meta/ClassicMiniRollerCoaster.h"
+#include "coaster/meta/ClassicStandUpRollerCoaster.h"
#include "coaster/meta/ClassicWoodenRollerCoaster.h"
#include "coaster/meta/CompactInvertedCoaster.h"
#include "coaster/meta/CorkscrewRollerCoaster.h"
@@ -350,6 +351,7 @@ constexpr RideTypeDescriptor RideTypeDescriptors[RIDE_TYPE_COUNT] = {
/* RIDE_TYPE_SINGLE_RAIL_ROLLER_COASTER */ SingleRailRollerCoasterRTD,
/* RIDE_TYPE_ALPINE_COASTER */ AlpineCoasterRTD,
/* RIDE_TYPE_CLASSIC_WOODEN_ROLLER_COASTER */ ClassicWoodenRollerCoasterRTD,
+ /* RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER */ ClassicStandUpRollerCoasterRTD,
};
bool RideTypeDescriptor::HasFlag(uint64_t flag) const
diff --git a/src/openrct2/ride/TrackPaint.cpp b/src/openrct2/ride/TrackPaint.cpp
index 69735b0e89..b4ad3fba81 100644
--- a/src/openrct2/ride/TrackPaint.cpp
+++ b/src/openrct2/ride/TrackPaint.cpp
@@ -1347,6 +1347,13 @@ const uint8_t mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[] = {
6, 4, 5, 3, 1, 2, 0,
};
+const uint8_t mapReversedDiagonalStraight[4] = {
+ 3,
+ 2,
+ 1,
+ 0,
+};
+
constexpr CoordsXY defaultRightQuarterTurn5TilesOffsets[4][5] = {
{
{ 0, 6 },
diff --git a/src/openrct2/ride/TrackPaint.h b/src/openrct2/ride/TrackPaint.h
index 695f2ce357..3f47862be2 100644
--- a/src/openrct2/ride/TrackPaint.h
+++ b/src/openrct2/ride/TrackPaint.h
@@ -247,6 +247,8 @@ extern const uint32_t trackSpritesSubmarineRideMiniHelicoptersQuarterTurn3Tiles[
extern const uint32_t trackSpritesSubmarineRideMiniHelicoptersQuarterTurn1Tile[4];
extern const uint8_t mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[];
+extern const Direction mapReversedDiagonalStraight[];
+
extern const CoordsXY defaultRightQuarterTurn5TilesOffsets[4][5];
extern const CoordsXYZ defaultRightQuarterTurn5TilesBoundOffsets[4][5];
extern const CoordsXY defaultRightQuarterTurn5TilesBoundLengths[4][5];
@@ -494,3 +496,4 @@ namespace AlpineRC
TRACK_PAINT_FUNCTION GetTrackPaintFunction(int32_t trackType);
}
TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicWoodenRC(int32_t trackType);
+TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(int32_t trackType);
diff --git a/src/openrct2/ride/coaster/ClassicStandUpRollerCoaster.cpp b/src/openrct2/ride/coaster/ClassicStandUpRollerCoaster.cpp
new file mode 100644
index 0000000000..f4a210e123
--- /dev/null
+++ b/src/openrct2/ride/coaster/ClassicStandUpRollerCoaster.cpp
@@ -0,0 +1,1528 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2024 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.
+ *****************************************************************************/
+
+#include "../../sprites.h"
+#include "../Track.h"
+#include "../TrackPaint.h"
+
+#include
+
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBank0 = SPR_CSG_BEGIN + 67009;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBank2 = SPR_CSG_BEGIN + 67010;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBank0 = SPR_CSG_BEGIN + 67011;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBank2 = SPR_CSG_BEGIN + 67012;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBank3 = SPR_CSG_BEGIN + 67013;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBank1 = SPR_CSG_BEGIN + 67014;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBank3 = SPR_CSG_BEGIN + 67015;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBank1 = SPR_CSG_BEGIN + 67016;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked0_0 = SPR_CSG_BEGIN + 67017;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked0_1 = SPR_CSG_BEGIN + 67018;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked0_2 = SPR_CSG_BEGIN + 67019;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked0_3 = SPR_CSG_BEGIN + 67020;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked0_4 = SPR_CSG_BEGIN + 67021;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked1_0 = SPR_CSG_BEGIN + 67022;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked1_1 = SPR_CSG_BEGIN + 67023;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked1_2 = SPR_CSG_BEGIN + 67024;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked1_3 = SPR_CSG_BEGIN + 67025;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked1_4 = SPR_CSG_BEGIN + 67026;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked2_0 = SPR_CSG_BEGIN + 67027;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked2_1 = SPR_CSG_BEGIN + 67028;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked2_2 = SPR_CSG_BEGIN + 67029;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked2_3 = SPR_CSG_BEGIN + 67030;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked2_4 = SPR_CSG_BEGIN + 67031;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked3_0 = SPR_CSG_BEGIN + 67032;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked3_1 = SPR_CSG_BEGIN + 67033;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked3_2 = SPR_CSG_BEGIN + 67034;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked3_3 = SPR_CSG_BEGIN + 67035;
+static constexpr ImageIndex kClassicStandUpRcRightTurn5TilesBanked3_4 = SPR_CSG_BEGIN + 67036;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatRightBanked0 = SPR_CSG_BEGIN + 67037;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatRightBanked1 = SPR_CSG_BEGIN + 67038;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatRightBanked2 = SPR_CSG_BEGIN + 67039;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatRightBanked3 = SPR_CSG_BEGIN + 67040;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatLeftBanked0 = SPR_CSG_BEGIN + 67041;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatLeftBanked1 = SPR_CSG_BEGIN + 67042;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatLeftBanked2 = SPR_CSG_BEGIN + 67043;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToFlatLeftBanked3 = SPR_CSG_BEGIN + 67044;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedTo25DegUp0 = SPR_CSG_BEGIN + 67045;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedTo25DegUp1 = SPR_CSG_BEGIN + 67046;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedTo25DegUp2 = SPR_CSG_BEGIN + 67047;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedTo25DegUp3 = SPR_CSG_BEGIN + 67048;
+static constexpr ImageIndex kClassicStandUpRcRightBankedTo25DegUp0 = SPR_CSG_BEGIN + 67049;
+static constexpr ImageIndex kClassicStandUpRcRightBankedTo25DegUp1 = SPR_CSG_BEGIN + 67050;
+static constexpr ImageIndex kClassicStandUpRcRightBankedTo25DegUp2 = SPR_CSG_BEGIN + 67051;
+static constexpr ImageIndex kClassicStandUpRcRightBankedTo25DegUp3 = SPR_CSG_BEGIN + 67052;
+static constexpr ImageIndex kClassicStandUpRcLeftBanked0 = SPR_CSG_BEGIN + 67053;
+static constexpr ImageIndex kClassicStandUpRcLeftBanked1 = SPR_CSG_BEGIN + 67054;
+static constexpr ImageIndex kClassicStandUpRcLeftBanked2 = SPR_CSG_BEGIN + 67055;
+static constexpr ImageIndex kClassicStandUpRcLeftBanked3 = SPR_CSG_BEGIN + 67056;
+
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked0_0 = SPR_CSG_BEGIN + 67229;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked0_1 = SPR_CSG_BEGIN + 67230;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked0_2 = SPR_CSG_BEGIN + 67231;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked1_0 = SPR_CSG_BEGIN + 67232;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked1_1 = SPR_CSG_BEGIN + 67233;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked1_2 = SPR_CSG_BEGIN + 67234;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked2_0 = SPR_CSG_BEGIN + 67235;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked2_1 = SPR_CSG_BEGIN + 67236;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked2_2 = SPR_CSG_BEGIN + 67237;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked3_0 = SPR_CSG_BEGIN + 67238;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked3_1 = SPR_CSG_BEGIN + 67239;
+static constexpr ImageIndex kClassicStandUpRcRightTurn3TilesBanked3_2 = SPR_CSG_BEGIN + 67240;
+
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag0_0 = SPR_CSG_BEGIN + 67361;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag0_1 = SPR_CSG_BEGIN + 67362;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag0_2 = SPR_CSG_BEGIN + 67363;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag0_3 = SPR_CSG_BEGIN + 67364;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag1_0 = SPR_CSG_BEGIN + 67365;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag1_1 = SPR_CSG_BEGIN + 67366;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag1_2 = SPR_CSG_BEGIN + 67367;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag1_3 = SPR_CSG_BEGIN + 67368;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag2_0 = SPR_CSG_BEGIN + 67369;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag2_1 = SPR_CSG_BEGIN + 67370;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag2_2 = SPR_CSG_BEGIN + 67371;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag2_3 = SPR_CSG_BEGIN + 67372;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag3_0 = SPR_CSG_BEGIN + 67373;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag3_1 = SPR_CSG_BEGIN + 67374;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag3_2 = SPR_CSG_BEGIN + 67375;
+static constexpr ImageIndex kClassicStandUpRcRightBankedOrthogonalToDiag3_3 = SPR_CSG_BEGIN + 67376;
+
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag0_0 = SPR_CSG_BEGIN + 67377;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag0_1 = SPR_CSG_BEGIN + 67378;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag0_2 = SPR_CSG_BEGIN + 67379;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag0_3 = SPR_CSG_BEGIN + 67380;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag1_0 = SPR_CSG_BEGIN + 67381;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag1_1 = SPR_CSG_BEGIN + 67382;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag1_2 = SPR_CSG_BEGIN + 67383;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag1_3 = SPR_CSG_BEGIN + 67384;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag2_0 = SPR_CSG_BEGIN + 67385;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag2_1 = SPR_CSG_BEGIN + 67386;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag2_2 = SPR_CSG_BEGIN + 67387;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag2_3 = SPR_CSG_BEGIN + 67388;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag3_0 = SPR_CSG_BEGIN + 67389;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag3_1 = SPR_CSG_BEGIN + 67390;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag3_2 = SPR_CSG_BEGIN + 67391;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedOrthogonalToDiag3_3 = SPR_CSG_BEGIN + 67392;
+
+static constexpr ImageIndex kClassicStandUpRcLeftBankedStraightDiag0 = SPR_CSG_BEGIN + 67421;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedStraightDiag1 = SPR_CSG_BEGIN + 67422;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedStraightDiag2 = SPR_CSG_BEGIN + 67423;
+static constexpr ImageIndex kClassicStandUpRcLeftBankedStraightDiag3 = SPR_CSG_BEGIN + 67424;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBankDiag0 = SPR_CSG_BEGIN + 67425;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBankDiag1 = SPR_CSG_BEGIN + 67426;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBankDiag2 = SPR_CSG_BEGIN + 67427;
+static constexpr ImageIndex kClassicStandUpRcFlatToLeftBankDiag3 = SPR_CSG_BEGIN + 67428;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBankDiag0 = SPR_CSG_BEGIN + 67429;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBankDiag1 = SPR_CSG_BEGIN + 67430;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBankDiag2 = SPR_CSG_BEGIN + 67431;
+static constexpr ImageIndex kClassicStandUpRcFlatToRightBankDiag3 = SPR_CSG_BEGIN + 67432;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToLeftBankDiag0 = SPR_CSG_BEGIN + 67433;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToLeftBankDiag1 = SPR_CSG_BEGIN + 67434;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToLeftBankDiag2 = SPR_CSG_BEGIN + 67435;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToLeftBankDiag3 = SPR_CSG_BEGIN + 67436;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToRightBankDiag0 = SPR_CSG_BEGIN + 67437;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToRightBankDiag1 = SPR_CSG_BEGIN + 67438;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToRightBankDiag2 = SPR_CSG_BEGIN + 67439;
+static constexpr ImageIndex kClassicStandUpRc25DegUpToRightBankDiag3 = SPR_CSG_BEGIN + 67440;
+static constexpr ImageIndex kClassicStandUpRcLeftBankTo25DegUpDiag0 = SPR_CSG_BEGIN + 67441;
+static constexpr ImageIndex kClassicStandUpRcLeftBankTo25DegUpDiag1 = SPR_CSG_BEGIN + 67442;
+static constexpr ImageIndex kClassicStandUpRcLeftBankTo25DegUpDiag2 = SPR_CSG_BEGIN + 67443;
+static constexpr ImageIndex kClassicStandUpRcLeftBankTo25DegUpDiag3 = SPR_CSG_BEGIN + 67444;
+static constexpr ImageIndex kClassicStandUpRcRightBankTo25DegUpDiag0 = SPR_CSG_BEGIN + 67445;
+static constexpr ImageIndex kClassicStandUpRcRightBankTo25DegUpDiag1 = SPR_CSG_BEGIN + 67446;
+static constexpr ImageIndex kClassicStandUpRcRightBankTo25DegUpDiag2 = SPR_CSG_BEGIN + 67447;
+static constexpr ImageIndex kClassicStandUpRcRightBankTo25DegUpDiag3 = SPR_CSG_BEGIN + 67448;
+
+static void classicStandUpRCTrackFlatToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcFlatToLeftBank0,
+ kClassicStandUpRcFlatToLeftBank1,
+ kClassicStandUpRcFlatToLeftBank2,
+ kClassicStandUpRcFlatToLeftBank3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ }
+
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackFlatToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcFlatToRightBank0,
+ kClassicStandUpRcFlatToRightBank1,
+ kClassicStandUpRcFlatToRightBank2,
+ kClassicStandUpRcFlatToRightBank3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ }
+
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackLeftBankToFlat(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ return classicStandUpRCTrackFlatToRightBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackRightBankToFlat(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ return classicStandUpRCTrackFlatToLeftBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackBankedRightQuarterTurn5(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ switch (trackSequence)
+ {
+ case 0:
+ {
+ constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcRightTurn5TilesBanked0_0,
+ kClassicStandUpRcRightTurn5TilesBanked1_0,
+ kClassicStandUpRcRightTurn5TilesBanked2_0,
+ kClassicStandUpRcRightTurn5TilesBanked3_0,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ switch (direction)
+ {
+ case 0:
+ PaintUtilPushTunnelLeft(session, height, TUNNEL_0);
+ break;
+ case 3:
+ PaintUtilPushTunnelRight(session, height, TUNNEL_0);
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+ case 1:
+ break;
+
+ case 2:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked0_1),
+ { 0, 16, height }, { 32, 16, 3 });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked1_1),
+ { 0, 16, height }, { 32, 16, 3 });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked2_1),
+ { 0, 0, height }, { 32, 16, 3 });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked3_1),
+ { 0, 0, height }, { 32, 16, 3 });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::rightCorner, PaintSegment::centre,
+ PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide, PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+
+ case 3:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked0_2),
+ { 0, 0, height }, { 16, 16, 3 });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked1_2),
+ { 16, 0, height }, { 16, 16, 3 });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked2_2),
+ { 16, 16, height }, { 16, 16, 3 });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked3_2),
+ { 0, 16, height }, { 16, 16, 3 });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+
+ case 4:
+ break;
+
+ case 5:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked0_3),
+ { 16, 0, height }, { 16, 32, 3 });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked1_3),
+ { 0, 0, height }, { 16, 32, 3 });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked2_3),
+ { 0, 0, height }, { 16, 32, 3 });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(kClassicStandUpRcRightTurn5TilesBanked3_3),
+ { 16, 0, height }, { 16, 32, 3 });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::bottomCorner, PaintSegment::centre,
+ PaintSegment::bottomLeftSide, PaintSegment::topLeftSide, PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+
+ case 6:
+ {
+ constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcRightTurn5TilesBanked0_4,
+ kClassicStandUpRcRightTurn5TilesBanked1_4,
+ kClassicStandUpRcRightTurn5TilesBanked2_4,
+ kClassicStandUpRcRightTurn5TilesBanked3_4,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 6, 0, height }, { 20, 32, 3 });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ if (direction == 1 || direction == 0)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+ }
+
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackBankedLeftQuarterTurn5(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapLeftQuarterTurn5TilesToRightQuarterTurn5Tiles[trackSequence];
+ direction = (direction + 1) % NumOrthogonalDirections;
+ return classicStandUpRCTrackBankedRightQuarterTurn5(session, ride, trackSequence, direction, height, trackElement);
+}
+
+static void classicStandUpRCTrackLeftBankTo25DegUp(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcLeftBankedTo25DegUp0,
+ kClassicStandUpRcLeftBankedTo25DegUp1,
+ kClassicStandUpRcLeftBankedTo25DegUp2,
+ kClassicStandUpRcLeftBankedTo25DegUp3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 3, height, session.SupportColours);
+ }
+
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ else
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_2);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20);
+}
+
+static void classicStandUpRCTrackRightBankTo25DegUp(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcRightBankedTo25DegUp0,
+ kClassicStandUpRcRightBankedTo25DegUp1,
+ kClassicStandUpRcRightBankedTo25DegUp2,
+ kClassicStandUpRcRightBankedTo25DegUp3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 3, height, session.SupportColours);
+ }
+
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ else
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_2);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20);
+}
+
+static void classicStandUpRCTrack25DegUpToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRc25DegUpToFlatLeftBanked0,
+ kClassicStandUpRc25DegUpToFlatLeftBanked1,
+ kClassicStandUpRc25DegUpToFlatLeftBanked2,
+ kClassicStandUpRc25DegUpToFlatLeftBanked3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 6, height, session.SupportColours);
+ }
+
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height - 8, TUNNEL_0);
+ }
+ else
+ {
+ PaintUtilPushTunnelRotated(session, direction, height + 8, TUNNEL_12);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 40, 0x20);
+}
+
+static void classicStandUpRCTrack25DegUpToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRc25DegUpToFlatRightBanked0,
+ kClassicStandUpRc25DegUpToFlatRightBanked1,
+ kClassicStandUpRc25DegUpToFlatRightBanked2,
+ kClassicStandUpRc25DegUpToFlatRightBanked3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 6, height, session.SupportColours);
+ }
+
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height - 8, TUNNEL_0);
+ }
+ else
+ {
+ PaintUtilPushTunnelRotated(session, direction, height + 8, TUNNEL_12);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 40, 0x20);
+}
+
+static void classicStandUpRCTrackLeftBankTo25DegDown(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrack25DegUpToRightBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackRightBankTo25DegDown(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrack25DegUpToLeftBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrack25DegDownToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackRightBankTo25DegUp(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrack25DegDownToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackLeftBankTo25DegUp(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[NumOrthogonalDirections] = {
+ kClassicStandUpRcLeftBanked0,
+ kClassicStandUpRcLeftBanked1,
+ kClassicStandUpRcLeftBanked2,
+ kClassicStandUpRcLeftBanked3,
+ };
+
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(map[direction]), { 0, 6, height }, { 32, 20, 3 });
+
+ if (TrackPaintUtilShouldPaintSupports(session.MapPosition))
+ {
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ }
+
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ return classicStandUpRCTrackLeftBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackLeftEighthBankToDiag(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[5][NumOrthogonalDirections] = {
+ { kClassicStandUpRcLeftBankedOrthogonalToDiag0_0, kClassicStandUpRcLeftBankedOrthogonalToDiag1_0,
+ kClassicStandUpRcLeftBankedOrthogonalToDiag2_0, kClassicStandUpRcLeftBankedOrthogonalToDiag3_0 },
+ { kClassicStandUpRcLeftBankedOrthogonalToDiag0_1, kClassicStandUpRcLeftBankedOrthogonalToDiag1_1,
+ kClassicStandUpRcLeftBankedOrthogonalToDiag2_1, kClassicStandUpRcLeftBankedOrthogonalToDiag3_1 },
+ { kClassicStandUpRcLeftBankedOrthogonalToDiag0_2, kClassicStandUpRcLeftBankedOrthogonalToDiag1_2,
+ kClassicStandUpRcLeftBankedOrthogonalToDiag2_2, kClassicStandUpRcLeftBankedOrthogonalToDiag3_2 },
+ { ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined },
+ { kClassicStandUpRcLeftBankedOrthogonalToDiag0_3, kClassicStandUpRcLeftBankedOrthogonalToDiag1_3,
+ kClassicStandUpRcLeftBankedOrthogonalToDiag2_3, kClassicStandUpRcLeftBankedOrthogonalToDiag3_3 },
+ };
+
+ const auto imageId = map[trackSequence][direction];
+
+ switch (trackSequence)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 6, height }, { 32, 20, 3 } });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 1:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 32, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 34, 16, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 32, 16, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 32, 16, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::topRightSide, PaintSegment::bottomLeftSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 16, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 16, height }, { 16, 16, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 0, height }, { 16, 16, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 16, 16, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 3:
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomLeftSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 4:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 16, height }, { 16, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 16, 18, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 16, 16, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 0, height }, { 16, 16, 3 } });
+ break;
+ }
+ MetalASupportsPaintSetupRotated(
+ session, MetalSupportType::Tubes, MetalSupportPlace::BottomCorner, direction, 0, height,
+ session.SupportColours);
+
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide,
+ PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ }
+}
+
+static void classicStandUpRCTrackRightEighthBankToDiag(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[5][NumOrthogonalDirections] = {
+ { kClassicStandUpRcRightBankedOrthogonalToDiag0_0, kClassicStandUpRcRightBankedOrthogonalToDiag1_0,
+ kClassicStandUpRcRightBankedOrthogonalToDiag2_0, kClassicStandUpRcRightBankedOrthogonalToDiag3_0 },
+ { kClassicStandUpRcRightBankedOrthogonalToDiag0_1, kClassicStandUpRcRightBankedOrthogonalToDiag1_1,
+ kClassicStandUpRcRightBankedOrthogonalToDiag2_1, kClassicStandUpRcRightBankedOrthogonalToDiag3_1 },
+ { kClassicStandUpRcRightBankedOrthogonalToDiag0_2, kClassicStandUpRcRightBankedOrthogonalToDiag1_2,
+ kClassicStandUpRcRightBankedOrthogonalToDiag2_2, kClassicStandUpRcRightBankedOrthogonalToDiag3_2 },
+ { ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined },
+ { kClassicStandUpRcRightBankedOrthogonalToDiag0_3, kClassicStandUpRcRightBankedOrthogonalToDiag1_3,
+ kClassicStandUpRcRightBankedOrthogonalToDiag2_3, kClassicStandUpRcRightBankedOrthogonalToDiag3_3 },
+ };
+
+ const auto imageId = map[trackSequence][direction];
+
+ switch (trackSequence)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 6, height }, { 32, 20, 3 } });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ if (direction == 0 || direction == 3)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(PaintSegment::centre, PaintSegment::topRightSide, PaintSegment::bottomLeftSide), direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 1:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 32, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 32, 16, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 34, 16, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 32, 16, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::topRightSide,
+ PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 16, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 0, height }, { 16, 16, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 4, 4, height }, { 28, 28, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 16, 16, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 3:
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ case 4:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 0, height }, { 16, 16, 3 } });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 0, height }, { 16, 16, 3 } });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 0, 16, height }, { 16, 18, 3 } });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height },
+ { { 16, 16, height }, { 16, 16, 3 } });
+ break;
+ }
+ MetalASupportsPaintSetupRotated(
+ session, MetalSupportType::Tubes, MetalSupportPlace::LeftCorner, direction, 0, height, session.SupportColours);
+
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide,
+ PaintSegment::bottomLeftSide, PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+ break;
+ }
+}
+
+static void classicStandUpRCTrackLeftEighthDiagBankToOrthogonal(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];
+ direction = (direction + 2) % NumOrthogonalDirections;
+ classicStandUpRCTrackRightEighthBankToDiag(session, ride, trackSequence, direction, height, trackElement);
+}
+
+static void classicStandUpRCTrackRightEighthDiagBankToOrthogonal(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapLeftEighthTurnToOrthogonal[trackSequence];
+ direction = (direction + 3) % NumOrthogonalDirections;
+ classicStandUpRCTrackLeftEighthBankToDiag(session, ride, trackSequence, direction, height, trackElement);
+}
+
+static void classicStandUpRCTrackRightBankedQuarterTurn3(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ static constexpr ImageIndex map[4][NumOrthogonalDirections] = {
+ { kClassicStandUpRcRightTurn3TilesBanked0_0, kClassicStandUpRcRightTurn3TilesBanked1_0,
+ kClassicStandUpRcRightTurn3TilesBanked2_0, kClassicStandUpRcRightTurn3TilesBanked3_0 },
+ { ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined, ImageIndexUndefined },
+ { kClassicStandUpRcRightTurn3TilesBanked0_1, kClassicStandUpRcRightTurn3TilesBanked1_1,
+ kClassicStandUpRcRightTurn3TilesBanked2_1, kClassicStandUpRcRightTurn3TilesBanked3_1 },
+
+ { kClassicStandUpRcRightTurn3TilesBanked0_2, kClassicStandUpRcRightTurn3TilesBanked1_2,
+ kClassicStandUpRcRightTurn3TilesBanked2_2, kClassicStandUpRcRightTurn3TilesBanked3_2 },
+ };
+
+ auto imageId = map[trackSequence][direction];
+
+ switch (trackSequence)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 6, height }, { 32, 20, 3 });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ switch (direction)
+ {
+ case 0:
+ PaintUtilPushTunnelLeft(session, height, TUNNEL_0);
+ break;
+ case 3:
+ PaintUtilPushTunnelRight(session, height, TUNNEL_0);
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 1:
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 16, 16, height }, { 16, 16, 3 });
+ break;
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 16, height }, { 16, 16, 3 });
+ break;
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 0, 0, height }, { 16, 16, 3 });
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 16, 0, height }, { 16, 16, 3 });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(imageId), { 6, 0, height }, { 20, 32, 3 });
+
+ MetalASupportsPaintSetup(
+ session, MetalSupportType::Tubes, MetalSupportPlace::Centre, 0, height, session.SupportColours);
+ if (direction == 0 || direction == 1)
+ {
+ PaintUtilPushTunnelRotated(session, direction, height, TUNNEL_0);
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackLeftBankedQuarterTurn3(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapLeftQuarterTurn3TilesToRightQuarterTurn3Tiles[trackSequence];
+ direction = (direction + 1) % NumOrthogonalDirections;
+ classicStandUpRCTrackRightBankedQuarterTurn3(session, ride, trackSequence, direction, height, trackElement);
+}
+
+template
+static inline void classicStandUpRCTrackDiagFlatWithBank(
+ PaintSession& session, uint8_t trackSequence, uint8_t direction, int32_t height)
+{
+ switch (trackSequence)
+ {
+ case 0:
+ switch (direction)
+ {
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img3), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 1:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img0), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img2), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 3:
+ switch (direction)
+ {
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img1), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ MetalASupportsPaintSetupRotated(
+ session, MetalSupportType::Tubes, MetalSupportPlace::LeftCorner, direction, 0, height, session.SupportColours);
+
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomLeftSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+
+ PaintUtilSetGeneralSupportHeight(session, height + 32, 0x20);
+}
+
+static void classicStandUpRCTrackDiagFlatToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiagFlatWithBank<
+ kClassicStandUpRcFlatToLeftBankDiag0, kClassicStandUpRcFlatToLeftBankDiag1, kClassicStandUpRcFlatToLeftBankDiag2,
+ kClassicStandUpRcFlatToLeftBankDiag3>(session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiagFlatToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiagFlatWithBank<
+ kClassicStandUpRcFlatToRightBankDiag0, kClassicStandUpRcFlatToRightBankDiag1, kClassicStandUpRcFlatToRightBankDiag2,
+ kClassicStandUpRcFlatToRightBankDiag3>(session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiagLeftBankToFlat(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ return classicStandUpRCTrackDiagFlatToRightBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackDiagRightBankToFlat(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ return classicStandUpRCTrackDiagFlatToLeftBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+static void classicStandUpRCTrackDiagLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiagFlatWithBank<
+ kClassicStandUpRcLeftBankedStraightDiag0, kClassicStandUpRcLeftBankedStraightDiag1,
+ kClassicStandUpRcLeftBankedStraightDiag2, kClassicStandUpRcLeftBankedStraightDiag3>(
+ session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiagRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ return classicStandUpRCTrackDiagLeftBank(
+ session, ride, trackSequence, (direction + 2) % NumOrthogonalDirections, height, trackElement);
+}
+
+template
+static void classicStandUpRCTrackDiagFlatTo25DegUpBanked(
+ PaintSession& session, uint8_t trackSequence, uint8_t direction, int32_t height)
+{
+ switch (trackSequence)
+ {
+ case 0:
+ switch (direction)
+ {
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img3), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 1:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img0), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img2), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 3:
+ switch (direction)
+ {
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img1), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ MetalBSupportsPaintSetupRotated(
+ session, MetalSupportType::Tubes, MetalSupportPlace::LeftCorner, direction, 4, height, session.SupportColours);
+
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomLeftSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+
+ PaintUtilSetGeneralSupportHeight(session, height + 48, 0x20);
+}
+
+static void classicStandUpRCTrackDiagLeftBankTo25DegUp(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiagFlatTo25DegUpBanked<
+ kClassicStandUpRcLeftBankTo25DegUpDiag0, kClassicStandUpRcLeftBankTo25DegUpDiag1,
+ kClassicStandUpRcLeftBankTo25DegUpDiag2, kClassicStandUpRcLeftBankTo25DegUpDiag3>(
+ session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiagRightBankTo25DegUp(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiagFlatTo25DegUpBanked<
+ kClassicStandUpRcRightBankTo25DegUpDiag0, kClassicStandUpRcRightBankTo25DegUpDiag1,
+ kClassicStandUpRcRightBankTo25DegUpDiag2, kClassicStandUpRcRightBankTo25DegUpDiag3>(
+ session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiag25DegDownToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ direction = (direction + 2) % NumOrthogonalDirections;
+ classicStandUpRCTrackDiagRightBankTo25DegUp(session, ride, trackSequence, direction, height, trackElement);
+}
+
+static void classicStandUpRCTrackDiag25DegDownToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ direction = (direction + 2) % NumOrthogonalDirections;
+ classicStandUpRCTrackDiagLeftBankTo25DegUp(session, ride, trackSequence, direction, height, trackElement);
+}
+
+template
+static void classicStandUpRCTrackDiag25DegUpToFlatBanked(
+ PaintSession& session, uint8_t trackSequence, uint8_t direction, int32_t height)
+{
+ switch (trackSequence)
+ {
+ case 0:
+ switch (direction)
+ {
+ case 3:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img3), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::rightCorner, PaintSegment::centre, PaintSegment::topRightSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 1:
+ switch (direction)
+ {
+ case 0:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img0), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::topCorner, PaintSegment::centre, PaintSegment::topLeftSide, PaintSegment::topRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 2:
+ switch (direction)
+ {
+ case 2:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img2), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::bottomCorner, PaintSegment::centre, PaintSegment::bottomLeftSide,
+ PaintSegment::bottomRightSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ case 3:
+ switch (direction)
+ {
+ case 1:
+ PaintAddImageAsParentRotated(
+ session, direction, session.TrackColours.WithIndex(img1), { -16, -16, height },
+ { { -16, -16, height }, { 32, 32, 3 } });
+ break;
+ }
+ MetalBSupportsPaintSetupRotated(
+ session, MetalSupportType::Tubes, MetalSupportPlace::LeftCorner, direction, 8, height, session.SupportColours);
+
+ PaintUtilSetSegmentSupportHeight(
+ session,
+ PaintUtilRotateSegments(
+ EnumsToFlags(
+ PaintSegment::leftCorner, PaintSegment::centre, PaintSegment::topLeftSide,
+ PaintSegment::bottomLeftSide),
+ direction),
+ 0xFFFF, 0);
+ break;
+ }
+
+ PaintUtilSetGeneralSupportHeight(session, height + 56, 0x20);
+}
+
+static void classicStandUpRCTrackDiag25DegUpToLeftBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiag25DegUpToFlatBanked<
+ kClassicStandUpRc25DegUpToLeftBankDiag0, kClassicStandUpRc25DegUpToLeftBankDiag1,
+ kClassicStandUpRc25DegUpToLeftBankDiag2, kClassicStandUpRc25DegUpToLeftBankDiag3>(
+ session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiag25DegUpToRightBank(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ classicStandUpRCTrackDiag25DegUpToFlatBanked<
+ kClassicStandUpRc25DegUpToRightBankDiag0, kClassicStandUpRc25DegUpToRightBankDiag1,
+ kClassicStandUpRc25DegUpToRightBankDiag2, kClassicStandUpRc25DegUpToRightBankDiag3>(
+ session, trackSequence, direction, height);
+}
+
+static void classicStandUpRCTrackDiagLeftBankTo25DegDown(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ direction = (direction + 2) % NumOrthogonalDirections;
+ classicStandUpRCTrackDiag25DegUpToRightBank(session, ride, trackSequence, direction, height, trackElement);
+}
+
+static void classicStandUpRCTrackDiagRightBankTo25DegDown(
+ PaintSession& session, const Ride& ride, uint8_t trackSequence, uint8_t direction, int32_t height,
+ const TrackElement& trackElement)
+{
+ trackSequence = mapReversedDiagonalStraight[trackSequence];
+ direction = (direction + 2) % NumOrthogonalDirections;
+ classicStandUpRCTrackDiag25DegUpToLeftBank(session, ride, trackSequence, direction, height, trackElement);
+}
+
+TRACK_PAINT_FUNCTION GetTrackPaintFunctionClassicStandUpRC(int32_t trackType)
+{
+ if (!IsCsgLoaded())
+ {
+ return GetTrackPaintFunctionStandUpRC(trackType);
+ }
+
+ switch (trackType)
+ {
+ case TrackElemType::FlatToLeftBank:
+ return classicStandUpRCTrackFlatToLeftBank;
+ case TrackElemType::FlatToRightBank:
+ return classicStandUpRCTrackFlatToRightBank;
+ case TrackElemType::LeftBankToFlat:
+ return classicStandUpRCTrackLeftBankToFlat;
+ case TrackElemType::RightBankToFlat:
+ return classicStandUpRCTrackRightBankToFlat;
+ case TrackElemType::BankedLeftQuarterTurn5Tiles:
+ return classicStandUpRCTrackBankedLeftQuarterTurn5;
+ case TrackElemType::BankedRightQuarterTurn5Tiles:
+ return classicStandUpRCTrackBankedRightQuarterTurn5;
+ case TrackElemType::LeftBankToUp25:
+ return classicStandUpRCTrackLeftBankTo25DegUp;
+ case TrackElemType::RightBankToUp25:
+ return classicStandUpRCTrackRightBankTo25DegUp;
+ case TrackElemType::Up25ToLeftBank:
+ return classicStandUpRCTrack25DegUpToLeftBank;
+ case TrackElemType::Up25ToRightBank:
+ return classicStandUpRCTrack25DegUpToRightBank;
+ case TrackElemType::LeftBankToDown25:
+ return classicStandUpRCTrackLeftBankTo25DegDown;
+ case TrackElemType::RightBankToDown25:
+ return classicStandUpRCTrackRightBankTo25DegDown;
+ case TrackElemType::Down25ToLeftBank:
+ return classicStandUpRCTrack25DegDownToLeftBank;
+ case TrackElemType::Down25ToRightBank:
+ return classicStandUpRCTrack25DegDownToRightBank;
+ case TrackElemType::LeftBank:
+ return classicStandUpRCTrackLeftBank;
+ case TrackElemType::RightBank:
+ return classicStandUpRCTrackRightBank;
+
+ case TrackElemType::LeftEighthBankToDiag:
+ return classicStandUpRCTrackLeftEighthBankToDiag;
+ case TrackElemType::RightEighthBankToDiag:
+ return classicStandUpRCTrackRightEighthBankToDiag;
+ case TrackElemType::LeftEighthBankToOrthogonal:
+ return classicStandUpRCTrackLeftEighthDiagBankToOrthogonal;
+ case TrackElemType::RightEighthBankToOrthogonal:
+ return classicStandUpRCTrackRightEighthDiagBankToOrthogonal;
+
+ case TrackElemType::LeftBankedQuarterTurn3Tiles:
+ return classicStandUpRCTrackLeftBankedQuarterTurn3;
+ case TrackElemType::RightBankedQuarterTurn3Tiles:
+ return classicStandUpRCTrackRightBankedQuarterTurn3;
+ case TrackElemType::DiagFlatToLeftBank:
+ return classicStandUpRCTrackDiagFlatToLeftBank;
+ case TrackElemType::DiagFlatToRightBank:
+ return classicStandUpRCTrackDiagFlatToRightBank;
+ case TrackElemType::DiagLeftBankToFlat:
+ return classicStandUpRCTrackDiagLeftBankToFlat;
+ case TrackElemType::DiagRightBankToFlat:
+ return classicStandUpRCTrackDiagRightBankToFlat;
+ case TrackElemType::DiagLeftBankToUp25:
+ return classicStandUpRCTrackDiagLeftBankTo25DegUp;
+ case TrackElemType::DiagRightBankToUp25:
+ return classicStandUpRCTrackDiagRightBankTo25DegUp;
+ case TrackElemType::DiagUp25ToLeftBank:
+ return classicStandUpRCTrackDiag25DegUpToLeftBank;
+ case TrackElemType::DiagUp25ToRightBank:
+ return classicStandUpRCTrackDiag25DegUpToRightBank;
+ case TrackElemType::DiagLeftBankToDown25:
+ return classicStandUpRCTrackDiagLeftBankTo25DegDown;
+ case TrackElemType::DiagRightBankToDown25:
+ return classicStandUpRCTrackDiagRightBankTo25DegDown;
+ case TrackElemType::DiagDown25ToLeftBank:
+ return classicStandUpRCTrackDiag25DegDownToLeftBank;
+ case TrackElemType::DiagDown25ToRightBank:
+ return classicStandUpRCTrackDiag25DegDownToRightBank;
+ case TrackElemType::DiagLeftBank:
+ return classicStandUpRCTrackDiagLeftBank;
+ case TrackElemType::DiagRightBank:
+ return classicStandUpRCTrackDiagRightBank;
+ }
+
+ return GetTrackPaintFunctionStandUpRC(trackType);
+}
diff --git a/src/openrct2/ride/coaster/meta/ClassicStandUpRollerCoaster.h b/src/openrct2/ride/coaster/meta/ClassicStandUpRollerCoaster.h
new file mode 100644
index 0000000000..2807d3068e
--- /dev/null
+++ b/src/openrct2/ride/coaster/meta/ClassicStandUpRollerCoaster.h
@@ -0,0 +1,87 @@
+/*****************************************************************************
+ * Copyright (c) 2014-2024 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
+
+#include "../../../sprites.h"
+#include "../../RideData.h"
+#include "../../ShopItem.h"
+#include "../../Track.h"
+
+// clang-format off
+constexpr RideTypeDescriptor ClassicStandUpRollerCoasterRTD =
+{
+ .AlternateType = RIDE_TYPE_NULL,
+ .Category = RIDE_CATEGORY_ROLLERCOASTER,
+ .EnabledTrackPieces = {TRACK_STRAIGHT, TRACK_STATION_END, TRACK_LIFT_HILL, TRACK_FLAT_ROLL_BANKING, TRACK_VERTICAL_LOOP, TRACK_SLOPE, TRACK_SLOPE_STEEP_UP, TRACK_SLOPE_STEEP_DOWN, TRACK_SLOPE_CURVE, TRACK_S_BEND, TRACK_CURVE_SMALL, TRACK_CURVE, TRACK_CURVE_LARGE, TRACK_HALF_LOOP, TRACK_CORKSCREW, TRACK_BRAKES, TRACK_ON_RIDE_PHOTO, TRACK_BLOCK_BRAKES, TRACK_DIAG_BRAKES, TRACK_DIAG_BLOCK_BRAKES},
+ .ExtraTrackPieces = {},
+ .CoveredTrackPieces = {},
+ .StartTrackPiece = TrackElemType::EndStation,
+ .TrackPaintFunctions = TrackDrawerDescriptor(GetTrackPaintFunctionClassicStandUpRC),
+ .Flags = RIDE_TYPE_FLAGS_TRACK_HAS_3_COLOURS | RIDE_TYPE_FLAG_HAS_LEAVE_WHEN_ANOTHER_VEHICLE_ARRIVES_AT_STATION |
+ RIDE_TYPE_FLAGS_COMMON_COASTER | RIDE_TYPE_FLAGS_COMMON_COASTER_NON_ALT |
+ RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
+ RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS,
+ .RideModes = EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch),
+ .DefaultMode = RideMode::ContinuousCircuit,
+ .OperatingSettings = { 7, 27, 0, 0, 0, 0 },
+ .Naming = { STR_RIDE_NAME_CLASSIC_STAND_UP_ROLLER_COASTER, STR_RIDE_DESCRIPTION_CLASSIC_STAND_UP_ROLLER_COASTER },
+ .NameConvention = { RideComponentType::Train, RideComponentType::Track, RideComponentType::Station },
+ .EnumName = nameof(RIDE_TYPE_CLASSIC_STAND_UP_ROLLER_COASTER),
+ .AvailableBreakdowns = (1 << BREAKDOWN_SAFETY_CUT_OUT) | (1 << BREAKDOWN_RESTRAINTS_STUCK_CLOSED) | (1 << BREAKDOWN_RESTRAINTS_STUCK_OPEN) | (1 << BREAKDOWN_VEHICLE_MALFUNCTION) | (1 << BREAKDOWN_BRAKES_FAILURE),
+ .Heights = { 30, 24, 9, 11, },
+ .MaxMass = 18,
+ .LiftData = { OpenRCT2::Audio::SoundId::LiftClassic, 4, 6 },
+ .RatingsMultipliers = { 50, 30, 10 },
+ .UpkeepCosts = { 40, 20, 80, 10, 3, 10 },
+ .BuildCosts = { 50.00_GBP, 2.50_GBP, 50, },
+ .DefaultPrices = { 20, 20 },
+ .DefaultMusic = MUSIC_OBJECT_TECHNO,
+ .PhotoItem = ShopItem::Photo,
+ .BonusValue = 90,
+ .ColourPresets = TRACK_COLOUR_PRESETS(
+ { COLOUR_BRIGHT_RED, COLOUR_BRIGHT_RED, COLOUR_BLACK },
+ { COLOUR_BLACK, COLOUR_LIGHT_BLUE, COLOUR_BLACK },
+ { COLOUR_LIGHT_ORANGE, COLOUR_WHITE, COLOUR_LIGHT_ORANGE },
+ { COLOUR_BORDEAUX_RED, COLOUR_YELLOW, COLOUR_BORDEAUX_RED },
+ { COLOUR_MOSS_GREEN, COLOUR_MOSS_GREEN, COLOUR_WHITE },
+ { COLOUR_SATURATED_BROWN, COLOUR_LIGHT_ORANGE, COLOUR_SATURATED_BROWN },
+ ),
+ .ColourPreview = { SPR_RIDE_DESIGN_PREVIEW_STAND_UP_ROLLER_COASTER_TRACK, SPR_RIDE_DESIGN_PREVIEW_STAND_UP_ROLLER_COASTER_SUPPORTS },
+ .ColourKey = RideColourKey::Ride,
+ .Name = "classic_stand_up_rc",
+ .RatingsData =
+ {
+ RatingsCalculationType::Normal,
+ { RIDE_RATING(2, 50), RIDE_RATING(3, 00), RIDE_RATING(3, 00) },
+ 17,
+ -1,
+ false,
+ {
+ { RatingsModifierType::BonusLength, 6000, 764, 0, 0 },
+ { RatingsModifierType::BonusSynchronisation, 0, RIDE_RATING(0, 40), RIDE_RATING(0, 10), 0 },
+ { RatingsModifierType::BonusTrainLength, 0, 187245, 0, 0 },
+ { RatingsModifierType::BonusMaxSpeed, 0, 44281, 123987, 35424 },
+ { RatingsModifierType::BonusAverageSpeed, 0, 291271, 436906, 0 },
+ { RatingsModifierType::BonusDuration, 150, 26214, 0, 0 },
+ { RatingsModifierType::BonusGForces, 0, 24576, 35746, 59578 },
+ { RatingsModifierType::BonusTurns, 0, 26749, 34767, 45749 },
+ { RatingsModifierType::BonusDrops, 0, 34952, 46811, 49152 },
+ { RatingsModifierType::BonusSheltered, 0, 12850, 28398, 30427 },
+ { RatingsModifierType::BonusReversedTrains, 0, 2, 20, 30 },
+ { RatingsModifierType::BonusProximity, 0, 17893, 0, 0 },
+ { RatingsModifierType::BonusScenery, 0, 5577, 0, 0 },
+ { RatingsModifierType::RequirementDropHeight, 12, 2, 2, 2 },
+ { RatingsModifierType::RequirementMaxSpeed, 0xA0000, 2, 2, 2 },
+ { RatingsModifierType::RequirementNegativeGs, FIXED_2DP(0, 50), 2, 2, 2 },
+ { RatingsModifierType::PenaltyLateralGs, 0, 24576, 35746, 59578 },
+ },
+ },
+};
+// clang-format on
diff --git a/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h b/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h
index 7436991e68..31042f6a15 100644
--- a/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h
+++ b/src/openrct2/ride/coaster/meta/StandUpRollerCoaster.h
@@ -28,7 +28,7 @@ constexpr RideTypeDescriptor StandUpRollerCoasterRTD =
RIDE_TYPE_FLAGS_COMMON_COASTER | RIDE_TYPE_FLAGS_COMMON_COASTER_NON_ALT |
RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS,
- .RideModes = EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch),
+ .RideModes = EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned),
.DefaultMode = RideMode::ContinuousCircuit,
.OperatingSettings = { 7, 27, 0, 0, 0, 0 },
.Naming = { STR_RIDE_NAME_STAND_UP_ROLLER_COASTER, STR_RIDE_DESCRIPTION_STAND_UP_ROLLER_COASTER },