"Reversed Trains" Option (#19305)

* Initial commit for backwards-facing trains

* Allow persistence for reversed cars across save/load

* Make log flume turntable compatible with new reversal implementation

* Style fixes + Better implementation of inverted bank angles

* Further Style Fixes

* Code cleanup from PR feedback

* Fix GetBankRotationForDrawing function declaration

* Use update flag for reversed state

* Replace modulo operation with bit mask

* Correct guest pathing destination when entering reversed cars

* More style fixes

* Add plugin support for reversed vehicles

* Fix formatting error

* Derive reversal from ride mode for car spawning

* Formatting

* Rename function to GetPaintBankRotation

* Add reversed trains modes to Multi Dimension Coaster

* Change name of isReversed plugin API parameter for consistency

* Replace reversal operating modes with separate ride setting

* Add ALLOW_REVERSED_TRAINS flag to more ride types

* Make clang-format happy

* More Formatting

* Fix ALLOW_REVERSED_TRAINS flag on a couple rides

* Exclude flat rides from Reverse Trains tickbox when cheats are enabled

* Formatting

* Use Disable Vehicle Limits cheat for checkbox appearance condition

* Use correct swinging sprites when cars are reversed

* Update changelog and Plugin/Network/Park version numbers

* Formatting

* Add separate error String ID for clarity

* Add name to contributors.md

* Fix ride vehicle preview window with reversed trains for RCT1 train types

* Bump version numbers again

---------

Co-authored-by: Trevor Finney <8711258+finneyt@users.noreply.github.com>
This commit is contained in:
kyphii 2023-04-21 12:22:33 -04:00 committed by GitHub
parent 8f0db4cb20
commit 6dfc6225e2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 228 additions and 54 deletions

View File

@ -104,7 +104,7 @@ The following people are not part of the development team, but have been contrib
* Umar Ahmed (umar-ahmed) - MacOS file watcher
* Andrew Arnold (fidwell) - Added window support for more scenery groups.
* Josh Trzebiatowski (trzejos) - Ride and scenery filtering
* (kyphii) - Extended color selection
* (kyphii) - Extended color selection, reversed ride vehicles, misc.
* Phumdol Lookthipnapha (beam41) - Misc.
* Nikolas Parshook (nparshook) - Misc.
* Wenzhao Qiu (qwzhaox) - Misc.

View File

@ -3687,6 +3687,10 @@ STR_6580 :Reset
STR_6581 :Are you sure you want to reset all shortcut keys on this tab?
STR_6582 :Open keyboard shortcuts window
STR_6583 :{WINDOW_COLOUR_2}Reversed Trains
STR_6584 :Select to run trains backwards
STR_6585 :Cant make changes…
#############
# Scenarios #
################

View File

@ -2,6 +2,8 @@
------------------------------------------------------------------------
- Feature: [#18713] Block brakes have speed control and brakes slower than adjacent block brakes copy block brake speed when block brake open.
- Feature: [#19276] Add Powered Lifthill to Giga Coaster.
- Feature: [#19305] Add new Reversed Trains ride setting to run trains backwards.
- Feature: [#19305] [Plugin] Add “Car.isReversed” to allow individual ride vehicles to run backwards.
- Feature: [#19446] Add new color options to color dropdown.
- Feature: [#19547] Add large sloped turns to hybrid coaster and single rail coaster.
- Feature: [OpenMusic#25] Added Prehistoric ride music style.

View File

@ -2327,6 +2327,11 @@ declare global {
* The current tilt of the car in the X/Y axis.
*/
bankRotation: number;
/**
* Whether the car sprite is reversed or not.
*/
isReversed: boolean;
/**
* The colour of the car.

View File

@ -126,6 +126,7 @@ enum {
WIDX_VEHICLE_TYPE = 14,
WIDX_VEHICLE_TYPE_DROPDOWN,
WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX,
WIDX_VEHICLE_TRAINS_PREVIEW,
WIDX_VEHICLE_TRAINS,
WIDX_VEHICLE_TRAINS_INCREASE,
@ -264,9 +265,10 @@ static Widget window_ride_vehicle_widgets[] = {
MAIN_RIDE_WIDGETS,
MakeWidget ({ 7, 50}, {302, 12}, WindowWidgetType::DropdownMenu, WindowColour::Secondary ),
MakeWidget ({297, 51}, { 11, 10}, WindowWidgetType::Button, WindowColour::Secondary, STR_DROPDOWN_GLYPH ),
MakeWidget ({ 7, 147}, {302, 43}, WindowWidgetType::Scroll, WindowColour::Secondary, STR_EMPTY ),
MakeSpinnerWidgets({ 7, 196}, {145, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_RIDE_VEHICLE_COUNT, STR_MAX_VEHICLES_TIP ),
MakeSpinnerWidgets({164, 196}, {145, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_1_CAR_PER_TRAIN, STR_MAX_CARS_PER_TRAIN_TIP),
MakeWidget ({ 7, 137}, {302, 12}, WindowWidgetType::Checkbox, WindowColour::Secondary, STR_OPTION_REVERSE_TRAINS, STR_OPTION_REVERSE_TRAINS_TIP ),
MakeWidget ({ 7, 154}, {302, 43}, WindowWidgetType::Scroll, WindowColour::Secondary, STR_EMPTY ),
MakeSpinnerWidgets({ 7, 203}, {145, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_RIDE_VEHICLE_COUNT, STR_MAX_VEHICLES_TIP ),
MakeSpinnerWidgets({164, 203}, {145, 12}, WindowWidgetType::Spinner, WindowColour::Secondary, STR_1_CAR_PER_TRAIN, STR_MAX_CARS_PER_TRAIN_TIP),
WIDGETS_END,
};
@ -2670,7 +2672,7 @@ static void WindowRideVehicleMouseup(WindowBase* w, WidgetIndex widgetIndex)
*/
static void WindowRideVehicleResize(WindowBase* w)
{
WindowSetResize(*w, 316, 214, 316, 214);
WindowSetResize(*w, 316, 221, 316, 221);
}
/**
@ -2688,6 +2690,9 @@ static void WindowRideVehicleMousedown(WindowBase* w, WidgetIndex widgetIndex, W
case WIDX_VEHICLE_TYPE_DROPDOWN:
WindowRideShowVehicleTypeDropdown(w, &w->widgets[widgetIndex]);
break;
case WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX:
ride->SetReversedTrains(!ride->HasLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS));
break;
case WIDX_VEHICLE_TRAINS_INCREASE:
if (ride->NumTrains < OpenRCT2::Limits::MaxTrainsPerRide)
ride->SetNumTrains(ride->NumTrains + 1);
@ -2853,6 +2858,24 @@ static void WindowRideVehicleInvalidate(WindowBase* w)
window_ride_vehicle_widgets[WIDX_VEHICLE_CARS_PER_TRAIN_DECREASE].type = WindowWidgetType::Empty;
}
if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS)
|| (gCheatsDisableTrainLengthLimit && !ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_FLAT_RIDE)))
{
window_ride_vehicle_widgets[WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX].type = WindowWidgetType::Checkbox;
if (ride->HasLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS))
{
w->pressed_widgets |= (1uLL << WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX);
}
else
{
w->pressed_widgets &= ~(1uLL << WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX);
}
}
else
{
window_ride_vehicle_widgets[WIDX_VEHICLE_REVERSED_TRAINS_CHECKBOX].type = WindowWidgetType::Empty;
}
auto ft = Formatter::Common();
ft.Increment(6);
ft.Add<uint16_t>(carsPerTrain);
@ -2979,7 +3002,11 @@ static void WindowRideVehicleScrollpaint(WindowBase* w, DrawPixelInfo& dpi, int3
int32_t startX = std::max(2, (widget->width() - ((ride->NumTrains - 1) * 36)) / 2 - 25);
int32_t startY = widget->height() - 4;
const auto& firstCarEntry = rideEntry->Cars[RideEntryGetVehicleAtPosition(ride->subtype, ride->num_cars_per_train, 0)];
bool isReversed = ride->HasLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS);
int32_t carIndex = (isReversed) ? ride->num_cars_per_train - 1 : 0;
const auto& firstCarEntry = rideEntry
->Cars[RideEntryGetVehicleAtPosition(ride->subtype, ride->num_cars_per_train, carIndex)];
startY += firstCarEntry.tab_height;
// For each train
@ -2994,7 +3021,10 @@ static void WindowRideVehicleScrollpaint(WindowBase* w, DrawPixelInfo& dpi, int3
static_assert(std::numeric_limits<decltype(ride->num_cars_per_train)>::max() <= std::size(trainCarImages));
for (int32_t j = 0; j < ride->num_cars_per_train; j++)
{
const auto& carEntry = rideEntry->Cars[RideEntryGetVehicleAtPosition(ride->subtype, ride->num_cars_per_train, j)];
carIndex = (isReversed) ? (ride->num_cars_per_train - 1) - j : j;
const auto& carEntry = rideEntry
->Cars[RideEntryGetVehicleAtPosition(ride->subtype, ride->num_cars_per_train, carIndex)];
x += carEntry.spacing / 17432;
y -= (carEntry.spacing / 2) / 17432;
@ -3009,12 +3039,19 @@ static void WindowRideVehicleScrollpaint(WindowBase* w, DrawPixelInfo& dpi, int3
vehicleColourIndex = i;
break;
case VEHICLE_COLOUR_SCHEME_PER_VEHICLE:
vehicleColourIndex = j;
vehicleColourIndex = carIndex;
break;
}
VehicleColour vehicleColour = RideGetVehicleColour(*ride, vehicleColourIndex);
ImageIndex imageIndex = carEntry.SpriteByYaw(OpenRCT2::Entity::Yaw::BaseRotation / 2, SpriteGroupType::SlopeFlat);
if (isReversed)
{
auto baseRotation = carEntry.NumRotationSprites(SpriteGroupType::SlopeFlat);
imageIndex = carEntry.SpriteByYaw(
(imageIndex + (baseRotation / 2)) & (baseRotation - 1), SpriteGroupType::SlopeFlat);
}
imageIndex &= carEntry.TabRotationMask;
imageIndex *= carEntry.base_num_frames;
imageIndex += carEntry.base_image_id;

View File

@ -29,6 +29,7 @@ constexpr static StringId SetVehicleTypeErrorTitle[] = {
STR_RIDE_SET_VEHICLE_SET_NUM_TRAINS_FAIL,
STR_RIDE_SET_VEHICLE_SET_NUM_CARS_PER_TRAIN_FAIL,
STR_RIDE_SET_VEHICLE_TYPE_FAIL,
STR_RIDE_SET_VEHICLE_REVERSED_FAIL,
};
RideSetVehicleAction::RideSetVehicleAction(RideId rideIndex, RideSetVehicleType type, uint16_t value, uint8_t colour)
@ -87,6 +88,7 @@ GameActions::Result RideSetVehicleAction::Query() const
{
case RideSetVehicleType::NumTrains:
case RideSetVehicleType::NumCarsPerTrain:
case RideSetVehicleType::TrainsReversed:
break;
case RideSetVehicleType::RideEntry:
{
@ -184,6 +186,15 @@ GameActions::Result RideSetVehicleAction::Execute() const
}
break;
}
case RideSetVehicleType::TrainsReversed:
{
RideClearForConstruction(*ride);
ride->RemovePeeps();
ride->vehicle_change_timeout = 100;
ride->SetLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS, _value);
break;
}
default:
LOG_ERROR("Unknown vehicle command. type = %d", _type);

View File

@ -16,6 +16,7 @@ enum class RideSetVehicleType : uint8_t
NumTrains,
NumCarsPerTrain,
RideEntry,
TrainsReversed,
Count,
};

View File

@ -3748,19 +3748,20 @@ void Guest::UpdateRideAdvanceThroughEntrance()
}
auto destination = GetDestination();
auto loadPositionWithReversal = (vehicle->HasFlag(VehicleFlags::CarIsReversed)) ? -load_position : load_position;
switch (vehicle->Orientation / 8)
{
case 0:
destination.x = vehicle->x - load_position;
destination.x = vehicle->x - loadPositionWithReversal;
break;
case 1:
destination.y = vehicle->y + load_position;
destination.y = vehicle->y + loadPositionWithReversal;
break;
case 2:
destination.x = vehicle->x + load_position;
destination.x = vehicle->x + loadPositionWithReversal;
break;
case 3:
destination.y = vehicle->y - load_position;
destination.y = vehicle->y - loadPositionWithReversal;
break;
}
SetDestination(destination);

View File

@ -3986,6 +3986,10 @@ enum : uint16_t
STR_SHORTCUT_OPEN_KEYBOARD_SHORTCUTS_WINDOW = 6582,
STR_OPTION_REVERSE_TRAINS = 6583,
STR_OPTION_REVERSE_TRAINS_TIP = 6584,
STR_RIDE_SET_VEHICLE_REVERSED_FAIL = 6585,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
/* MAX_STR_COUNT = 32768 */ // MAX_STR_COUNT - upper limit for number of strings, not the current count strings
};

View File

@ -43,7 +43,7 @@
// It is used for making sure only compatible builds get connected, even within
// single OpenRCT2 version.
#define NETWORK_STREAM_VERSION "12"
#define NETWORK_STREAM_VERSION "13"
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION

View File

@ -9,10 +9,10 @@ struct ObjectRepositoryItem;
namespace OpenRCT2
{
// Current version that is saved.
constexpr uint32_t PARK_FILE_CURRENT_VERSION = 29;
constexpr uint32_t PARK_FILE_CURRENT_VERSION = 30;
// The minimum version that is forwards compatible with the current version.
constexpr uint32_t PARK_FILE_MIN_VERSION = 28;
constexpr uint32_t PARK_FILE_MIN_VERSION = 30;
// The minimum version that is backwards compatible with the current version.
// If this is increased beyond 0, uncomment the checks in ParkFile.cpp and Context.cpp!

View File

@ -3370,6 +3370,12 @@ static Vehicle* VehicleCreateCar(
}
}
vehicle->SetState(Vehicle::Status::MovingToEndOfStation);
if (ride.HasLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS))
{
vehicle->SubType = carIndex == (ride.num_cars_per_train - 1) ? Vehicle::Type::Head : Vehicle::Type::Tail;
vehicle->SetFlag(VehicleFlags::CarIsReversed);
}
}
// Loc6DDD5E:
@ -3387,11 +3393,14 @@ static TrainReference VehicleCreateTrain(
Ride& ride, const CoordsXYZ& trainPos, int32_t vehicleIndex, int32_t* remainingDistance, TrackElement* trackElement)
{
TrainReference train = { nullptr, nullptr };
bool isReversed = ride.HasLifecycleFlag(RIDE_LIFECYCLE_REVERSED_TRAINS);
for (int32_t carIndex = 0; carIndex < ride.num_cars_per_train; carIndex++)
{
auto vehicle = RideEntryGetVehicleAtPosition(ride.subtype, ride.num_cars_per_train, carIndex);
auto car = VehicleCreateCar(ride, vehicle, carIndex, vehicleIndex, trainPos, remainingDistance, trackElement);
auto carSpawnIndex = (isReversed) ? (ride.num_cars_per_train - 1) - carIndex : carIndex;
auto vehicle = RideEntryGetVehicleAtPosition(ride.subtype, ride.num_cars_per_train, carSpawnIndex);
auto car = VehicleCreateCar(ride, vehicle, carSpawnIndex, vehicleIndex, trainPos, remainingDistance, trackElement);
if (car == nullptr)
break;
@ -4661,7 +4670,15 @@ void RideUpdateVehicleColours(const Ride& ride)
colours = ride.vehicle_colours[i];
break;
case RIDE_COLOUR_SCHEME_MODE_DIFFERENT_PER_CAR:
colours = ride.vehicle_colours[std::min(carIndex, OpenRCT2::Limits::MaxCarsPerTrain - 1)];
if (vehicle->HasFlag(VehicleFlags::CarIsReversed))
{
colours = ride.vehicle_colours[std::min(
(ride.num_cars_per_train - 1) - carIndex, OpenRCT2::Limits::MaxCarsPerTrain - 1)];
}
else
{
colours = ride.vehicle_colours[std::min(carIndex, OpenRCT2::Limits::MaxCarsPerTrain - 1)];
}
break;
}
@ -5146,6 +5163,12 @@ void Ride::SetNumCarsPerVehicle(int32_t numCarsPerVehicle)
GameActions::Execute(&rideSetVehicleAction);
}
void Ride::SetReversedTrains(bool reverseTrains)
{
auto rideSetVehicleAction = RideSetVehicleAction(id, RideSetVehicleType::TrainsReversed, reverseTrains);
GameActions::Execute(&rideSetVehicleAction);
}
void Ride::SetToDefaultInspectionInterval()
{
uint8_t defaultInspectionInterval = gConfigGeneral.DefaultInspectionInterval;

View File

@ -327,6 +327,7 @@ public:
void SetNumTrains(int32_t numTrains);
void SetNumCarsPerVehicle(int32_t numCarsPerVehicle);
void SetReversedTrains(bool reversedTrains);
void UpdateMaxVehicles();
void UpdateNumberOfCircuits();
@ -455,6 +456,7 @@ enum
RIDE_LIFECYCLE_SIX_FLAGS_DEPRECATED = 1 << 19, // Not used anymore
RIDE_LIFECYCLE_FIXED_RATINGS = 1 << 20, // When set, the ratings will not be updated (useful for hacked rides).
RIDE_LIFECYCLE_RANDOM_SHOP_COLOURS = 1 << 21,
RIDE_LIFECYCLE_REVERSED_TRAINS = 1 << 22,
};
// Constants used by the ride_type->flags property at 0x008

View File

@ -347,6 +347,7 @@ enum ride_type_flags : uint64_t
RIDE_TYPE_FLAG_IS_FIRST_AID = (1uLL << 57),
RIDE_TYPE_FLAG_IS_MAZE = (1uLL << 58),
RIDE_TYPE_FLAG_IS_SPIRAL_SLIDE = (1uLL << 59),
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS = (1uLL << 60),
};
// Set on ride types that have a main colour, additional colour and support colour.

View File

@ -6351,6 +6351,10 @@ static uint8_t GetSwingSprite(int16_t swingPosition)
void Vehicle::UpdateSwingingCar()
{
int32_t dword_F64E08 = abs(_vehicleVelocityF64E08);
if (HasFlag(VehicleFlags::CarIsReversed))
{
dword_F64E08 *= -1;
}
SwingSpeed += (-SwingPosition) >> 6;
int32_t swingAmount = GetSwingAmount();
if (swingAmount < 0)

View File

@ -450,6 +450,7 @@ namespace VehicleFlags
constexpr uint32_t MoveSingleCar = (1 << 14); // OpenRCT2 Flag: Used to override UpdateMotion to move the position of
// an individual car on a train
constexpr uint32_t Crashed = (1 << 15); // Car displays as smoke plume
constexpr uint32_t CarIsReversed = (1 << 16); // Car is displayed running backwards
} // namespace VehicleFlags
enum

View File

@ -935,6 +935,21 @@ const VehicleBoundBox VehicleBoundboxes[16][224] = {
}
};
// Opposite Pitch values for reversed cars
const uint8_t PitchInvertTable[] = {
0, // Flat Track
5, 6, 7, 8, 1, 2, 3, 4, // Slopes 1
17, 18, 19, 20, 21, 22, 23, 16, 9, 10, 11, 12, 13, 14, 15, // Vertical Loop
29, 30, 31, 32, 33, 24, 25, 26, 27, 28, 39, 40, 41, 42, 43, 34, 35, 36, 37, 38, // Corkscrews
0, 0, 0, 0, 0, 0, // Helices
53, 54, 55, 50, 51, 52, // Slopes 2
56, 57, 58, // Zero-G Rolls
0 // 59 = Spiral Lift. This is the only pitch with no corresponding pitch down, so flat will be used instead
};
// Opposite Bank values for reversed cars
const uint8_t BankInvertTable[] = { 0, 3, 4, 1, 2, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 15, 18, 19, 16, 17 };
#pragma endregion
#pragma region VehiclePaintUtil
@ -1028,6 +1043,12 @@ static void VehicleSpritePaintRestraints(
vehicle_sprite_paint(session, vehicle, spriteNum, VehicleBoundboxes[carEntry->draw_order][boundingBoxNum], z, carEntry);
}
// Returns the opposite of the bank angle for reversed cars, normal bank angle otherwise
static uint8_t GetPaintBankRotation(const Vehicle* vehicle)
{
return (vehicle->HasFlag(VehicleFlags::CarIsReversed)) ? BankInvertTable[vehicle->bank_rotation] : vehicle->bank_rotation;
}
#pragma endregion
#pragma region FlatSlope
@ -1349,7 +1370,7 @@ static void VehiclePitchFlat(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3DE4:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchFlatUnbanked(session, vehicle, imageDirection, z, carEntry);
@ -1506,7 +1527,7 @@ static void VehiclePitchUp12(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3C04:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchUp12Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -1788,7 +1809,7 @@ static void VehiclePitchUp25(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3CA4:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchUp25Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -1999,7 +2020,7 @@ static void VehiclePitchUp42BankedRight90(
static void VehiclePitchUp42(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchUp42Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -2082,7 +2103,7 @@ static void VehiclePitchUp60BankedRight22(
static void VehiclePitchUp60(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchUp60Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -2189,7 +2210,7 @@ static void VehiclePitchDown12(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3C54:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchDown12Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -2506,7 +2527,7 @@ static void VehiclePitchDown25(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3CF4:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchDown25Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -2716,7 +2737,7 @@ static void VehiclePitchDown42BankedRight90(
static void VehiclePitchDown42(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchDown42Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -2799,7 +2820,7 @@ static void VehiclePitchDown60BankedRight22(
static void VehiclePitchDown60(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchDown60Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -3225,7 +3246,7 @@ static void VehiclePitchUp8(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3D44:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchUp8Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -3467,7 +3488,7 @@ static void VehiclePitchDown8(
PaintSession& session, const Vehicle* vehicle, int32_t imageDirection, int32_t z, const CarEntry* carEntry)
{
// 0x009A3D94:
switch (vehicle->bank_rotation)
switch (GetPaintBankRotation(vehicle))
{
case 0:
VehiclePitchDown8Unbanked(session, vehicle, imageDirection, z, carEntry);
@ -3907,7 +3928,17 @@ void VehicleVisualDefault(
{
if (vehicle->Pitch < std::size(PaintFunctionsByPitch))
{
PaintFunctionsByPitch[vehicle->Pitch](session, vehicle, imageDirection, z, carEntry);
if (vehicle->HasFlag(VehicleFlags::CarIsReversed))
{
auto imagePitch = PitchInvertTable[vehicle->Pitch];
auto imageYaw = (imageDirection + (OpenRCT2::Entity::Yaw::BaseRotation / 2))
& (OpenRCT2::Entity::Yaw::BaseRotation - 1);
PaintFunctionsByPitch[imagePitch](session, vehicle, imageYaw, z, carEntry);
}
else
{
PaintFunctionsByPitch[vehicle->Pitch](session, vehicle, imageDirection, z, carEntry);
}
}
}

View File

@ -25,7 +25,8 @@ constexpr const RideTypeDescriptor ClassicMiniRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionJuniorRC),
SET_FIELD(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_ALLOW_DOORS_ON_TRACK | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS),
RIDE_TYPE_FLAG_ALLOW_DOORS_ON_TRACK | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 17, 16, -1 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor ClassicWoodenRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionClassicWoodenRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 68, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor CorkscrewRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionCorkscrewRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch, RideMode::ReverseInclineLaunchedShuttle)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 25, 25, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor GigaCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionGigaRC),
SET_FIELD(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_CABLE_LIFT_HILL),
RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_ALLOW_CABLE_LIFT_HILL |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 17, 68, 1 }),

View File

@ -25,7 +25,8 @@ constexpr const RideTypeDescriptor HeartlineTwisterCoasterRTD =
SET_FIELD(StartTrackPiece, TrackElemType::EndStation),
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionHeartlineTwisterRC),
SET_FIELD(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_FLAGS_COMMON_COASTER | RIDE_TYPE_FLAGS_COMMON_COASTER_NON_ALT | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 25, 25, 0 }),

View File

@ -24,7 +24,7 @@ constexpr const RideTypeDescriptor HybridCoasterRTD =
SET_FIELD(TrackPaintFunction, HybridRC::GetTrackPaintFunction),
SET_FIELD(Flags, RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_MAIN | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS | 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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 30, 15, 52, 0 }),

View File

@ -27,7 +27,8 @@ constexpr const RideTypeDescriptor HyperTwisterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionBolligerMabillard<METAL_SUPPORTS_TUBES>),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 17, 68, 0 }),

View File

@ -25,7 +25,8 @@ constexpr const RideTypeDescriptor HypercoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionCorkscrewRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch, RideMode::ReverseInclineLaunchedShuttle)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 25, 25, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor InvertedImpulseCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionInvertedImpulseRC),
SET_FIELD(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_IS_SUSPENDED),
RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_IS_SUSPENDED |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch)),
SET_FIELD(DefaultMode, RideMode::PoweredLaunchPasstrough),
SET_FIELD(OperatingSettings, { 10, 33, 30, 25, 25, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor InvertedRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionInvertedRC),
SET_FIELD(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_IS_SUSPENDED),
RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_IS_SUSPENDED |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 7, 27, 0, 0, 38, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor JuniorRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionJuniorRC),
SET_FIELD(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_ALLOW_DOORS_ON_TRACK | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS),
RIDE_TYPE_FLAG_ALLOW_DOORS_ON_TRACK | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 17, 16, -1 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor LIMLaunchedRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionLimLaunchedRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch, RideMode::PoweredLaunchBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::PoweredLaunchPasstrough),
SET_FIELD(OperatingSettings, { 10, 31, 26, 18, 52, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor LoopingRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionLoopingRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 26, 18, 18, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor MineRideRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionMineRide),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 0, 0 }),

View File

@ -27,7 +27,8 @@ constexpr const RideTypeDescriptor MineTrainCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionMineTrainRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 0, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor MiniRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionMiniRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 68, 1 }),

View File

@ -27,7 +27,8 @@ constexpr const RideTypeDescriptor MultiDimensionRollerCoasterRTD =
SET_FIELD(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_HAS_ALTERNATIVE_TRACK_TYPE | RIDE_TYPE_FLAG_PEEP_CHECK_GFORCES |
RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_HAS_SEAT_ROTATION),
RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS | RIDE_TYPE_FLAG_HAS_SEAT_ROTATION |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 25, 25, 0 }),

