From 60d1e94046abb0302433dbd6848a7b8412424b97 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Sun, 10 Jan 2021 22:38:02 +0100 Subject: [PATCH] Close #7059: Implement landscape doors on Ghost Train (#13636) * Implement landscape door updating * Implement door drawing for Ghost Train * Amend changelog and bump network version * Apply review requests * Always return default seat rotation for ride types with landscape doors * Fix comment * Update replays Co-authored-by: duncanspumpkin --- CMakeLists.txt | 4 +- distribution/changelog.txt | 1 + openrct2.proj | 4 +- src/openrct2/actions/TrackPlaceAction.cpp | 5 ++ src/openrct2/network/NetworkBase.cpp | 2 +- src/openrct2/rct1/S4Importer.cpp | 15 +++- src/openrct2/rct12/RCT12.cpp | 12 +++ src/openrct2/rct12/RCT12.h | 5 +- src/openrct2/rct2/S6Exporter.cpp | 16 +++- src/openrct2/rct2/S6Importer.cpp | 10 ++- src/openrct2/ride/RideData.h | 1 + src/openrct2/ride/Track.cpp | 4 + src/openrct2/ride/Vehicle.cpp | 56 +++++++++++++ src/openrct2/ride/Vehicle.h | 2 + src/openrct2/ride/gentle/GhostTrain.cpp | 94 +++++++++++++++++++--- src/openrct2/ride/gentle/meta/GhostTrain.h | 3 +- src/openrct2/world/TileElement.h | 7 ++ test/testpaint/Compat.cpp | 4 + 18 files changed, 220 insertions(+), 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5475cfb535..ad3f2bb95a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,8 @@ set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip") set(OBJECTS_SHA1 "151424d24b1d49a167932b58319bedaa6ec368e9") -set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.24/replays.zip") -set(REPLAYS_SHA1 "58AD8B2D2A804D2FEE787597A2A4DEADBF4D2A65") +set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.25/replays.zip") +set(REPLAYS_SHA1 "DA3E595E4D0231934F1DCFC3B540097CE2ED1B17") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(WITH_TESTS "Build tests") diff --git a/distribution/changelog.txt b/distribution/changelog.txt index a8a3794242..a7aa44c1fe 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -2,6 +2,7 @@ ------------------------------------------------------------------------ - Feature: [#6677] Add Discord RPC to macOS builds. - Feature: [#6844] Enhanced track designer with ability to add/remove scenery and footpaths. +- Feature: [#7059] Landscape doors for the Ghost Train. - Feature: [#11859] Add on-ride photo section to Air Powered Vertical and Reverse Freefall Coaster. - Feature: [#12307] Allow extraction of GOG installer via innoextract (for Linux users). - Feature: [#13057] Make GameAction flags accessible by plugins. diff --git a/openrct2.proj b/openrct2.proj index 39029076fb..83e25c0753 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -48,8 +48,8 @@ 304d13a126c15bf2c86ff13b81a2f2cc1856ac8d https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip 151424d24b1d49a167932b58319bedaa6ec368e9 - https://github.com/OpenRCT2/replays/releases/download/v0.0.24/replays.zip - 58AD8B2D2A804D2FEE787597A2A4DEADBF4D2A65 + https://github.com/OpenRCT2/replays/releases/download/v0.0.25/replays.zip + DA3E595E4D0231934F1DCFC3B540097CE2ED1B17 diff --git a/src/openrct2/actions/TrackPlaceAction.cpp b/src/openrct2/actions/TrackPlaceAction.cpp index c4caec13b8..0bbc903265 100644 --- a/src/openrct2/actions/TrackPlaceAction.cpp +++ b/src/openrct2/actions/TrackPlaceAction.cpp @@ -629,6 +629,11 @@ GameActions::Result::Ptr TrackPlaceAction::Execute() const { tileElement->AsTrack()->SetBrakeBoosterSpeed(_brakeSpeed); } + else if (ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) + { + tileElement->AsTrack()->SetDoorAState(LANDSCAPE_DOOR_CLOSED); + tileElement->AsTrack()->SetDoorBState(LANDSCAPE_DOOR_CLOSED); + } else { tileElement->AsTrack()->SetSeatRotation(_seatRotation); diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index d836a166d6..dcc92f51eb 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -34,7 +34,7 @@ // This string specifies which version of network stream current build uses. // It is used for making sure only compatible builds get connected, even within // single OpenRCT2 version. -#define NETWORK_STREAM_VERSION "10" +#define NETWORK_STREAM_VERSION "11" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/rct1/S4Importer.cpp b/src/openrct2/rct1/S4Importer.cpp index 788328f5bf..c90b684e3b 100644 --- a/src/openrct2/rct1/S4Importer.cpp +++ b/src/openrct2/rct1/S4Importer.cpp @@ -2100,6 +2100,7 @@ private: { auto dst2 = dst->AsTrack(); auto src2 = src->AsTrack(); + auto rideType = _s4.rides[src2->GetRideIndex()].type; dst2->SetTrackType(src2->GetTrackType()); dst2->SetSequenceIndex(src2->GetSequenceIndex()); @@ -2108,12 +2109,18 @@ private: dst2->SetHasChain(src2->HasChain()); dst2->SetHasCableLift(false); dst2->SetInverted(src2->IsInverted()); - dst2->SetDoorAState(src2->GetDoorAState()); - dst2->SetDoorBState(src2->GetDoorBState()); dst2->SetStationIndex(src2->GetStationIndex()); dst2->SetHasGreenLight(src2->HasGreenLight()); dst2->SetIsIndestructible(src2->IsIndestructible()); - dst2->SetSeatRotation(DEFAULT_SEAT_ROTATION); + if (rideType == RCT1_RIDE_TYPE_GHOST_TRAIN) + { + dst2->SetDoorAState(src2->GetDoorAState()); + dst2->SetDoorBState(src2->GetDoorBState()); + } + else + { + dst2->SetSeatRotation(DEFAULT_SEAT_ROTATION); + } // Skipping IsHighlighted() auto trackType = dst2->GetTrackType(); @@ -2127,7 +2134,7 @@ private: } // This has to be done last, since the maze entry shares fields with the colour and sequence fields. - if (_s4.rides[src2->GetRideIndex()].type == RIDE_TYPE_MAZE) + if (rideType == RIDE_TYPE_MAZE) { dst2->SetMazeEntry(src2->GetMazeEntry()); } diff --git a/src/openrct2/rct12/RCT12.cpp b/src/openrct2/rct12/RCT12.cpp index 963da8f07c..d8128a4925 100644 --- a/src/openrct2/rct12/RCT12.cpp +++ b/src/openrct2/rct12/RCT12.cpp @@ -290,6 +290,18 @@ uint8_t RCT12TrackElement::GetDoorBState() const return (colour & RCT12_TRACK_ELEMENT_DOOR_B_MASK) >> 5; } +void RCT12TrackElement::SetDoorAState(uint8_t newState) +{ + colour &= ~RCT12_TRACK_ELEMENT_DOOR_B_MASK; + colour |= ((newState << 2) & RCT12_TRACK_ELEMENT_DOOR_B_MASK); +} + +void RCT12TrackElement::SetDoorBState(uint8_t newState) +{ + colour &= ~RCT12_TRACK_ELEMENT_DOOR_B_MASK; + colour |= ((newState << 5) & RCT12_TRACK_ELEMENT_DOOR_B_MASK); +} + bool RCT12TrackElement::IsIndestructible() const { return (flags & RCT12_TILE_ELEMENT_FLAG_INDESTRUCTIBLE_TRACK_PIECE) != 0; diff --git a/src/openrct2/rct12/RCT12.h b/src/openrct2/rct12/RCT12.h index d2542aabbc..6d09cc894d 100644 --- a/src/openrct2/rct12/RCT12.h +++ b/src/openrct2/rct12/RCT12.h @@ -511,10 +511,11 @@ public: uint8_t GetSeatRotation() const; uint16_t GetMazeEntry() const; uint8_t GetPhotoTimeout() const; - // Used in RCT1, will be reintroduced at some point. - // (See https://github.com/OpenRCT2/OpenRCT2/issues/7059) + // RCT1 feature, reintroduced by OpenRCT2. See https://github.com/OpenRCT2/OpenRCT2/issues/7059 uint8_t GetDoorAState() const; uint8_t GetDoorBState() const; + void SetDoorAState(uint8_t newState); + void SetDoorBState(uint8_t newState); void SetTrackType(uint8_t newEntryIndex); void SetSequenceIndex(uint8_t newSequenceIndex); diff --git a/src/openrct2/rct2/S6Exporter.cpp b/src/openrct2/rct2/S6Exporter.cpp index 5e0dedbb77..89bf503232 100644 --- a/src/openrct2/rct2/S6Exporter.cpp +++ b/src/openrct2/rct2/S6Exporter.cpp @@ -1511,7 +1511,7 @@ void S6Exporter::ExportTileElement(RCT12TileElement* dst, TileElement* src) dst2->SetPhotoTimeout(src2->GetPhotoTimeout()); dst2->SetBlockBrakeClosed(src2->BlockBrakeClosed()); dst2->SetIsIndestructible(src2->IsIndestructible()); - dst2->SetSeatRotation(src2->GetSeatRotation()); + // Skipping IsHighlighted() // This has to be done last, since the maze entry shares fields with the colour and sequence fields. @@ -1522,6 +1522,20 @@ void S6Exporter::ExportTileElement(RCT12TileElement* dst, TileElement* src) { dst2->SetMazeEntry(src2->GetMazeEntry()); } + else if (ride->type == RIDE_TYPE_GHOST_TRAIN) + { + dst2->SetDoorAState(src2->GetDoorAState()); + dst2->SetDoorBState(src2->GetDoorBState()); + } + else + { + dst2->SetSeatRotation(src2->GetSeatRotation()); + } + } + // _Should_ not happen, but if it does, pick the most likely option. + else + { + dst2->SetSeatRotation(src2->GetSeatRotation()); } break; diff --git a/src/openrct2/rct2/S6Importer.cpp b/src/openrct2/rct2/S6Importer.cpp index 7bc48be7d7..e706d1d942 100644 --- a/src/openrct2/rct2/S6Importer.cpp +++ b/src/openrct2/rct2/S6Importer.cpp @@ -1126,7 +1126,6 @@ public: dst2->SetHasGreenLight(src2->HasGreenLight()); dst2->SetBlockBrakeClosed(src2->BlockBrakeClosed()); dst2->SetIsIndestructible(src2->IsIndestructible()); - dst2->SetSeatRotation(src2->GetSeatRotation()); // Skipping IsHighlighted() auto trackType = dst2->GetTrackType(); @@ -1145,6 +1144,15 @@ public: { dst2->SetMazeEntry(src2->GetMazeEntry()); } + else if (rideType == RIDE_TYPE_GHOST_TRAIN) + { + dst2->SetDoorAState(src2->GetDoorAState()); + dst2->SetDoorBState(src2->GetDoorBState()); + } + else + { + dst2->SetSeatRotation(src2->GetSeatRotation()); + } break; } diff --git a/src/openrct2/ride/RideData.h b/src/openrct2/ride/RideData.h index 7f83add5a5..bc855ccd36 100644 --- a/src/openrct2/ride/RideData.h +++ b/src/openrct2/ride/RideData.h @@ -258,6 +258,7 @@ enum ride_type_flags : uint64_t RIDE_TYPE_FLAG_LIST_VEHICLES_SEPARATELY = (1ULL << 48), RIDE_TYPE_FLAG_SUPPORTS_LEVEL_CROSSINGS = (1ULL << 49), RIDE_TYPE_FLAG_IS_SUSPENDED = (1ULL << 50), + RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS = (1ULL << 51), }; // Set on ride types that have a main colour, additional colour and support colour. diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index 41584bdc23..3b34b156ad 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -1211,6 +1211,10 @@ bool TrackTypeHasSpeedSetting(track_type_t trackType) uint8_t TrackElement::GetSeatRotation() const { + const auto* ride = get_ride(GetRideIndex()); + if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) + return DEFAULT_SEAT_ROTATION; + return ColourScheme >> 4; } diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index 2b267a8c0c..33111ecbdc 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -7483,6 +7483,44 @@ void Vehicle::UpdateSceneryDoor() const { wallCoords, static_cast(direction) }, TrackLocation, next_vehicle_on_train == SPRITE_INDEX_NULL); } +template static void AnimateLandscapeDoor(TrackElement* trackElement, bool isLastVehicle) +{ + auto doorState = isBackwards ? trackElement->GetDoorAState() : trackElement->GetDoorBState(); + if (!isLastVehicle && doorState == LANDSCAPE_DOOR_CLOSED) + { + if (isBackwards) + trackElement->SetDoorAState(LANDSCAPE_DOOR_OPEN); + else + trackElement->SetDoorBState(LANDSCAPE_DOOR_OPEN); + // TODO: play door open sound + } + + if (isLastVehicle) + { + if (isBackwards) + trackElement->SetDoorAState(LANDSCAPE_DOOR_CLOSED); + else + trackElement->SetDoorBState(LANDSCAPE_DOOR_CLOSED); + // TODO: play door close sound + } +} + +void Vehicle::UpdateLandscapeDoor() const +{ + const auto* currentRide = GetRide(); + if (currentRide == nullptr || !currentRide->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) + { + return; + } + + auto coords = CoordsXYZ{ x, y, TrackLocation.z }.ToTileStart(); + auto* tileElement = map_get_track_element_at_from_ride(coords, ride); + if (tileElement != nullptr && tileElement->GetType() == static_cast(TileElementType::Track)) + { + AnimateLandscapeDoor(tileElement->AsTrack(), next_vehicle_on_train == SPRITE_INDEX_NULL); + } +} + /** * * rct2: 0x006DB38B @@ -7539,6 +7577,22 @@ void Vehicle::UpdateSceneryDoorBackwards() const { wallCoords, static_cast(direction) }, TrackLocation, next_vehicle_on_train == SPRITE_INDEX_NULL); } +void Vehicle::UpdateLandscapeDoorBackwards() const +{ + const auto* currentRide = GetRide(); + if (currentRide == nullptr || !currentRide->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) + { + return; + } + + auto coords = CoordsXYZ{ TrackLocation, TrackLocation.z }; + auto* tileElement = map_get_track_element_at_from_ride(coords, ride); + if (tileElement != nullptr && tileElement->GetType() == static_cast(TileElementType::Track)) + { + AnimateLandscapeDoor(tileElement->AsTrack(), next_vehicle_on_train == SPRITE_INDEX_NULL); + } +} + static void vehicle_update_play_water_splash_sound() { if (_vehicleVelocityF64E08 <= BLOCK_BRAKE_BASE_SPEED) @@ -7970,6 +8024,7 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, Ride* cur // Change from original: this used to check if the vehicle allowed doors. UpdateSceneryDoor(); + UpdateLandscapeDoor(); bool isGoingBack = false; switch (TrackSubposition) @@ -8113,6 +8168,7 @@ bool Vehicle::UpdateTrackMotionForwardsGetNewTrack(uint16_t trackType, Ride* cur } // Change from original: this used to check if the vehicle allowed doors. UpdateSceneryDoorBackwards(); + UpdateLandscapeDoorBackwards(); return true; } diff --git a/src/openrct2/ride/Vehicle.h b/src/openrct2/ride/Vehicle.h index 91364cd072..347b42e9c6 100644 --- a/src/openrct2/ride/Vehicle.h +++ b/src/openrct2/ride/Vehicle.h @@ -450,6 +450,8 @@ private: void UpdateGoKartAttemptSwitchLanes(); void UpdateSceneryDoor() const; void UpdateSceneryDoorBackwards() const; + void UpdateLandscapeDoor() const; + void UpdateLandscapeDoorBackwards() const; }; struct train_ref diff --git a/src/openrct2/ride/gentle/GhostTrain.cpp b/src/openrct2/ride/gentle/GhostTrain.cpp index 654bb03ea5..6dea62282e 100644 --- a/src/openrct2/ride/gentle/GhostTrain.cpp +++ b/src/openrct2/ride/gentle/GhostTrain.cpp @@ -127,6 +127,42 @@ static constexpr const uint32_t ghost_train_track_pieces_brakes[4] = { SPR_GHOST_TRAIN_TRACK_BRAKES_NW_SE, }; +static constexpr const uint8_t doorOpeningOutwardsToImage[] = { + TUNNEL_DOORS_2, // Closed + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_3, // Half open + TUNNEL_DOORS_4, // Fully open + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_2, // Unused? +}; + +static constexpr const uint8_t doorOpeningInwardsToImage[] = { + TUNNEL_DOORS_2, // Closed + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_5, // Half open + TUNNEL_DOORS_6, // Fully open + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_2, // Unused? + TUNNEL_DOORS_2, // Unused? +}; + +static uint8_t get_tunnel_doors_image_straight_flat(const TrackElement* trackElement, uint8_t direction) +{ + switch (direction) + { + case 0: + return doorOpeningInwardsToImage[trackElement->GetDoorAState()]; + case 1: + return doorOpeningOutwardsToImage[trackElement->GetDoorBState()]; + case 2: + return doorOpeningOutwardsToImage[trackElement->GetDoorBState()]; + case 3: + return doorOpeningInwardsToImage[trackElement->GetDoorAState()]; + } + return TUNNEL_DOORS_2; +} + /** rct2: 0x00770BEC */ static void paint_ghost_train_track_flat( paint_session* session, ride_id_t rideIndex, uint8_t trackSequence, uint8_t direction, int32_t height, @@ -136,7 +172,8 @@ static void paint_ghost_train_track_flat( PaintAddImageAsParentRotated(session, direction, imageId, 0, 0, 32, 20, 3, height, 0, 6, height); - paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_0); + auto tunnelImage = get_tunnel_doors_image_straight_flat(tileElement->AsTrack(), direction); + paint_util_push_tunnel_rotated(session, direction, height, tunnelImage); if (track_paint_util_should_paint_supports(session->MapPosition)) { @@ -190,6 +227,17 @@ static void paint_ghost_train_track_flat_to_25_deg_up( paint_session* session, ride_id_t rideIndex, uint8_t trackSequence, uint8_t direction, int32_t height, const TileElement* tileElement) { + bool isBackwards = tileElement->AsTrack()->GetTrackType() == TrackElemType::Down25ToFlat; + uint8_t doorImage; + if (!isBackwards) + { + doorImage = doorOpeningInwardsToImage[tileElement->AsTrack()->GetDoorAState()]; + } + else + { + doorImage = doorOpeningOutwardsToImage[tileElement->AsTrack()->GetDoorBState()]; + } + uint32_t imageId = ghost_train_track_pieces_flat_to_25_deg_up[direction][0] | session->TrackColours[SCHEME_TRACK]; PaintAddImageAsParentRotated(session, direction, imageId, 0, 0, 32, 20, 3, height, 0, 6, height); @@ -204,7 +252,7 @@ static void paint_ghost_train_track_flat_to_25_deg_up( switch (direction) { case 0: - paint_util_push_tunnel_left(session, height, TUNNEL_0); + paint_util_push_tunnel_left(session, height, doorImage); break; case 1: paint_util_push_tunnel_right(session, height, TUNNEL_2); @@ -213,7 +261,7 @@ static void paint_ghost_train_track_flat_to_25_deg_up( paint_util_push_tunnel_left(session, height, TUNNEL_2); break; case 3: - paint_util_push_tunnel_right(session, height, TUNNEL_0); + paint_util_push_tunnel_right(session, height, doorImage); break; } @@ -255,10 +303,12 @@ static void paint_ghost_train_track_25_deg_up_to_flat( paint_util_push_tunnel_left(session, height - 8, TUNNEL_0); break; case 1: - paint_util_push_tunnel_right(session, height + 8, TUNNEL_12); + paint_util_push_tunnel_right( + session, height + 8, doorOpeningOutwardsToImage[tileElement->AsTrack()->GetDoorBState()]); break; case 2: - paint_util_push_tunnel_left(session, height + 8, TUNNEL_12); + paint_util_push_tunnel_left( + session, height + 8, doorOpeningOutwardsToImage[tileElement->AsTrack()->GetDoorBState()]); break; case 3: paint_util_push_tunnel_right(session, height - 8, TUNNEL_0); @@ -288,10 +338,12 @@ static void paint_ghost_train_track_flat_to_25_deg_down( paint_util_push_tunnel_left(session, height - 8, TUNNEL_0); break; case 1: - paint_util_push_tunnel_right(session, height + 8, TUNNEL_0); + paint_util_push_tunnel_right( + session, height + 8, doorOpeningInwardsToImage[tileElement->AsTrack()->GetDoorAState()]); break; case 2: - paint_util_push_tunnel_left(session, height + 8, TUNNEL_0); + paint_util_push_tunnel_left( + session, height + 8, doorOpeningInwardsToImage[tileElement->AsTrack()->GetDoorAState()]); break; case 3: paint_util_push_tunnel_right(session, height - 8, TUNNEL_0); @@ -355,7 +407,12 @@ static void paint_ghost_train_track_right_quarter_turn_3_tiles( session, 3, height, direction, trackSequence, session->TrackColours[SCHEME_TRACK], ghost_train_track_pieces_quarter_turn_3_tiles, nullptr, defaultRightQuarterTurn3TilesBoundLengths, defaultRightQuarterTurn3TilesBoundOffsets); - track_paint_util_right_quarter_turn_3_tiles_tunnel(session, height, direction, trackSequence, TUNNEL_0); + const auto* trackElement = tileElement->AsTrack(); + bool isBackwards = trackElement->GetTrackType() == TrackElemType::LeftQuarterTurn3Tiles; + bool isDoorA = (!isBackwards && trackSequence == 0) || (isBackwards && trackSequence == 3); + auto tunnelType = isDoorA ? doorOpeningInwardsToImage[trackElement->GetDoorAState()] + : doorOpeningOutwardsToImage[trackElement->GetDoorBState()]; + track_paint_util_right_quarter_turn_3_tiles_tunnel(session, height, direction, trackSequence, tunnelType); switch (trackSequence) { @@ -398,9 +455,22 @@ static void paint_ghost_train_track_left_quarter_turn_1_tile( paint_session* session, ride_id_t rideIndex, uint8_t trackSequence, uint8_t direction, int32_t height, const TileElement* tileElement) { + bool isBackwards = tileElement->AsTrack()->GetTrackType() == TrackElemType::RightQuarterTurn1Tile; + uint8_t tunnelStartImage, tunnelEndImage; + if (!isBackwards) + { + tunnelStartImage = doorOpeningInwardsToImage[tileElement->AsTrack()->GetDoorAState()]; + tunnelEndImage = doorOpeningOutwardsToImage[tileElement->AsTrack()->GetDoorBState()]; + } + else + { + tunnelStartImage = doorOpeningOutwardsToImage[tileElement->AsTrack()->GetDoorBState()]; + tunnelEndImage = doorOpeningInwardsToImage[tileElement->AsTrack()->GetDoorAState()]; + } + track_paint_util_left_quarter_turn_1_tile_paint( session, 3, height, 0, direction, session->TrackColours[SCHEME_TRACK], ghost_train_track_pieces_quarter_turn_1_tile); - track_paint_util_left_quarter_turn_1_tile_tunnel(session, direction, height, 0, TUNNEL_0, 0, TUNNEL_0); + track_paint_util_left_quarter_turn_1_tile_tunnel(session, direction, height, 0, tunnelStartImage, 0, tunnelEndImage); metal_a_supports_paint_setup(session, METAL_SUPPORTS_BOXED, 4, 0, height, session->TrackColours[SCHEME_SUPPORTS]); paint_util_set_segment_support_height(session, SEGMENTS_ALL, 0xFFFF, 0); @@ -427,7 +497,8 @@ static void paint_ghost_train_track_spinning_tunnel( track_paint_util_spinning_tunnel_paint(session, 3, height, direction); - paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_0); + auto tunnelImage = get_tunnel_doors_image_straight_flat(tileElement->AsTrack(), direction); + paint_util_push_tunnel_rotated(session, direction, height, tunnelImage); wooden_a_supports_paint_setup(session, (direction & 1), 0, height, session->TrackColours[SCHEME_MISC], nullptr); @@ -444,7 +515,8 @@ static void paint_ghost_train_track_brakes( PaintAddImageAsParentRotated(session, direction, imageId, 0, 0, 32, 20, 3, height, 0, 6, height); - paint_util_push_tunnel_rotated(session, direction, height, TUNNEL_0); + auto tunnelImage = get_tunnel_doors_image_straight_flat(tileElement->AsTrack(), direction); + paint_util_push_tunnel_rotated(session, direction, height, tunnelImage); if (track_paint_util_should_paint_supports(session->MapPosition)) { diff --git a/src/openrct2/ride/gentle/meta/GhostTrain.h b/src/openrct2/ride/gentle/meta/GhostTrain.h index 7d1fd0df29..a2bbe1bc3f 100644 --- a/src/openrct2/ride/gentle/meta/GhostTrain.h +++ b/src/openrct2/ride/gentle/meta/GhostTrain.h @@ -29,7 +29,8 @@ constexpr const RideTypeDescriptor GhostTrainRTD = RIDE_TYPE_FLAG_HAS_LOAD_OPTIONS | RIDE_TYPE_FLAG_PEEP_WILL_RIDE_AGAIN | RIDE_TYPE_FLAG_HAS_VEHICLE_COLOURS | RIDE_TYPE_FLAG_HAS_TRACK | RIDE_TYPE_FLAG_SUPPORTS_MULTIPLE_TRACK_COLOUR | RIDE_TYPE_FLAG_ALLOW_DOORS_ON_TRACK | RIDE_TYPE_FLAG_ALLOW_MUSIC | RIDE_TYPE_FLAG_HAS_ENTRANCE_EXIT | RIDE_TYPE_FLAG_ALLOW_MORE_VEHICLES_THAN_STATION_FITS | - RIDE_TYPE_FLAG_HAS_AIR_TIME | RIDE_TYPE_FLAG_SHOW_IN_TRACK_DESIGNER | RIDE_TYPE_FLAG_INTERESTING_TO_LOOK_AT), + RIDE_TYPE_FLAG_HAS_AIR_TIME | RIDE_TYPE_FLAG_SHOW_IN_TRACK_DESIGNER | RIDE_TYPE_FLAG_INTERESTING_TO_LOOK_AT | + RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS), SET_FIELD(RideModes, EnumsToFlags(RideMode::ContinuousCircuit)), SET_FIELD(DefaultMode, RideMode::ContinuousCircuit), SET_FIELD(OperatingSettings, { 0, 0, 0, 0, 0, 0 }), diff --git a/src/openrct2/world/TileElement.h b/src/openrct2/world/TileElement.h index 9225352ccf..3235728756 100644 --- a/src/openrct2/world/TileElement.h +++ b/src/openrct2/world/TileElement.h @@ -683,4 +683,11 @@ enum #define TILE_ELEMENT_COLOUR_MASK 0b00011111 +enum +{ + LANDSCAPE_DOOR_CLOSED = 0, + LANDSCAPE_DOOR_HALF_OPEN = 2, + LANDSCAPE_DOOR_OPEN = 3, +}; + bool tile_element_is_underground(TileElement* tileElement); diff --git a/test/testpaint/Compat.cpp b/test/testpaint/Compat.cpp index 31e248e6c9..4a6c52e5b5 100644 --- a/test/testpaint/Compat.cpp +++ b/test/testpaint/Compat.cpp @@ -229,6 +229,10 @@ bool is_csg_loaded() uint8_t TrackElement::GetSeatRotation() const { + const auto* ride = get_ride(GetRideIndex()); + if (ride != nullptr && ride->GetRideTypeDescriptor().HasFlag(RIDE_TYPE_FLAG_HAS_LANDSCAPE_DOORS)) + return DEFAULT_SEAT_ROTATION; + return ColourScheme >> 4; }