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 :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_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 :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
|
||||||
|
|
||||||
@@ -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_AIRCRAFT_TOO_FAR :{ORANGE}Too far to next destination
|
||||||
STR_VEHICLE_STATUS_TRAIN_WAITING_TIMETABLE :{ORANGE}Waiting due to timetable
|
STR_VEHICLE_STATUS_TRAIN_WAITING_TIMETABLE :{ORANGE}Waiting due to timetable
|
||||||
STR_VEHICLE_STATUS_TRAIN_REVERSING :{ORANGE}Reversing, {VELOCITY}
|
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_CRITICAL :Mechanical failure
|
||||||
STR_BREAKDOWN_TYPE_EM_STOP :Emergency stop
|
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 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.
|
* 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;
|
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)
|
FindDepotData YapfTrainFindNearestDepot(const Train *v, int max_penalty)
|
||||||
{
|
{
|
||||||
const Train *last_veh = v->Last();
|
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_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_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_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
|
{ 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_SHIP_LOST_COUNTER, ///< Ship lost counter
|
||||||
XSLFI_BUILD_OBJECT_RATE_LIMIT, ///< Build object rate limit
|
XSLFI_BUILD_OBJECT_RATE_LIMIT, ///< Build object rate limit
|
||||||
XSLFI_LOCAL_COMPANY, ///< Local company ID
|
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_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
|
||||||
|
@@ -1830,6 +1830,7 @@ static SettingsContainer &GetSettingsTree()
|
|||||||
routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
|
routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
|
||||||
routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
|
routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
|
||||||
routing->Add(new SettingEntry("pf.reroute_rv_on_layout_change"));
|
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"));
|
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 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
|
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. */
|
/** 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""
|
patxname = ""roadveh_articulated_overtaking.vehicle.roadveh_articulated_overtaking""
|
||||||
cat = SC_BASIC
|
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
|
; station.join_stations
|
||||||
[SDT_NULL]
|
[SDT_NULL]
|
||||||
length = 1
|
length = 1
|
||||||
|
@@ -2598,6 +2598,12 @@ static bool CheckTrainStayInDepot(Train *v)
|
|||||||
return true;
|
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;
|
SigSegState seg_state;
|
||||||
|
|
||||||
if (v->force_proceed == TFP_NONE) {
|
if (v->force_proceed == TFP_NONE) {
|
||||||
@@ -2628,6 +2634,53 @@ static bool CheckTrainStayInDepot(Train *v)
|
|||||||
return true;
|
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. */
|
/* Only leave when we can reserve a path to our destination. */
|
||||||
if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
|
if (seg_state == SIGSEG_PBS && !TryPathReserve(v) && v->force_proceed == TFP_NONE) {
|
||||||
/* No path and no force proceed. */
|
/* 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) {
|
} 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;
|
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) {
|
} else if (v->type == VEH_TRAIN && Train::From(v)->reverse_distance > 1) {
|
||||||
str = STR_VEHICLE_STATUS_TRAIN_REVERSING;
|
if (Train::From(v)->track == TRACK_BIT_DEPOT) {
|
||||||
SetDParam(0, v->GetDisplaySpeed());
|
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)) {
|
} 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;
|
str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
|
||||||
} else { // vehicle is in a "normal" state, show current order
|
} else { // vehicle is in a "normal" state, show current order
|
||||||
|
Reference in New Issue
Block a user