View File

@ -24,7 +24,7 @@ constexpr const RideTypeDescriptor ReverseFreefallCoasterRTD =
SET_FIELD(CoveredTrackPieces, {}),
SET_FIELD(StartTrackPiece, TrackElemType::EndStation),
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionReverseFreefallRC),
SET_FIELD(Flags, RIDE_TYPE_FLAGS_TRACK_HAS_3_COLOURS | RIDE_TYPE_FLAGS_COMMON_COASTER | RIDE_TYPE_FLAGS_COMMON_COASTER_NON_ALT),
SET_FIELD(Flags, RIDE_TYPE_FLAGS_TRACK_HAS_3_COLOURS | RIDE_TYPE_FLAGS_COMMON_COASTER | RIDE_TYPE_FLAGS_COMMON_COASTER_NON_ALT | RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::LimPoweredLaunch)),
SET_FIELD(DefaultMode, RideMode::LimPoweredLaunch),
SET_FIELD(OperatingSettings, { 7, 30, 30, 40, 40, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor SideFrictionRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionSideFrictionRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 0, 0 }),

View File

@ -24,7 +24,8 @@ constexpr const RideTypeDescriptor SingleRailRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, SingleRailRC::GetTrackPaintFunction),
SET_FIELD(Flags, RIDE_TYPE_FLAGS_TRACK_HAS_3_COLOURS | RIDE_TYPE_FLAG_HAS_TRACK_COLOUR_SUPPORTS | 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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 30, 15, 52, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor StandUpRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionStandUpRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle, RideMode::PoweredLaunchPasstrough, RideMode::PoweredLaunch)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 7, 27, 0, 0, 0, 0 }),

