Add drive-through train depot emulation (default off)

pull/195/head
Jonathan G Rennison 4 years ago
parent b6f583a799
commit 84dd35b685

@ -1307,6 +1307,9 @@ STR_CONFIG_SETTING_FLIP_DIRECTION_ALL_TRAINS_HELPTEXT :Enable flipping
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_DRIVE_THROUGH_TRAIN_DEPOT :Drive-through train depots: {STRING2}
STR_CONFIG_SETTING_DRIVE_THROUGH_TRAIN_DEPOT_HELPTEXT :Enable emulation of drive-through train depots. Trains can move between depots placed back to back, optionally with intermediary depots in between. Requires the YAPF pathfinder.
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR :Starting company colour: {STRING2}
STR_CONFIG_SETTING_COMPANY_STARTING_COLOUR_HELPTEXT :Choose starting colour for the company
@ -4610,6 +4613,7 @@ STR_VEHICLE_STATUS_TRAIN_STUCK_WAIT_RESTRICTION :{ORANGE}Waiting
STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR :{ORANGE}Too far to next destination
STR_VEHICLE_STATUS_TRAIN_WAITING_TIMETABLE :{ORANGE}Waiting due to timetable
STR_VEHICLE_STATUS_TRAIN_REVERSING :{ORANGE}Reversing, {VELOCITY}
STR_VEHICLE_STATUS_TRAIN_MOVING_DEPOT :{ORANGE}Moving in depot
STR_BREAKDOWN_TYPE_CRITICAL :Mechanical failure
STR_BREAKDOWN_TYPE_EM_STOP :Emergency stop

@ -86,6 +86,8 @@ FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_distance);
*/
bool YapfTrainCheckReverse(const Train *v);
bool YapfTrainCheckDepotReverse(const Train *v, TileIndex forward_depot, TileIndex reverse_depot);
/**
* Try to extend the reserved path of a train to the nearest safe tile using YAPF.
*

@ -724,6 +724,22 @@ bool YapfTrainCheckReverse(const Train *v)
return reverse;
}
bool YapfTrainCheckDepotReverse(const Train *v, TileIndex forward_depot, TileIndex reverse_depot)
{
typedef bool (*PfnCheckReverseTrain)(const Train*, TileIndex, Trackdir, TileIndex, Trackdir, int);
PfnCheckReverseTrain pfnCheckReverseTrain = CYapfRail1::stCheckReverseTrain;
/* check if non-default YAPF type needed */
if (_settings_game.pf.forbid_90_deg) {
pfnCheckReverseTrain = &CYapfRail2::stCheckReverseTrain; // Trackdir, forbid 90-deg
}
bool reverse = pfnCheckReverseTrain(v, forward_depot, DiagDirToDiagTrackdir(GetRailDepotDirection(forward_depot)),
reverse_depot, DiagDirToDiagTrackdir(GetRailDepotDirection(reverse_depot)), 1);
return reverse;
}
FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_penalty)
{
const Train *last_veh = v->Last();

@ -133,6 +133,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_SHIP_LOST_COUNTER, XSCF_NULL, 1, 1, "ship_lost_counter", nullptr, nullptr, nullptr },
{ XSLFI_BUILD_OBJECT_RATE_LIMIT,XSCF_NULL, 1, 1, "build_object_rate_limit", nullptr, nullptr, nullptr },
{ XSLFI_LOCAL_COMPANY, XSCF_IGNORABLE_ALL, 1, 1, "local_company", saveLC, loadLC, nullptr },
{ XSLFI_THROUGH_TRAIN_DEPOT, XSCF_NULL, 1, 1, "drive_through_train_depot", nullptr, nullptr, nullptr },
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
};

@ -87,6 +87,7 @@ enum SlXvFeatureIndex {
XSLFI_SHIP_LOST_COUNTER, ///< Ship lost counter
XSLFI_BUILD_OBJECT_RATE_LIMIT, ///< Build object rate limit
XSLFI_LOCAL_COMPANY, ///< Local company ID
XSLFI_THROUGH_TRAIN_DEPOT, ///< Drive-through train depots
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

@ -1830,6 +1830,7 @@ static SettingsContainer &GetSettingsTree()
routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
routing->Add(new SettingEntry("pf.reroute_rv_on_layout_change"));
routing->Add(new SettingEntry("vehicle.drive_through_train_depot"));
}
vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));

@ -561,6 +561,7 @@ struct VehicleSettings {
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 roadveh_articulated_overtaking; ///< enable articulated road vehicles overtaking other vehicles
bool drive_through_train_depot; ///< enable drive-through train depot emulation
};
/** Settings related to the economy. */

