Add drive-through train depot emulation (default off)
This commit is contained in:
@@ -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) {
|
||||
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
|
||||
|
Reference in New Issue
Block a user