Allow articulated road vehicles to overtake other vehicles

Add setting
This commit is contained in:
Jonathan G Rennison
2019-04-27 13:56:49 +01:00
parent c84a8c14b4
commit a6ea1ea408
8 changed files with 66 additions and 16 deletions

View File

@@ -1295,6 +1295,9 @@ STR_CONFIG_SETTING_NO_TRAIN_CRASH_OTHER_COMPANY_HELPTEXT :This setting is
STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS :All train vehicles may be direction flipped in depot: {STRING2} STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS :All train vehicles may be direction flipped in depot: {STRING2}
STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS_HELPTEXT :Enable flipping the direction of all train vehicles in depots, even if it is not enabled by the NewGRF. STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS_HELPTEXT :Enable flipping the direction of all train vehicles in depots, even if it is not enabled by the NewGRF.
STR_CONFIG_SETTING_ROADVEH_ARTICULATED_OVERTAKING :Articulated road vehicles may overtake: {STRING2}
STR_CONFIG_SETTING_ROADVEH_ARTICULATED_OVERTAKING_HELPTEXT :Enable articulated road vehicles to overtake other road vehicles.
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :Starting company colour: {STRING2} STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :Starting company colour: {STRING2}
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :Choose starting colour for the company STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :Choose starting colour for the company

View File

@@ -166,6 +166,18 @@ struct RoadVehicle FINAL : public GroundVehicle<RoadVehicle, VEH_ROAD> {
return !this->IsRoadVehicleOnLevelCrossing(); return !this->IsRoadVehicleOnLevelCrossing();
} }
inline uint GetOvertakingCounterThreshold() const
{
return RV_OVERTAKE_TIMEOUT + (this->gcache.cached_total_length / 2) - (VEHICLE_LENGTH / 2);
}
inline void SetRoadVehicleOvertaking(byte overtaking)
{
for (RoadVehicle *u = this; u != nullptr; u = u->Next()) {
u->overtaking = overtaking;
}
}
protected: // These functions should not be called outside acceleration code. protected: // These functions should not be called outside acceleration code.
/** /**

View File

@@ -852,10 +852,10 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
if (v->roadtype == ROADTYPE_TRAM) return; if (v->roadtype == ROADTYPE_TRAM) return;
/* Don't overtake in stations */ /* 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 not permitted, articulated road vehicles can't overtake anything. */
if (v->HasArticulatedPart()) return; if (!_settings_game.vehicle.roadveh_articulated_overtaking && v->HasArticulatedPart()) return;
/* Don't overtake if the vehicle is broken or about to break down */ /* Don't overtake if the vehicle is broken or about to break down */
if (v->breakdown_ctr != 0) return; 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 */ /* Vehicles are not driving in same direction || direction is not a diagonal direction */
if (v->direction != u->direction || !(v->direction & 1)) return; 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 */ /* Vehicles chain is too long to overtake */
if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->state & RVSB_TRACKDIR_MASK))) return; 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 /* 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. * 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 barred levelcrossing
* - No other vehicles in the way * - No other vehicles in the way
*/ */
od.tile = v->tile; uint tile_count = 1 + CeilDiv(v->gcache.cached_total_length, TILE_SIZE);
if (CheckRoadBlockedForOvertaking(&od)) return; TileIndex check_tile = v->tile;
TileIndexDiff check_tile_diff = TileOffsByDiagDir(DirToDiagDir(v->direction));
od.tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction)); for (; tile_count != 0; tile_count--, check_tile += check_tile_diff) {
if (CheckRoadBlockedForOvertaking(&od)) return; 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 /* 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. */ * 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_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) 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) bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
{ {
SCOPE_INFO_FMT([&], "IndividualRoadVehicleController: %s, %s", scope_dumper().VehicleInfo(v), scope_dumper().VehicleInfo(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)) { if (IsTileType(v->tile, MP_STATION)) {
/* Force us to be not overtaking! */ /* 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) { } 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 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 * if the vehicle started a corner. To protect that, only allow an abort of
* overtake if we are on straight roads */ * overtake if we are on straight roads */
if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) { if (v->overtaking_ctr >= v->GetOvertakingCounterThreshold() && v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
v->overtaking = 0; v->SetRoadVehicleOvertaking(0);
} }
} }
} }
@@ -1274,7 +1296,7 @@ again:
uint start_frame = RVC_DEFAULT_START_FRAME; uint start_frame = RVC_DEFAULT_START_FRAME;
if (IsReversingRoadTrackdir(dir)) { if (IsReversingRoadTrackdir(dir)) {
/* When turning around we can't be overtaking. */ /* When turning around we can't be overtaking. */
v->overtaking = 0; v->SetRoadVehicleOvertaking(0);
if (no_advance_tile) { if (no_advance_tile) {
DEBUG(misc, 0, "Road vehicle attempted to turn around on a single road piece bridge head"); DEBUG(misc, 0, "Road vehicle attempted to turn around on a single road piece bridge head");

View File

@@ -103,6 +103,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_DUAL_RAIL_TYPES, XSCF_NULL, 1, 1, "dual_rail_types", nullptr, nullptr, nullptr }, { XSLFI_DUAL_RAIL_TYPES, XSCF_NULL, 1, 1, "dual_rail_types", nullptr, nullptr, nullptr },
{ XSLFI_CONSIST_SPEED_RD_FLAG, XSCF_NULL, 1, 1, "consist_speed_rd_flag", nullptr, nullptr, nullptr }, { XSLFI_CONSIST_SPEED_RD_FLAG, XSCF_NULL, 1, 1, "consist_speed_rd_flag", nullptr, nullptr, nullptr },
{ XSLFI_SAVEGAME_UNIQUE_ID, XSCF_IGNORABLE_ALL, 1, 1, "savegame_unique_id", nullptr, nullptr, nullptr }, { XSLFI_SAVEGAME_UNIQUE_ID, XSCF_IGNORABLE_ALL, 1, 1, "savegame_unique_id", nullptr, nullptr, nullptr },
{ XSLFI_RV_OVERTAKING, XSCF_NULL, 1, 1, "roadveh_overtaking", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
}; };

View File

@@ -70,6 +70,7 @@ enum SlXvFeatureIndex {
XSLFI_DUAL_RAIL_TYPES, ///< Two rail-types per tile XSLFI_DUAL_RAIL_TYPES, ///< Two rail-types per tile
XSLFI_CONSIST_SPEED_RD_FLAG, ///< Consist speed reduction flag XSLFI_CONSIST_SPEED_RD_FLAG, ///< Consist speed reduction flag
XSLFI_SAVEGAME_UNIQUE_ID, ///< Savegame unique ID XSLFI_SAVEGAME_UNIQUE_ID, ///< Savegame unique ID
XSLFI_RV_OVERTAKING, ///< Roadvehicle overtaking
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

View File

@@ -1718,6 +1718,7 @@ static SettingsContainer &GetSettingsTree()
physics->Add(new SettingEntry("vehicle.smoke_amount")); physics->Add(new SettingEntry("vehicle.smoke_amount"));
physics->Add(new SettingEntry("vehicle.plane_speed")); physics->Add(new SettingEntry("vehicle.plane_speed"));
physics->Add(new SettingEntry("vehicle.ship_collision_avoidance")); physics->Add(new SettingEntry("vehicle.ship_collision_avoidance"));
physics->Add(new SettingEntry("vehicle.roadveh_articulated_overtaking"));
} }
SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING)); SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));

