Skip to content

Commit

Permalink
Close #7059: Implement landscape doors on Ghost Train (#13636)
Browse files Browse the repository at this point in the history
* 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 <duncans_pumpkin@hotmail.co.uk>
  • Loading branch information
Gymnasiast and duncanspumpkin committed Jan 10, 2021
1 parent b1e5a11 commit 60d1e94
Show file tree
Hide file tree
Showing 18 changed files with 220 additions and 25 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Expand Up @@ -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")
Expand Down
1 change: 1 addition & 0 deletions distribution/changelog.txt
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions openrct2.proj
Expand Up @@ -48,8 +48,8 @@
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.20/objects.zip</ObjectsUrl>
<ObjectsSha1>151424d24b1d49a167932b58319bedaa6ec368e9</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.24/replays.zip</ReplaysUrl>
<ReplaysSha1>58AD8B2D2A804D2FEE787597A2A4DEADBF4D2A65</ReplaysSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.25/replays.zip</ReplaysUrl>
<ReplaysSha1>DA3E595E4D0231934F1DCFC3B540097CE2ED1B17</ReplaysSha1>
</PropertyGroup>

<ItemGroup>
Expand Down
5 changes: 5 additions & 0 deletions src/openrct2/actions/TrackPlaceAction.cpp
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/openrct2/network/NetworkBase.cpp
Expand Up @@ -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;
Expand Down
15 changes: 11 additions & 4 deletions src/openrct2/rct1/S4Importer.cpp
Expand Up @@ -2100,6 +2100,7 @@ class S4Importer final : public IParkImporter
{
auto dst2 = dst->AsTrack();
auto src2 = src->AsTrack();
auto rideType = _s4.rides[src2->GetRideIndex()].type;

dst2->SetTrackType(src2->GetTrackType());
dst2->SetSequenceIndex(src2->GetSequenceIndex());
Expand All @@ -2108,12 +2109,18 @@ class S4Importer final : public IParkImporter
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();
Expand All @@ -2127,7 +2134,7 @@ class S4Importer final : public IParkImporter
}

// 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());
}
Expand Down
12 changes: 12 additions & 0 deletions src/openrct2/rct12/RCT12.cpp
Expand Up @@ -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;
Expand Down
5 changes: 3 additions & 2 deletions src/openrct2/rct12/RCT12.h
Expand Up @@ -511,10 +511,11 @@ struct RCT12TrackElement : RCT12TileElementBase
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);
Expand Down
16 changes: 15 additions & 1 deletion src/openrct2/rct2/S6Exporter.cpp
Expand Up @@ -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.
Expand All @@ -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;
Expand Down
10 changes: 9 additions & 1 deletion src/openrct2/rct2/S6Importer.cpp
Expand Up @@ -1126,7 +1126,6 @@ class S6Importer final : public IParkImporter
dst2->SetHasGreenLight(src2->HasGreenLight());
dst2->SetBlockBrakeClosed(src2->BlockBrakeClosed());
dst2->SetIsIndestructible(src2->IsIndestructible());
dst2->SetSeatRotation(src2->GetSeatRotation());
// Skipping IsHighlighted()

auto trackType = dst2->GetTrackType();
Expand All @@ -1145,6 +1144,15 @@ class S6Importer final : public IParkImporter
{
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;
}
Expand Down
1 change: 1 addition & 0 deletions src/openrct2/ride/RideData.h
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions src/openrct2/ride/Track.cpp
Expand Up @@ -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;
}

Expand Down
56 changes: 56 additions & 0 deletions src/openrct2/ride/Vehicle.cpp
Expand Up @@ -7483,6 +7483,44 @@ void Vehicle::UpdateSceneryDoor() const
{ wallCoords, static_cast<Direction>(direction) }, TrackLocation, next_vehicle_on_train == SPRITE_INDEX_NULL);
}

template<bool isBackwards> 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<uint8_t>(TileElementType::Track))
{
AnimateLandscapeDoor<false>(tileElement->AsTrack(), next_vehicle_on_train == SPRITE_INDEX_NULL);
}
}

/**
*
* rct2: 0x006DB38B
Expand Down Expand Up @@ -7539,6 +7577,22 @@ void Vehicle::UpdateSceneryDoorBackwards() const
{ wallCoords, static_cast<Direction>(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<uint8_t>(TileElementType::Track))
{
AnimateLandscapeDoor<true>(tileElement->AsTrack(), next_vehicle_on_train == SPRITE_INDEX_NULL);
}
}

static void vehicle_update_play_water_splash_sound()
{
if (_vehicleVelocityF64E08 <= BLOCK_BRAKE_BASE_SPEED)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/openrct2/ride/Vehicle.h
Expand Up @@ -450,6 +450,8 @@ struct Vehicle : SpriteBase
void UpdateGoKartAttemptSwitchLanes();
void UpdateSceneryDoor() const;
void UpdateSceneryDoorBackwards() const;
void UpdateLandscapeDoor() const;
void UpdateLandscapeDoorBackwards() const;
};

struct train_ref
Expand Down

0 comments on commit 60d1e94

Please sign in to comment.