Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close #7059: Implement landscape doors on Ghost Train #13636

Merged
merged 7 commits into from Jan 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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