View File

@ -28,7 +28,8 @@ constexpr const RideTypeDescriptor TwisterRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionBolligerMabillard<METAL_SUPPORTS_TUBES>),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 10, 27, 30, 17, 68, 0 }),

View File

@ -26,7 +26,8 @@ constexpr const RideTypeDescriptor WoodenRollerCoasterRTD =
SET_FIELD(TrackPaintFunction, GetTrackPaintFunctionWoodenRC),
SET_FIELD(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_PEEP_CHECK_GFORCES | RIDE_TYPE_FLAG_ALLOW_MULTIPLE_CIRCUITS |
RIDE_TYPE_FLAG_ALLOW_REVERSED_TRAINS),
SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit, RideMode::ContinuousCircuitBlockSectioned, RideMode::ReverseInclineLaunchedShuttle)),
SET_FIELD(DefaultMode, RideMode::ContinuousCircuit),
SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 68, 0 }),

View File

@ -47,7 +47,7 @@ namespace OpenRCT2
namespace OpenRCT2::Scripting
{
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 74;
static constexpr int32_t OPENRCT2_PLUGIN_API_VERSION = 75;
// Versions marking breaking changes.
static constexpr int32_t API_VERSION_33_PEEP_DEPRECATION = 33;

View File

@ -71,6 +71,7 @@ namespace OpenRCT2::Scripting
dukglue_register_property(ctx, &ScVehicle::acceleration_get, &ScVehicle::acceleration_set, "acceleration");
dukglue_register_property(ctx, &ScVehicle::velocity_get, &ScVehicle::velocity_set, "velocity");
dukglue_register_property(ctx, &ScVehicle::bankRotation_get, &ScVehicle::bankRotation_set, "bankRotation");
dukglue_register_property(ctx, &ScVehicle::isReversed_get, &ScVehicle::isReversed_set, "isReversed");
dukglue_register_property(ctx, &ScVehicle::colours_get, &ScVehicle::colours_set, "colours");
dukglue_register_property(ctx, &ScVehicle::trackLocation_get, &ScVehicle::trackLocation_set, "trackLocation");
dukglue_register_property(ctx, &ScVehicle::trackProgress_get, nullptr, "trackProgress");
@ -332,6 +333,28 @@ namespace OpenRCT2::Scripting
}
}
bool ScVehicle::isReversed_get() const
{
auto vehicle = GetVehicle();
return vehicle != nullptr ? vehicle->HasFlag(VehicleFlags::CarIsReversed) : false;
}
void ScVehicle::isReversed_set(bool value)
{
ThrowIfGameStateNotMutable();
auto vehicle = GetVehicle();
if (vehicle != nullptr)
{
if (value)
{
vehicle->SetFlag(VehicleFlags::CarIsReversed);
}
else
{
vehicle->ClearFlag(VehicleFlags::CarIsReversed);
}
}
}
DukValue ScVehicle::colours_get() const
{
auto ctx = GetContext()->GetScriptEngine().GetContext();

View File

@ -67,6 +67,9 @@ namespace OpenRCT2::Scripting
uint8_t bankRotation_get() const;
void bankRotation_set(uint8_t value);
bool isReversed_get() const;
void isReversed_set(bool value);
DukValue colours_get() const;
void colours_set(const DukValue& value);