View File

@@ -540,6 +540,7 @@ struct VehicleSettings {
bool ship_collision_avoidance; ///< ships try to avoid colliding with each other bool ship_collision_avoidance; ///< ships try to avoid colliding with each other
bool no_train_crash_other_company; ///< trains cannot crash with trains from other companies bool no_train_crash_other_company; ///< trains cannot crash with trains from other companies
bool flip_direction_all_trains; ///< enable flipping direction in depot for all train engine types bool flip_direction_all_trains; ///< enable flipping direction in depot for all train engine types
bool roadveh_articulated_overtaking; ///< enable articulated road vehicles overtaking other vehicles
}; };
/** Settings related to the economy. */ /** Settings related to the economy. */

View File

@@ -1381,6 +1381,15 @@ strhelp = STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS_HELPTEXT
patxname = ""flip_direction_all_trains.vehicle.flip_direction_all_trains"" patxname = ""flip_direction_all_trains.vehicle.flip_direction_all_trains""
cat = SC_EXPERT cat = SC_EXPERT
[SDT_BOOL]
base = GameSettings
var = vehicle.roadveh_articulated_overtaking
def = true
str = STR_CONFIG_SETTING_ROADVEH_ARTICULATED_OVERTAKING
strhelp = STR_CONFIG_SETTING_ROADVEH_ARTICULATED_OVERTAKING_HELPTEXT
patxname = ""roadveh_articulated_overtaking.vehicle.roadveh_articulated_overtaking""
cat = SC_BASIC
; station.join_stations ; station.join_stations
[SDT_NULL] [SDT_NULL]
length = 1 length = 1