1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-17 20:13:07 +01:00

Add animations for land edge doors

This commit is contained in:
mix
2025-05-19 23:07:34 +01:00
parent daf8c186d3
commit 43b0ed6dc8
7 changed files with 111 additions and 65 deletions

View File

@@ -617,8 +617,8 @@ GameActions::Result TrackPlaceAction::Execute() const
if (rtd.HasFlag(RtdFlag::hasLandscapeDoors))
{
trackElement->SetDoorAState(LANDSCAPE_DOOR_CLOSED);
trackElement->SetDoorBState(LANDSCAPE_DOOR_CLOSED);
trackElement->SetDoorAState(kLandEdgeDoorFrameClosed);
trackElement->SetDoorBState(kLandEdgeDoorFrameClosed);
}
else
{

View File

@@ -153,24 +153,26 @@ static constexpr uint32_t kGhostTrainTrackPiecesBrakes[4] = {
SprGhostTrainTrackBrakesNwSe,
};
static constexpr TunnelType kDoorOpeningOutwardsToImage[] = {
TunnelType::Doors2, // Closed
TunnelType::Doors2, // Unused?
TunnelType::Doors3, // Half open
TunnelType::Doors4, // Fully open
TunnelType::Doors2, // Unused?
TunnelType::Doors2, // Unused?
TunnelType::Doors2, // Unused?
static constexpr std::array<TunnelType, kLandEdgeDoorFrameCount> kDoorOpeningOutwardsToImage = {
TunnelType::Doors2, // closed
TunnelType::Doors3, // opening
TunnelType::Doors3, // opening
TunnelType::Doors4, // open
TunnelType::Doors3, // closing
TunnelType::Doors3, // closing
TunnelType::Doors2, // closed
TunnelType::Doors2, // unused
};
static constexpr TunnelType kDoorOpeningInwardsToImage[] = {
TunnelType::Doors2, // Closed
TunnelType::Doors2, // Unused?
TunnelType::Doors5, // Half open
TunnelType::Doors6, // Fully open
TunnelType::Doors2, // Unused?
TunnelType::Doors2, // Unused?
TunnelType::Doors2, // Unused?
static constexpr std::array<TunnelType, kLandEdgeDoorFrameCount> kDoorOpeningInwardsToImage = {
TunnelType::Doors2, // closed
TunnelType::Doors5, // opening
TunnelType::Doors5, // opening
TunnelType::Doors6, // open
TunnelType::Doors5, // closing
TunnelType::Doors5, // closing
TunnelType::Doors2, // closed
TunnelType::Doors2, // unused
};
static TunnelType GetTunnelDoorsImageStraightFlat(const TrackElement& trackElement, uint8_t direction)
@@ -189,24 +191,26 @@ static TunnelType GetTunnelDoorsImageStraightFlat(const TrackElement& trackEleme
return TunnelType::Doors2;
}
static constexpr TunnelType kDoorFlatTo25DegOpeningOutwardsToImage[] = {
TunnelType::DoorsFlatTo25Deg2, // Closed
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg3, // Half open
TunnelType::DoorsFlatTo25Deg4, // Fully open
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg2, // Unused?
static constexpr std::array<TunnelType, kLandEdgeDoorFrameCount> kDoorFlatTo25DegOpeningOutwardsToImage = {
TunnelType::DoorsFlatTo25Deg2, // closed
TunnelType::DoorsFlatTo25Deg3, // opening
TunnelType::DoorsFlatTo25Deg3, // opening
TunnelType::DoorsFlatTo25Deg4, // open
TunnelType::DoorsFlatTo25Deg3, // closing
TunnelType::DoorsFlatTo25Deg3, // closing
TunnelType::DoorsFlatTo25Deg2, // closed
TunnelType::DoorsFlatTo25Deg2, // unused
};
static constexpr TunnelType kDoorFlatTo25DegOpeningInwardsToImage[] = {
TunnelType::DoorsFlatTo25Deg2, // Closed
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg5, // Half open
TunnelType::DoorsFlatTo25Deg6, // Fully open
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg2, // Unused?
TunnelType::DoorsFlatTo25Deg2, // Unused?
static constexpr std::array<TunnelType, kLandEdgeDoorFrameCount> kDoorFlatTo25DegOpeningInwardsToImage = {
TunnelType::DoorsFlatTo25Deg2, // closed
TunnelType::DoorsFlatTo25Deg5, // opening
TunnelType::DoorsFlatTo25Deg5, // opening
TunnelType::DoorsFlatTo25Deg6, // open
TunnelType::DoorsFlatTo25Deg5, // closing
TunnelType::DoorsFlatTo25Deg5, // closing
TunnelType::DoorsFlatTo25Deg2, // closed
TunnelType::DoorsFlatTo25Deg2, // unused
};
/** rct2: 0x00770BEC */

View File

@@ -1285,13 +1285,6 @@ namespace OpenRCT2::RCT1
RCT1_SCENERY_SMALL_RED_GARDENS = 176, // TG19
};
enum
{
RCT1_LANDSCAPE_DOOR_CLOSED = 0,
RCT1_LANDSCAPE_DOOR_HALF_OPEN = 2,
RCT1_LANDSCAPE_DOOR_OPEN = 3,
};
enum
{
RCT1_PATH_SUPPORT_TYPE_TRUSS,

View File

@@ -6347,25 +6347,27 @@ void Vehicle::UpdateSceneryDoor() const
}
template<bool isBackwards>
static void AnimateLandscapeDoor(TrackElement* trackElement, bool isLastVehicle)
static void AnimateLandscapeDoor(const CoordsXYZ& doorLocation, TrackElement& trackElement, const bool isLastVehicle)
{
auto doorState = isBackwards ? trackElement->GetDoorAState() : trackElement->GetDoorBState();
if (!isLastVehicle && doorState == LANDSCAPE_DOOR_CLOSED)
const auto doorState = isBackwards ? trackElement.GetDoorAState() : trackElement.GetDoorBState();
if (!isLastVehicle && doorState == kLandEdgeDoorFrameClosed)
{
if (isBackwards)
trackElement->SetDoorAState(LANDSCAPE_DOOR_OPEN);
trackElement.SetDoorAState(kLandEdgeDoorFrameOpening);
else
trackElement->SetDoorBState(LANDSCAPE_DOOR_OPEN);
// TODO: play door open sound
trackElement.SetDoorBState(kLandEdgeDoorFrameOpening);
MapAnimation::CreateTemporary(doorLocation, MapAnimation::TemporaryType::landEdgeDoor);
}
if (isLastVehicle)
{
if (isBackwards)
trackElement->SetDoorAState(LANDSCAPE_DOOR_CLOSED);
trackElement.SetDoorAState(kLandEdgeDoorFrameClosing);
else
trackElement->SetDoorBState(LANDSCAPE_DOOR_CLOSED);
// TODO: play door close sound
trackElement.SetDoorBState(kLandEdgeDoorFrameClosing);
MapAnimation::CreateTemporary(doorLocation, MapAnimation::TemporaryType::landEdgeDoor);
}
}
@@ -6377,11 +6379,11 @@ void Vehicle::UpdateLandscapeDoor() const
return;
}
auto coords = CoordsXYZ{ x, y, TrackLocation.z }.ToTileStart();
auto* tileElement = MapGetTrackElementAtFromRide(coords, ride);
const auto coords = CoordsXYZ{ x, y, TrackLocation.z }.ToTileStart();
auto* const tileElement = MapGetTrackElementAtFromRide(coords, ride);
if (tileElement != nullptr && tileElement->GetType() == TileElementType::Track)
{
AnimateLandscapeDoor<false>(tileElement->AsTrack(), next_vehicle_on_train.IsNull());
AnimateLandscapeDoor<false>(coords, *tileElement->AsTrack(), next_vehicle_on_train.IsNull());
}
}
@@ -6438,11 +6440,11 @@ void Vehicle::UpdateLandscapeDoorBackwards() const
return;
}
auto coords = CoordsXYZ{ TrackLocation, TrackLocation.z };
auto* tileElement = MapGetTrackElementAtFromRide(coords, ride);
const auto coords = CoordsXYZ{ TrackLocation, TrackLocation.z };
auto* const tileElement = MapGetTrackElementAtFromRide(coords, ride);
if (tileElement != nullptr && tileElement->GetType() == TileElementType::Track)
{
AnimateLandscapeDoor<true>(tileElement->AsTrack(), next_vehicle_on_train.IsNull());
AnimateLandscapeDoor<true>(coords, *tileElement->AsTrack(), next_vehicle_on_train.IsNull());
}
}

