Allow articulated road vehicles to overtake other vehicles
Add setting
This commit is contained in:
@@ -852,10 +852,10 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||
if (v->roadtype == ROADTYPE_TRAM) return;
|
||||
|
||||
/* Don't overtake in stations */
|
||||
if (IsTileType(v->tile, MP_STATION) || IsTileType(u->tile, MP_STATION)) return;
|
||||
if (IsTileType(u->tile, MP_STATION)) return;
|
||||
|
||||
/* For now, articulated road vehicles can't overtake anything. */
|
||||
if (v->HasArticulatedPart()) return;
|
||||
/* If not permitted, articulated road vehicles can't overtake anything. */
|
||||
if (!_settings_game.vehicle.roadveh_articulated_overtaking && v->HasArticulatedPart()) return;
|
||||
|
||||
/* Don't overtake if the vehicle is broken or about to break down */
|
||||
if (v->breakdown_ctr != 0) return;
|
||||
@@ -863,8 +863,19 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||
/* Vehicles are not driving in same direction || direction is not a diagonal direction */
|
||||
if (v->direction != u->direction || !(v->direction & 1)) return;
|
||||
|
||||
/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
|
||||
if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->state & RVSB_TRACKDIR_MASK))) return;
|
||||
/* Vehicles chain is too long to overtake */
|
||||
if (v->GetOvertakingCounterThreshold() > 255) return;
|
||||
|
||||
for (RoadVehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
/* Don't overtake in stations */
|
||||
if (IsTileType(w->tile, MP_STATION)) return;
|
||||
|
||||
/* Don't overtake if vehicle parts not all in same direction */
|
||||
if (w->direction != v->direction) return;
|
||||
|
||||
/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
|
||||
if (w->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(w->state & RVSB_TRACKDIR_MASK))) return;
|
||||
}
|
||||
|
||||
/* Can't overtake a vehicle that is moving faster than us. If the vehicle in front is
|
||||
* accelerating, take the maximum speed for the comparison, else the current speed.
|
||||
@@ -884,16 +895,24 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||
* - No barred levelcrossing
|
||||
* - No other vehicles in the way
|
||||
*/
|
||||
od.tile = v->tile;
|
||||
if (CheckRoadBlockedForOvertaking(&od)) return;
|
||||
|
||||
od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
|
||||
if (CheckRoadBlockedForOvertaking(&od)) return;
|
||||
uint tile_count = 1 + CeilDiv(v->gcache.cached_total_length, TILE_SIZE);
|
||||
TileIndex check_tile = v->tile;
|
||||
TileIndexDiff check_tile_diff = TileOffsByDiagDir(DirToDiagDir(v->direction));
|
||||
for (; tile_count != 0; tile_count--, check_tile += check_tile_diff) {
|
||||
od.tile = check_tile;
|
||||
if (CheckRoadBlockedForOvertaking(&od)) return;
|
||||
}
|
||||
tile_count = v->gcache.cached_total_length / TILE_SIZE;
|
||||
check_tile = v->tile - check_tile_diff;
|
||||
for (; tile_count != 0; tile_count--, check_tile -= check_tile_diff) {
|
||||
od.tile = check_tile;
|
||||
if (CheckRoadBlockedForOvertaking(&od)) return;
|
||||
}
|
||||
|
||||
/* When the vehicle in front of us is stopped we may only take
|
||||
* half the time to pass it than when the vehicle is moving. */
|
||||
v->overtaking_ctr = (od.u->cur_speed == 0 || od.u->IsRoadVehicleStopped()) ? RV_OVERTAKE_TIMEOUT / 2 : 0;
|
||||
v->overtaking = RVSB_DRIVE_SIDE;
|
||||
v->SetRoadVehicleOvertaking(RVSB_DRIVE_SIDE);
|
||||
}
|
||||
|
||||
static void RoadZPosAffectSpeed(RoadVehicle *v, int old_z)
|
||||
@@ -1187,16 +1206,19 @@ static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadBits r)
|
||||
bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
|
||||
{
|
||||
SCOPE_INFO_FMT([&], "IndividualRoadVehicleController: %s, %s", scope_dumper().VehicleInfo(v), scope_dumper().VehicleInfo(prev));
|
||||
if (v->overtaking != 0) {
|
||||
if (v->overtaking != 0 && v->IsFrontEngine()) {
|
||||
if (IsTileType(v->tile, MP_STATION)) {
|
||||
/* Force us to be not overtaking! */
|
||||
v->overtaking = 0;
|
||||
v->SetRoadVehicleOvertaking(0);
|
||||
} else if (v->HasArticulatedPart() && !IsStraightRoadTrackdir((Trackdir)v->state)) {
|
||||
/* Articulated RVs may not overtake on corners */
|
||||
v->SetRoadVehicleOvertaking(0);
|
||||
} else if (++v->overtaking_ctr >= RV_OVERTAKE_TIMEOUT) {
|
||||
/* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
|
||||
* if the vehicle started a corner. To protect that, only allow an abort of
|
||||
* overtake if we are on straight roads */
|
||||
if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
|
||||
v->overtaking = 0;
|
||||
if (v->overtaking_ctr >= v->GetOvertakingCounterThreshold() && v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
|
||||
v->SetRoadVehicleOvertaking(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1274,7 +1296,7 @@ again:
|
||||
uint start_frame = RVC_DEFAULT_START_FRAME;
|
||||
if (IsReversingRoadTrackdir(dir)) {
|
||||
/* When turning around we can't be overtaking. */
|
||||
v->overtaking = 0;
|
||||
v->SetRoadVehicleOvertaking(0);
|
||||
|
||||
if (no_advance_tile) {
|
||||
DEBUG(misc, 0, "Road vehicle attempted to turn around on a single road piece bridge head");
|
||||
|
Reference in New Issue
Block a user