@ -1706,6 +1706,14 @@ strhelp = STR_CONFIG_SETTING_ROADVEH_ARTICULATED_OVERTAKING_HELPTEXT
patxname = ""roadveh_articulated_overtaking.vehicle.roadveh_articulated_overtaking""
cat = SC_BASIC
[SDT_BOOL]
base = GameSettings
var = vehicle.drive_through_train_depot
def = false
str = STR_CONFIG_SETTING_DRIVE_THROUGH_TRAIN_DEPOT
strhelp = STR_CONFIG_SETTING_DRIVE_THROUGH_TRAIN_DEPOT_HELPTEXT
patxname = ""drive_through_train_depot.vehicle.drive_through_train_depot""
; station.join_stations
[SDT_NULL]
length = 1

@ -2598,6 +2598,12 @@ static bool CheckTrainStayInDepot(Train *v)
return true;
}
if (v->reverse_distance > 0) {
v->reverse_distance--;
if (v->reverse_distance == 0) SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
return true;
}
SigSegState seg_state;
if (v->force_proceed == TFP_NONE) {
@ -2628,6 +2634,53 @@ static bool CheckTrainStayInDepot(Train *v)
return true;
}
if (_settings_game.pf.pathfinder_for_trains == VPF_YAPF && _settings_game.vehicle.drive_through_train_depot) {
const TileIndex depot_tile = v->tile;
const DiagDirection depot_dir = GetRailDepotDirection(depot_tile);
const DiagDirection behind_depot_dir = ReverseDiagDir(depot_dir);
const int depot_z = GetTileMaxZ(depot_tile);
const TileIndexDiffC tile_diff = TileIndexDiffCByDiagDir(behind_depot_dir);
TileIndex behind_depot_tile = depot_tile;
uint skipped = 0;
while (true) {
TileIndex tile = AddTileIndexDiffCWrap(behind_depot_tile, tile_diff);
if (tile == INVALID_TILE) break;
if (!IsRailDepotTile(tile)) break;
DiagDirection dir = GetRailDepotDirection(tile);
if (dir != depot_dir && dir != behind_depot_dir) break;
if (!HasBit(v->compatible_railtypes, GetRailType(tile))) break;
if (GetTileMaxZ(tile) != depot_z) break;
behind_depot_tile = tile;
skipped++;
}
if (skipped > 0 && GetRailDepotDirection(behind_depot_tile) == behind_depot_dir &&
YapfTrainCheckDepotReverse(v, depot_tile, behind_depot_tile)) {
Direction direction = DiagDirToDir(behind_depot_dir);
int x = TileX(behind_depot_tile) * TILE_SIZE | _vehicle_initial_x_fract[behind_depot_dir];
int y = TileY(behind_depot_tile) * TILE_SIZE | _vehicle_initial_y_fract[behind_depot_dir];
if (v->gcache.cached_total_length < skipped * TILE_SIZE) {
int delta = (skipped * TILE_SIZE) - v->gcache.cached_total_length;
int speed = max(1, v->GetCurrentMaxSpeed());
v->reverse_distance = (1 + (((192 * 3 / 2) * delta) / speed));
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
for (Train *u = v; u != nullptr; u = u->Next()) {
u->tile = behind_depot_tile;
u->direction = direction;
u->x_pos = x;
u->y_pos = y;
}
InvalidateWindowData(WC_VEHICLE_DEPOT, depot_tile);
InvalidateWindowData(WC_VEHICLE_DEPOT, behind_depot_tile);
return true;
}
}
/* Only leave when we can reserve a path to our destination. */
if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
/* No path and no force proceed. */

@ -3356,8 +3356,12 @@ public:
} else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING) && !mouse_over_start_stop) {
str = HasBit(Train::From(v)->flags, VRF_WAITING_RESTRICTION) ? STR_VEHICLE_STATUS_TRAIN_STUCK_WAIT_RESTRICTION : STR_VEHICLE_STATUS_TRAIN_STUCK;
} else if (v->type == VEH_TRAIN && Train::From(v)->reverse_distance > 1) {
str = STR_VEHICLE_STATUS_TRAIN_REVERSING;
SetDParam(0, v->GetDisplaySpeed());
if (Train::From(v)->track == TRACK_BIT_DEPOT) {
str = STR_VEHICLE_STATUS_TRAIN_MOVING_DEPOT;
} else {
str = STR_VEHICLE_STATUS_TRAIN_REVERSING;
SetDParam(0, v->GetDisplaySpeed());
}
} else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) {
str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
} else { // vehicle is in a "normal" state, show current order

Loading…
Cancel
Save