From de00f27195791ab7c7ace239122d23582a49c694 Mon Sep 17 00:00:00 2001 From: zaxcav Date: Mon, 15 Aug 2016 12:13:46 +0200 Subject: [PATCH 1/3] Fix issues with sync adjacent stations Change try_add_synchronised_station() so that adjacent stations are always in the _synchronisedVehicles list; those without a vehicle to sync have vehicle_id == SPRITE_INDEX_NULL. Change vehicle_can_depart_synchronised() so that adjacent stations are searched for on both sides of the tile; reverse the logic of the return values to make sense with respect to the function name (all except for the case when there are no adjacent stations, which already made sense and was consequently flipped in relation to all other returns; numerous minor fixes to the checks on the departure conditions/exceptions. In vehicle_update_waiting_to_depart() flip the logic on the call to vehicle_can_depart_synchronised() according with the above change to its return values. Fixes issues: #4178 and #4182 --- src/ride/vehicle.c | 138 +++++++++++++++++++++++++++++++-------------- 1 file changed, 95 insertions(+), 43 deletions(-) diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index bee3dab67e..10e1ce1865 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -1913,7 +1913,7 @@ static void vehicle_update_waiting_to_depart(rct_vehicle* vehicle) { if (ride_type_has_flag(ride->type, RIDE_TYPE_FLAG_CAN_SYNCHRONISE_ADJACENT_STATIONS)) { if (ride->depart_flags & RIDE_DEPART_SYNCHRONISE_WITH_ADJACENT_STATIONS) { if (vehicle->update_flags & VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT) { - if (vehicle_can_depart_synchronised(vehicle)) { + if (!vehicle_can_depart_synchronised(vehicle)) { return; } } @@ -2119,6 +2119,10 @@ static bool try_add_synchronised_station(int x, int y, int z) return false; } + /* From this point on, the ride of the map element is one that is set + * to sync with adjacent stations, so it will return true. + * Still to determine if a vehicle to sync can be identified. */ + int stationIndex = map_get_station(mapElement); rct_synchronised_vehicle *sv = _lastSynchronisedVehicle; @@ -2127,10 +2131,20 @@ static bool try_add_synchronised_station(int x, int y, int z) sv->vehicle_id = SPRITE_INDEX_NULL; _lastSynchronisedVehicle++; + /* Ride vehicles are not on the track (e.g. ride is/was under + * construction), so just return; vehicle_id for this station + * is SPRITE_INDEX_NULL. */ if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_ON_TRACK)) { - return false; + return true; } + /* Station is not ready to depart, so just return; + * vehicle_id for this station is SPRITE_INDEX_NULL. */ + if (!(ride->station_depart[stationIndex] & STATION_DEPART_FLAG)) { + return true; + } + + // Look for a vehicle on this station waiting to depart. for (int i = 0; i < ride->num_vehicles; i++) { uint16 spriteIndex = ride->vehicles[i]; if (spriteIndex == SPRITE_INDEX_NULL) continue; @@ -2144,7 +2158,11 @@ static bool try_add_synchronised_station(int x, int y, int z) sv->vehicle_id = spriteIndex; return true; } - return false; + + /* No vehicle found waiting to depart (with sync adjacent) at the + * station, so just return; vehicle_id for this station is + * SPRITE_INDEX_NULL. */ + return true; } /** @@ -2152,6 +2170,11 @@ static bool try_add_synchronised_station(int x, int y, int z) * rct2: 0x006DE287 * @param vehicle The vehicle waiting to depart. * @returns true if the vehicle can depart (all adjacent trains are ready or broken down), otherwise false. + * + * Permits vehicles to depart in two ways: + * Returns true, permitting the vehicle in the param to depart immediately; + * The vehicle flag VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT is cleared for those + * vehicles that depart in sync with the vehicle in the param. */ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) { @@ -2166,9 +2189,15 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) if (mapElement == NULL) { return false; } - int direction = (mapElement->type + 1) & 3; + + // Reset the list of synchronised vehicles to empty. _lastSynchronisedVehicle = _synchronisedVehicles; + // Search for stations to sync in both directions from the current tile. + + // First search direction. + int direction = (mapElement->type + 1) & 3; + while (_lastSynchronisedVehicle < &_synchronisedVehicles[SYNCHRONISED_VEHICLE_COUNT - 1]) { x += TileDirectionDelta[direction].x; y += TileDirectionDelta[direction].y; @@ -2177,6 +2206,12 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } } + // Reset back to starting tile. + x = (xy & 0xFF) * 32; + y = (xy >> 8) * 32; + + // Other search direction. + direction = (direction ^ 2) & 3; while (_lastSynchronisedVehicle < &_synchronisedVehicles[SYNCHRONISED_VEHICLE_COUNT - 1]) { x += TileDirectionDelta[direction].x; y += TileDirectionDelta[direction].y; @@ -2191,49 +2226,57 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } for (rct_synchronised_vehicle *sv = _synchronisedVehicles; sv < _lastSynchronisedVehicle; sv++) { - if (ride_is_block_sectioned(ride)) { - if (!(ride->station_depart[sv->station_id] & 0x80)) { - sv = _synchronisedVehicles; - uint8 rideId = 0xFF; - for (; sv < _lastSynchronisedVehicle; sv++) { - if (rideId == 0xFF) { - rideId = sv->ride_id; - } - if (rideId != sv->ride_id) { + rct_ride *sv_ride = get_ride(sv->ride_id); + + if (!(sv_ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { + if (sv_ride->status != RIDE_STATUS_CLOSED) { + if (ride_is_block_sectioned(sv_ride)) { + if (!(sv_ride->station_depart[sv->station_id] & STATION_DEPART_FLAG)) { + sv = _synchronisedVehicles; + uint8 rideId = 0xFF; + for (; sv < _lastSynchronisedVehicle; sv++) { + if (rideId == 0xFF) { + rideId = sv->ride_id; + } + if (rideId != sv->ride_id) { + // Here the sync-ed stations are not all from the same ride. + return false; + } + } + + /* Here all the of sync-ed stations are from the same ride */ + ride = get_ride(rideId); + for (int i = 0; i < ride->num_vehicles; i++) { + rct_vehicle *v = GET_VEHICLE(ride->vehicles[i]); + if (v->status != VEHICLE_STATUS_WAITING_TO_DEPART && v->velocity != 0) { + // Here at least one vehicle on the ride is moving. + return false; + } + } + + // UNCERTAIN: is the return desired here, or rather continue on with the general checks? return true; } } - - ride = get_ride(rideId); - for (int i = 0; i < ride->num_vehicles; i++) { - rct_vehicle *v = GET_VEHICLE(ride->vehicles[i]); - if (v->status != VEHICLE_STATUS_WAITING_TO_DEPART && v->velocity != 0) { - return true; - } - } - - vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; - return false; - } - } - if (!(ride->lifecycle_flags & RIDE_LIFECYCLE_BROKEN_DOWN)) { - if (ride->status != RIDE_STATUS_CLOSED) { + // There is no vehicle waiting at this station to sync with. if (sv->vehicle_id == SPRITE_INDEX_NULL) { + // Check conditions for departing without all stations being in sync. if (_lastSynchronisedVehicle > &_synchronisedVehicles[1]) { - return true; + // Sync condition: there are at least 3 stations to sync + return false; } uint8 someRideIndex = _synchronisedVehicles[0].ride_id; // uint8 currentStation = _synchronisedVehicles[0].station_id if (someRideIndex != vehicle->ride) { - return true; + // Sync condition: the first station to sync is a different ride + return false; } - ride = get_ride(someRideIndex); - int numAdjacentTrainsAtStation = 0; + int numTrainsAtStation = 0; int numTravelingTrains = 0; - int currentStation = vehicle->current_station; - for (int i = 0; i < ride->num_vehicles; i++) { - uint16 spriteIndex = ride->vehicles[i]; + int currentStation = sv->station_id; + for (int i = 0; i < sv_ride->num_vehicles; i++) { + uint16 spriteIndex = sv_ride->vehicles[i]; if (spriteIndex != SPRITE_INDEX_NULL) { rct_vehicle *otherVehicle = GET_VEHICLE(spriteIndex); if (otherVehicle->status != VEHICLE_STATUS_TRAVELLING) { @@ -2241,7 +2284,7 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) if (otherVehicle->status == VEHICLE_STATUS_WAITING_TO_DEPART || otherVehicle->status == VEHICLE_STATUS_MOVING_TO_END_OF_STATION ) { - numAdjacentTrainsAtStation++; + numTrainsAtStation++; } } } else { @@ -2250,18 +2293,28 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } } - int totalTrains = numAdjacentTrainsAtStation + numTravelingTrains; - if (totalTrains != ride->num_vehicles || numTravelingTrains >= ride->num_vehicles / 2) { - return true; - } else { - vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; + int totalTrains = numTrainsAtStation + numTravelingTrains; + //return false; // force sync - no exceptions! + if (totalTrains != sv_ride->num_vehicles || numTravelingTrains >= sv_ride->num_vehicles / 2) { + //if (numArrivingTrains > 0 || numTravelingTrains >= sv_ride->num_vehicles / 2) { + /* Sync condition: If there are trains arriving at the + * station or half or more of the ride trains are + * travelling, this station must be sync-ed before the + * trains can depart! */ return false; + } else { + /* Sync exception - train is not arriving at the station + * and there are less than half the trains for the ride + * travelling (will also cover closed rides, rides under + * construction). */ + continue; } } } } } + // At this point all vehicles in _snychronisedVehicles can depart. for (rct_synchronised_vehicle *sv = _synchronisedVehicles; sv < _lastSynchronisedVehicle; sv++) { if (sv->vehicle_id != SPRITE_INDEX_NULL) { rct_vehicle *v = GET_VEHICLE(sv->vehicle_id); @@ -2269,8 +2322,7 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } } - vehicle->update_flags &= ~VEHICLE_UPDATE_FLAG_WAIT_ON_ADJACENT; - return false; + return true; } /** From a562fc4e0bb9a7aba931855d041cd0e96c5e8835 Mon Sep 17 00:00:00 2001 From: zaxcav Date: Mon, 15 Aug 2016 12:44:20 +0200 Subject: [PATCH 2/3] Remove commented out code. --- src/ride/vehicle.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index 10e1ce1865..b9255d56cf 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -2294,7 +2294,6 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } int totalTrains = numTrainsAtStation + numTravelingTrains; - //return false; // force sync - no exceptions! if (totalTrains != sv_ride->num_vehicles || numTravelingTrains >= sv_ride->num_vehicles / 2) { //if (numArrivingTrains > 0 || numTravelingTrains >= sv_ride->num_vehicles / 2) { /* Sync condition: If there are trains arriving at the From 6e4290eed7940288cd48f2679c98a78c3a5460c7 Mon Sep 17 00:00:00 2001 From: zaxcav Date: Mon, 15 Aug 2016 13:21:06 +0200 Subject: [PATCH 3/3] Remove incorrect details from comment. --- src/ride/vehicle.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index b9255d56cf..4f399ab0c7 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -2304,8 +2304,7 @@ static bool vehicle_can_depart_synchronised(rct_vehicle *vehicle) } else { /* Sync exception - train is not arriving at the station * and there are less than half the trains for the ride - * travelling (will also cover closed rides, rides under - * construction). */ + * travelling. */ continue; } }