diff --git a/distribution/changelog.txt b/distribution/changelog.txt index a2e3d450a4..c56ded9c64 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -1,5 +1,6 @@ 0.2.5+ (in development) ------------------------------------------------------------------------ +- Fix: [#6123, #7907, #9472, #11028] Cannot build some track designs with 4 stations. - Fix: [#11027] Third color on walls becomes black when saving. 0.2.5 (2020-03-24) diff --git a/src/openrct2-ui/windows/RideConstruction.cpp b/src/openrct2-ui/windows/RideConstruction.cpp index bcda34399c..71fbf7738e 100644 --- a/src/openrct2-ui/windows/RideConstruction.cpp +++ b/src/openrct2-ui/windows/RideConstruction.cpp @@ -1810,7 +1810,7 @@ static void window_ride_construction_construct(rct_window* w) auto trackPlaceAction = TrackPlaceAction( rideIndex, trackType, { x, y, z, static_cast(trackDirection) }, (properties)&0xFF, (properties >> 8) & 0x0F, - (properties >> 12) & 0x0F, liftHillAndAlternativeState); + (properties >> 12) & 0x0F, liftHillAndAlternativeState, false); if (_rideConstructionState == RIDE_CONSTRUCTION_STATE_BACK) { trackPlaceAction.SetCallback(RideConstructPlacedBackwardGameActionCallback); diff --git a/src/openrct2/actions/TrackPlaceAction.hpp b/src/openrct2/actions/TrackPlaceAction.hpp index e49a9704de..9b76f2657c 100644 --- a/src/openrct2/actions/TrackPlaceAction.hpp +++ b/src/openrct2/actions/TrackPlaceAction.hpp @@ -52,6 +52,7 @@ private: int32_t _colour; int32_t _seatRotation; int32_t _trackPlaceFlags; + bool _fromTrackDesign; public: TrackPlaceAction() @@ -60,7 +61,7 @@ public: TrackPlaceAction( NetworkRideId_t rideIndex, int32_t trackType, const CoordsXYZD& origin, int32_t brakeSpeed, int32_t colour, - int32_t seatRotation, int32_t liftHillAndAlternativeState) + int32_t seatRotation, int32_t liftHillAndAlternativeState, bool fromTrackDesign) : _rideIndex(rideIndex) , _trackType(trackType) , _origin(origin) @@ -68,6 +69,7 @@ public: , _colour(colour) , _seatRotation(seatRotation) , _trackPlaceFlags(liftHillAndAlternativeState) + , _fromTrackDesign(fromTrackDesign) { _origin.direction &= 3; } @@ -348,7 +350,7 @@ public: } if ((entranceDirections & TRACK_SEQUENCE_FLAG_ORIGIN) && trackBlock->index == 0) { - if (!track_add_station_element({ mapLoc, baseZ, _origin.direction }, _rideIndex, 0)) + if (!track_add_station_element({ mapLoc, baseZ, _origin.direction }, _rideIndex, 0, _fromTrackDesign)) { return std::make_unique(GA_ERROR::UNKNOWN, gGameCommandErrorText); } @@ -665,7 +667,8 @@ public: { if (trackBlock->index == 0) { - track_add_station_element({ mapLoc, _origin.direction }, _rideIndex, GAME_COMMAND_FLAG_APPLY); + track_add_station_element( + { mapLoc, _origin.direction }, _rideIndex, GAME_COMMAND_FLAG_APPLY, _fromTrackDesign); } sub_6CB945(ride); ride->UpdateMaxVehicles(); diff --git a/src/openrct2/network/Network.cpp b/src/openrct2/network/Network.cpp index 81c45c1ad0..0ebbbfaed6 100644 --- a/src/openrct2/network/Network.cpp +++ b/src/openrct2/network/Network.cpp @@ -31,7 +31,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 "0" +#define NETWORK_STREAM_VERSION "1" #define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION static Peep* _pickup_peep = nullptr; diff --git a/src/openrct2/ride/Track.cpp b/src/openrct2/ride/Track.cpp index a38ccce8ee..8eb84daa6e 100644 --- a/src/openrct2/ride/Track.cpp +++ b/src/openrct2/ride/Track.cpp @@ -637,14 +637,14 @@ static void ride_remove_station(Ride* ride, const CoordsXYZ& location) * * rct2: 0x006C4D89 */ -bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flags) +bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flags, bool fromTrackDesign) { auto ride = get_ride(rideIndex); if (ride == nullptr) return false; - CoordsXY stationLoc0 = loc; - CoordsXY stationLoc1 = loc; + CoordsXY stationBackLoc = loc; + CoordsXY stationFrontLoc = loc; int32_t stationLength = 1; if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_HAS_SINGLE_PIECE_STATION)) @@ -672,7 +672,7 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag TileElement* stationElement; // Search backwards for more station - loc = { stationLoc0, loc.z, loc.direction }; + loc = { stationBackLoc, loc.z, loc.direction }; do { loc -= CoordsDirectionDelta[loc.direction]; @@ -688,13 +688,13 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag } } - stationLoc0 = loc; + stationBackLoc = loc; stationLength++; } } while (stationElement != nullptr); // Search forwards for more station - loc = { stationLoc1, loc.z, loc.direction }; + loc = { stationFrontLoc, loc.z, loc.direction }; do { loc += CoordsDirectionDelta[loc.direction]; @@ -710,12 +710,14 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag } } - stationLoc1 = loc; + stationFrontLoc = loc; stationLength++; } } while (stationElement != nullptr); - if (stationLoc0 == stationLoc1 && ride->num_stations >= MAX_STATIONS) + // When attempting to place a track design, it sometimes happens that the front and back of station 0 are built, + // but the middle is not. Allow this, so the track place function can actually finish building all 4 stations. + if (stationBackLoc == stationFrontLoc && ride->num_stations >= MAX_STATIONS && !fromTrackDesign) { gGameCommandErrorText = STR_NO_MORE_STATIONS_ALLOWED_ON_THIS_RIDE; return false; @@ -729,7 +731,7 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag if (flags & GAME_COMMAND_FLAG_APPLY) { - loc = { stationLoc1, loc.z, loc.direction }; + loc = { stationFrontLoc, loc.z, loc.direction }; bool finaliseStationDone; do @@ -740,7 +742,7 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag if (stationElement != nullptr) { int32_t targetTrackType; - if (stationLoc1 == loc) + if (stationFrontLoc == loc) { auto stationIndex = ride_get_first_empty_station_start(ride); if (stationIndex == STATION_INDEX_NULL) @@ -758,7 +760,7 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag targetTrackType = TRACK_ELEM_END_STATION; } - else if (stationLoc0 == loc) + else if (stationBackLoc == loc) { targetTrackType = TRACK_ELEM_BEGIN_STATION; } @@ -770,7 +772,7 @@ bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flag map_invalidate_element(loc, stationElement); - if (stationLoc0 != loc) + if (stationBackLoc != loc) { loc -= CoordsDirectionDelta[loc.direction]; finaliseStationDone = false; diff --git a/src/openrct2/ride/Track.h b/src/openrct2/ride/Track.h index 53793358fa..0f63d0ae9e 100644 --- a/src/openrct2/ride/Track.h +++ b/src/openrct2/ride/Track.h @@ -553,7 +553,7 @@ int32_t track_get_actual_bank(TileElement* tileElement, int32_t bank); int32_t track_get_actual_bank_2(int32_t rideType, bool isInverted, int32_t bank); int32_t track_get_actual_bank_3(Vehicle* vehicle, TileElement* tileElement); -bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flags); +bool track_add_station_element(CoordsXYZD loc, ride_id_t rideIndex, int32_t flags, bool fromTrackDesign); bool track_remove_station_element(int32_t x, int32_t y, int32_t z, Direction direction, ride_id_t rideIndex, int32_t flags); money32 maze_set_track( diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 31cd30a039..5ee993a06f 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -1564,7 +1564,7 @@ static bool track_design_place_ride(TrackDesign* td6, int16_t x, int16_t y, int1 gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; auto trackPlaceAction = TrackPlaceAction( _currentRideIndex, trackType, { x, y, tempZ, static_cast(rotation) }, brakeSpeed, trackColour, - seatRotation, liftHillAndAlternativeState); + seatRotation, liftHillAndAlternativeState, true); trackPlaceAction.SetFlags(flags); auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&trackPlaceAction) diff --git a/src/openrct2/windows/_legacy.cpp b/src/openrct2/windows/_legacy.cpp index 42b0ea290d..7d30b46009 100644 --- a/src/openrct2/windows/_legacy.cpp +++ b/src/openrct2/windows/_legacy.cpp @@ -82,7 +82,8 @@ money32 place_provisional_track_piece( else { auto trackPlaceAction = TrackPlaceAction( - rideIndex, trackType, { x, y, z, static_cast(trackDirection) }, 0, 0, 0, liftHillAndAlternativeState); + rideIndex, trackType, { x, y, z, static_cast(trackDirection) }, 0, 0, 0, liftHillAndAlternativeState, + false); trackPlaceAction.SetFlags(GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED | GAME_COMMAND_FLAG_NO_SPEND | GAME_COMMAND_FLAG_GHOST); // This command must not be sent over the network auto res = GameActions::Execute(&trackPlaceAction);