View File

@@ -299,6 +299,44 @@ static bool UpdateOnRidePhotoAnimation(TrackElement& track, const CoordsXYZ& coo
return false;
}
static bool UpdateLandEdgeDoorsAnimation(TrackElement& track, const CoordsXYZ& coords)
{
if (getGameState().currentTicks & 3)
{
return true;
}
bool isAnimating = false;
const auto doorAState = track.GetDoorAState();
if (doorAState >= kLandEdgeDoorFrameEnd)
{
track.SetDoorAState(kLandEdgeDoorFrameClosed);
MapInvalidateTileZoom1({ coords, coords.z + 32 });
}
else if (doorAState != kLandEdgeDoorFrameClosed && doorAState != kLandEdgeDoorFrameOpen)
{
track.SetDoorAState(doorAState + 1);
MapInvalidateTileZoom1({ coords, coords.z + 32 });
isAnimating = true;
}
const auto doorBState = track.GetDoorBState();
if (doorBState >= kLandEdgeDoorFrameEnd)
{
track.SetDoorBState(kLandEdgeDoorFrameClosed);
MapInvalidateTileZoom1({ coords, coords.z + 32 });
}
else if (doorBState != kLandEdgeDoorFrameClosed && doorBState != kLandEdgeDoorFrameOpen)
{
track.SetDoorBState(doorBState + 1);
MapInvalidateTileZoom1({ coords, coords.z + 32 });
isAnimating = true;
}
return isAnimating;
}
static bool UpdateTemporaryAnimation(const TemporaryMapAnimation& animation)
{
const TileCoordsXYZ tileCoords{ animation.location };
@@ -308,7 +346,7 @@ static bool UpdateTemporaryAnimation(const TemporaryMapAnimation& animation)
return true;
}
bool hasAnimations = false;
bool isAnimating = false;
do
{
switch (animation.type)
@@ -318,14 +356,21 @@ static bool UpdateTemporaryAnimation(const TemporaryMapAnimation& animation)
if (tileElement->GetType() == TileElementType::Track && tileElement->BaseHeight == tileCoords.z
&& tileElement->AsTrack()->GetTrackType() == TrackElemType::OnRidePhoto)
{
hasAnimations |= UpdateOnRidePhotoAnimation(*tileElement->AsTrack(), animation.location);
isAnimating |= UpdateOnRidePhotoAnimation(*tileElement->AsTrack(), animation.location);
}
break;
}
case MapAnimation::TemporaryType::landEdgeDoor:
{
if (tileElement->GetType() == TileElementType::Track && tileElement->BaseHeight == tileCoords.z)
{
isAnimating |= UpdateLandEdgeDoorsAnimation(*tileElement->AsTrack(), animation.location);
}
}
}
} while (!(tileElement++)->IsLastForTile());
return hasAnimations;
return isAnimating;
}
static bool IsElementAnimated(const TileElementBase& element)

View File

@@ -16,6 +16,7 @@ namespace OpenRCT2::MapAnimation
enum class TemporaryType : uint8_t
{
onRidePhoto,
landEdgeDoor,
};
void Create(const CoordsXY coords);

View File

@@ -41,12 +41,13 @@ enum
TRACK_ELEMENT_COLOUR_SEAT_ROTATION_MASK = 0b11110000,
};
enum
{
LANDSCAPE_DOOR_CLOSED = 0,
LANDSCAPE_DOOR_HALF_OPEN = 2,
LANDSCAPE_DOOR_OPEN = 3,
};
constexpr const int32_t kLandEdgeDoorFrameClosed = 0;
constexpr const int32_t kLandEdgeDoorFrameOpening = 1;
constexpr const int32_t kLandEdgeDoorFrameOpen = 3;
constexpr const int32_t kLandEdgeDoorFrameClosing = 4;
constexpr const int32_t kLandEdgeDoorFrameEnd = 6;
constexpr const int32_t kLandEdgeDoorFrameCount = 8;
#pragma pack(push, 1)