Merge branch 'tracerestrict' into tracerestrict-sx
This commit is contained in:
@@ -2417,6 +2417,8 @@ STR_TRACE_RESTRICT_PF_ALLOW :Allow
|
||||
STR_TRACE_RESTRICT_PF_ALLOW_LONG :Allow (cancel previous Deny)
|
||||
STR_TRACE_RESTRICT_RESERVE_THROUGH :Reserve through
|
||||
STR_TRACE_RESTRICT_RESERVE_THROUGH_CANCEL :Cancel reserve through
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE :Long reserve
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL :Cancel long reserve
|
||||
STR_TRACE_RESTRICT_PF_PENALTY :Penalty
|
||||
STR_TRACE_RESTRICT_PF_VALUE_SMALL :small
|
||||
STR_TRACE_RESTRICT_PF_VALUE_MEDIUM :medium
|
||||
|
@@ -393,7 +393,7 @@ Train *GetTrainForReservation(TileIndex tile, Track track)
|
||||
* This is called to retrieve the previous signal, as required
|
||||
* This is not run all the time as it is somewhat expensive and most restrictions will not test for the previous signal
|
||||
*/
|
||||
static TileIndex IsSafeWaitingPositionTraceRestrictPreviousSignalCallback(const Train *v, const void *)
|
||||
TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *)
|
||||
{
|
||||
// scan forwards from vehicle position, for the case that train is waiting at/approaching PBS signal
|
||||
|
||||
@@ -470,7 +470,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(ft.m_new_tile, TrackdirToTrack(td));
|
||||
if (prog && prog->actions_used_flags & TRPAUF_RESERVE_THROUGH) {
|
||||
TraceRestrictProgramResult out;
|
||||
prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &IsSafeWaitingPositionTraceRestrictPreviousSignalCallback, NULL), out);
|
||||
prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, NULL), out);
|
||||
if (out.flags & TRPRF_RESERVE_THROUGH) {
|
||||
return false;
|
||||
}
|
||||
|
@@ -390,6 +390,14 @@ void TraceRestrictProgram::Execute(const Train* v, const TraceRestrictProgramInp
|
||||
}
|
||||
break;
|
||||
|
||||
case TRIT_LONG_RESERVE:
|
||||
if (GetTraceRestrictValue(item)) {
|
||||
out.flags &= ~TRPRF_LONG_RESERVE;
|
||||
} else {
|
||||
out.flags |= TRPRF_LONG_RESERVE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
@@ -492,6 +500,10 @@ CommandCost TraceRestrictProgram::Validate(const std::vector<TraceRestrictItem>
|
||||
actions_used_flags |= TRPAUF_RESERVE_THROUGH;
|
||||
break;
|
||||
|
||||
case TRIT_LONG_RESERVE:
|
||||
actions_used_flags |= TRPAUF_LONG_RESERVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return_cmd_error(STR_TRACE_RESTRICT_ERROR_VALIDATE_UNKNOWN_INSTRUCTION);
|
||||
}
|
||||
@@ -544,6 +556,7 @@ void SetTraceRestrictValueDefault(TraceRestrictItem &item, TraceRestrictValueTyp
|
||||
case TRVT_SPEED:
|
||||
case TRVT_TILE_INDEX:
|
||||
case TRVT_RESERVE_THROUGH:
|
||||
case TRVT_LONG_RESERVE:
|
||||
SetTraceRestrictValue(item, 0);
|
||||
SetTraceRestrictAuxField(item, 0);
|
||||
break;
|
||||
|
@@ -98,6 +98,7 @@ enum TraceRestrictItemType {
|
||||
TRIT_PF_DENY = 1, ///< Pathfinder deny/allow
|
||||
TRIT_PF_PENALTY = 2, ///< Add to pathfinder penalty
|
||||
TRIT_RESERVE_THROUGH = 3, ///< Reserve through PBS signal
|
||||
TRIT_LONG_RESERVE = 4, ///< Long reserve PBS signal
|
||||
|
||||
TRIT_COND_BEGIN = 8, ///< Start of conditional item types, note that this has the same value as TRIT_COND_ENDIF
|
||||
TRIT_COND_ENDIF = 8, ///< This is an endif block or an else block
|
||||
@@ -195,6 +196,7 @@ enum TraceRestrictPathfinderPenaltyPresetIndex {
|
||||
enum TraceRestrictProgramResultFlags {
|
||||
TRPRF_DENY = 1 << 0, ///< Pathfinder deny is set
|
||||
TRPRF_RESERVE_THROUGH = 1 << 1, ///< Reserve through is set
|
||||
TRPRF_LONG_RESERVE = 1 << 2, ///< Long reserve is set
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags)
|
||||
|
||||
@@ -204,6 +206,7 @@ DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramResultFlags)
|
||||
enum TraceRestrictProgramActionsUsedFlags {
|
||||
TRPAUF_PF = 1 << 0, ///< Pathfinder deny or penalty are present
|
||||
TRPAUF_RESERVE_THROUGH = 1 << 1, ///< Reserve through action is present
|
||||
TRPAUF_LONG_RESERVE = 1 << 2, ///< Long reserve action is present
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(TraceRestrictProgramActionsUsedFlags)
|
||||
|
||||
@@ -407,6 +410,7 @@ enum TraceRestrictValueType {
|
||||
TRVT_TILE_INDEX = 8, ///< takes a TileIndex in the next item slot
|
||||
TRVT_PF_PENALTY = 9, ///< takes a pathfinder penalty value or preset index, as per the auxiliary field as type: TraceRestrictPathfinderPenaltyAuxField
|
||||
TRVT_RESERVE_THROUGH = 10,///< takes a value 0 = reserve through, 1 = cancel previous reserve through
|
||||
TRVT_LONG_RESERVE = 11,///< takes a value 0 = long reserve, 1 = cancel previous long reserve
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -480,6 +484,8 @@ static inline TraceRestrictTypePropertySet GetTraceRestrictTypeProperties(TraceR
|
||||
out.value_type = TRVT_DENY;
|
||||
} else if (GetTraceRestrictType(item) == TRIT_RESERVE_THROUGH) {
|
||||
out.value_type = TRVT_RESERVE_THROUGH;
|
||||
} else if (GetTraceRestrictType(item) == TRIT_LONG_RESERVE) {
|
||||
out.value_type = TRVT_LONG_RESERVE;
|
||||
} else {
|
||||
out.value_type = TRVT_NONE;
|
||||
}
|
||||
|
@@ -120,6 +120,7 @@ static const StringID _program_insert_str[] = {
|
||||
STR_TRACE_RESTRICT_PF_DENY,
|
||||
STR_TRACE_RESTRICT_PF_PENALTY,
|
||||
STR_TRACE_RESTRICT_RESERVE_THROUGH,
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
static const uint32 _program_insert_else_hide_mask = 8; ///< disable bitmask for else
|
||||
@@ -133,6 +134,7 @@ static const uint _program_insert_val[] = {
|
||||
TRIT_PF_DENY, // deny
|
||||
TRIT_PF_PENALTY, // penalty
|
||||
TRIT_RESERVE_THROUGH, // reserve through
|
||||
TRIT_LONG_RESERVE, // long reserve
|
||||
};
|
||||
|
||||
/** insert drop down list strings and values */
|
||||
@@ -170,6 +172,21 @@ static const TraceRestrictDropDownListSet _reserve_through_value = {
|
||||
_reserve_through_value_str, _reserve_through_value_val,
|
||||
};
|
||||
|
||||
static const StringID _long_reserve_value_str[] = {
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE,
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL,
|
||||
INVALID_STRING_ID
|
||||
};
|
||||
static const uint _long_reserve_value_val[] = {
|
||||
0,
|
||||
1,
|
||||
};
|
||||
|
||||
/** value drop down list for long reserve types strings and values */
|
||||
static const TraceRestrictDropDownListSet _long_reserve_value = {
|
||||
_long_reserve_value_str, _long_reserve_value_val,
|
||||
};
|
||||
|
||||
static const StringID _direction_value_str[] = {
|
||||
STR_TRACE_RESTRICT_DIRECTION_FRONT,
|
||||
STR_TRACE_RESTRICT_DIRECTION_BACK,
|
||||
@@ -229,12 +246,14 @@ static const TraceRestrictDropDownListSet *GetTypeDropDownListSet(TraceRestrictI
|
||||
STR_TRACE_RESTRICT_PF_DENY,
|
||||
STR_TRACE_RESTRICT_PF_PENALTY,
|
||||
STR_TRACE_RESTRICT_RESERVE_THROUGH,
|
||||
STR_TRACE_RESTRICT_LONG_RESERVE,
|
||||
INVALID_STRING_ID,
|
||||
};
|
||||
static const uint val_action[] = {
|
||||
TRIT_PF_DENY,
|
||||
TRIT_PF_PENALTY,
|
||||
TRIT_RESERVE_THROUGH,
|
||||
TRIT_LONG_RESERVE,
|
||||
};
|
||||
static const TraceRestrictDropDownListSet set_action = {
|
||||
str_action, val_action,
|
||||
@@ -665,6 +684,10 @@ static void DrawInstructionString(const TraceRestrictProgram *prog, TraceRestric
|
||||
instruction_string = GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_RESERVE_THROUGH_CANCEL : STR_TRACE_RESTRICT_RESERVE_THROUGH;
|
||||
break;
|
||||
|
||||
case TRIT_LONG_RESERVE:
|
||||
instruction_string = GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL : STR_TRACE_RESTRICT_LONG_RESERVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
break;
|
||||
@@ -870,6 +893,10 @@ public:
|
||||
this->ShowDropDownListWithValue(&_reserve_through_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0);
|
||||
break;
|
||||
|
||||
case TRVT_LONG_RESERVE:
|
||||
this->ShowDropDownListWithValue(&_long_reserve_value, GetTraceRestrictValue(item), false, TR_WIDGET_VALUE_DROPDOWN, 0, 0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1615,6 +1642,13 @@ private:
|
||||
GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_RESERVE_THROUGH_CANCEL : STR_TRACE_RESTRICT_RESERVE_THROUGH;
|
||||
break;
|
||||
|
||||
case TRVT_LONG_RESERVE:
|
||||
right_sel->SetDisplayedPlane(DPR_VALUE_DROPDOWN);
|
||||
this->EnableWidget(TR_WIDGET_VALUE_DROPDOWN);
|
||||
this->GetWidget<NWidgetCore>(TR_WIDGET_VALUE_DROPDOWN)->widget_data =
|
||||
GetTraceRestrictValue(item) ? STR_TRACE_RESTRICT_LONG_RESERVE_CANCEL : STR_TRACE_RESTRICT_LONG_RESERVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -35,18 +35,20 @@
|
||||
#include "order_backup.h"
|
||||
#include "zoom_func.h"
|
||||
#include "newgrf_debug.h"
|
||||
#include "tracerestrict.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/train_cmd.h"
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
|
||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *p_got_reservation, bool mark_stuck);
|
||||
static bool TrainCheckIfLineEnds(Train *v, bool reverse = true);
|
||||
bool TrainController(Train *v, Vehicle *nomove, bool reverse = true); // Also used in vehicle_sl.cpp.
|
||||
static TileIndex TrainApproachingCrossingTile(const Train *v);
|
||||
static void CheckIfTrainNeedsService(Train *v);
|
||||
static void CheckNextTrainTile(Train *v);
|
||||
TileIndex VehiclePosTraceRestrictPreviousSignalCallback(const Train *v, const void *);
|
||||
|
||||
static const byte _vehicle_initial_x_fract[4] = {10, 8, 4, 8};
|
||||
static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
|
||||
@@ -2336,12 +2338,14 @@ static Track DoTrainPathfind(const Train *v, TileIndex tile, DiagDirection enter
|
||||
/**
|
||||
* Extend a train path as far as possible. Stops on encountering a safe tile,
|
||||
* another reservation or a track choice.
|
||||
* @param v The train.
|
||||
* @param origin The tile from which the reservation have to be extended
|
||||
* @param new_tracks [out] Tracks to choose from when encountering a choice
|
||||
* @param enterdir [out] The direction from which the choice tile is to be entered
|
||||
* @return INVALID_TILE indicates that the reservation failed.
|
||||
*/
|
||||
static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
|
||||
static PBSTileInfo ExtendTrainReservation(const Train *v, const PBSTileInfo &origin, TrackBits *new_tracks, DiagDirection *enterdir)
|
||||
{
|
||||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
|
||||
CFollowTrackRail ft(v);
|
||||
|
||||
TileIndex tile = origin.tile;
|
||||
@@ -2520,8 +2524,37 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* choose a track */
|
||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
|
||||
static bool HasLongReservePbsSignalOnTrackdir(Train* v, TileIndex tile, Trackdir trackdir)
|
||||
{
|
||||
if (HasPbsSignalOnTrackdir(tile, trackdir)) {
|
||||
if (IsRestrictedSignal(tile)) {
|
||||
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(tile, TrackdirToTrack(trackdir));
|
||||
if (prog && prog->actions_used_flags & TRPAUF_LONG_RESERVE) {
|
||||
TraceRestrictProgramResult out;
|
||||
prog->Execute(v, TraceRestrictProgramInput(tile, trackdir, &VehiclePosTraceRestrictPreviousSignalCallback, nullptr), out);
|
||||
if (out.flags & TRPRF_LONG_RESERVE) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Choose a track and reserve if necessary
|
||||
*
|
||||
* @param v The vehicle
|
||||
* @param tile The tile from which to start
|
||||
* @param enterdir
|
||||
* @param tracks
|
||||
* @param force_res Force a reservation to be made
|
||||
* @param p_got_reservation [out] If the train has a reservation
|
||||
* @param mark_stuck The train has to be marked as stuck when needed
|
||||
* @return The track the train should take.
|
||||
*/
|
||||
static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *p_got_reservation, bool mark_stuck)
|
||||
{
|
||||
Track best_track = INVALID_TRACK;
|
||||
bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
|
||||
@@ -2529,7 +2562,8 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||
|
||||
assert((tracks & ~TRACK_BIT_MASK) == 0);
|
||||
|
||||
if (got_reservation != NULL) *got_reservation = false;
|
||||
bool got_reservation = false;
|
||||
if (p_got_reservation != NULL) *p_got_reservation = got_reservation;
|
||||
|
||||
/* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */
|
||||
TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir));
|
||||
@@ -2550,10 +2584,11 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||
best_track = track;
|
||||
}
|
||||
|
||||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false);
|
||||
DiagDirection dest_enterdir = enterdir;
|
||||
if (do_track_reservation) {
|
||||
res_dest = ExtendTrainReservation(v, &tracks, &dest_enterdir);
|
||||
res_dest = ExtendTrainReservation(v, origin, &tracks, &dest_enterdir);
|
||||
if (res_dest.tile == INVALID_TILE) {
|
||||
/* Reservation failed? */
|
||||
if (mark_stuck) MarkTrainAsStuck(v);
|
||||
@@ -2561,11 +2596,18 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||
return FindFirstTrack(tracks);
|
||||
}
|
||||
if (res_dest.okay) {
|
||||
/* Got a valid reservation that ends at a safe target, quick exit. */
|
||||
if (got_reservation != NULL) *got_reservation = true;
|
||||
if (changed_signal) MarkTileDirtyByTile(tile);
|
||||
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
|
||||
return best_track;
|
||||
CFollowTrackRail ft(v);
|
||||
if (ft.Follow(res_dest.tile, res_dest.trackdir)) {
|
||||
Trackdir new_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
|
||||
if (!HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td)) {
|
||||
/* Got a valid reservation that ends at a safe target, quick exit. */
|
||||
if (p_got_reservation != NULL) *p_got_reservation = true;
|
||||
if (changed_signal) MarkTileDirtyByTile(tile);
|
||||
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
|
||||
return best_track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the train needs service here, so it has a chance to always find a depot.
|
||||
@@ -2609,28 +2651,28 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||
/* A path was found, but could not be reserved. */
|
||||
if (res_dest.tile != INVALID_TILE && !res_dest.okay) {
|
||||
if (mark_stuck) MarkTrainAsStuck(v);
|
||||
FreeTrainTrackReservation(v);
|
||||
FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
|
||||
return best_track;
|
||||
}
|
||||
|
||||
/* No possible reservation target found, we are probably lost. */
|
||||
if (res_dest.tile == INVALID_TILE) {
|
||||
/* Try to find any safe destination. */
|
||||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
if (TryReserveSafeTrack(v, origin.tile, origin.trackdir, false)) {
|
||||
PBSTileInfo path_end = FollowTrainReservation(v);
|
||||
if (TryReserveSafeTrack(v, path_end.tile, path_end.trackdir, false)) {
|
||||
TrackBits res = GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir);
|
||||
best_track = FindFirstTrack(res);
|
||||
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
|
||||
if (got_reservation != NULL) *got_reservation = true;
|
||||
if (p_got_reservation != NULL) *p_got_reservation = true;
|
||||
if (changed_signal) MarkTileDirtyByTile(tile);
|
||||
} else {
|
||||
FreeTrainTrackReservation(v);
|
||||
FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
|
||||
if (mark_stuck) MarkTrainAsStuck(v);
|
||||
}
|
||||
return best_track;
|
||||
}
|
||||
|
||||
if (got_reservation != NULL) *got_reservation = true;
|
||||
got_reservation = true;
|
||||
|
||||
/* Reservation target found and free, check if it is safe. */
|
||||
while (!IsSafeWaitingPosition(v, res_dest.tile, res_dest.trackdir, true, _settings_game.pf.forbid_90_deg)) {
|
||||
@@ -2651,26 +2693,39 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
||||
res_dest = cur_dest;
|
||||
if (res_dest.okay) continue;
|
||||
/* Path found, but could not be reserved. */
|
||||
FreeTrainTrackReservation(v);
|
||||
FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
|
||||
if (mark_stuck) MarkTrainAsStuck(v);
|
||||
if (got_reservation != NULL) *got_reservation = false;
|
||||
got_reservation = false;
|
||||
changed_signal = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* No order or no safe position found, try any position. */
|
||||
if (!TryReserveSafeTrack(v, res_dest.tile, res_dest.trackdir, true)) {
|
||||
FreeTrainTrackReservation(v);
|
||||
FreeTrainTrackReservation(v, origin.tile, origin.trackdir);
|
||||
if (mark_stuck) MarkTrainAsStuck(v);
|
||||
if (got_reservation != NULL) *got_reservation = false;
|
||||
got_reservation = false;
|
||||
changed_signal = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (got_reservation) {
|
||||
CFollowTrackRail ft(v);
|
||||
if (ft.Follow(res_dest.tile, res_dest.trackdir)) {
|
||||
Trackdir new_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
|
||||
if (HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td)) {
|
||||
// We reserved up to a LR signal, reserve past it as well. recursion
|
||||
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), force_res, NULL, mark_stuck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
|
||||
|
||||
if (changed_signal) MarkTileDirtyByTile(tile);
|
||||
if (p_got_reservation != NULL) *p_got_reservation = got_reservation;
|
||||
|
||||
return best_track;
|
||||
}
|
||||
@@ -2721,7 +2776,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
||||
}
|
||||
|
||||
/* If we are in a depot, tentatively reserve the depot. */
|
||||
if (v->track == TRACK_BIT_DEPOT) {
|
||||
if (v->track == TRACK_BIT_DEPOT && v->tile == origin.tile) {
|
||||
SetDepotReservation(v->tile, true);
|
||||
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile);
|
||||
}
|
||||
@@ -2737,7 +2792,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
||||
|
||||
if (!res_made) {
|
||||
/* Free the depot reservation as well. */
|
||||
if (v->track == TRACK_BIT_DEPOT) SetDepotReservation(v->tile, false);
|
||||
if (v->track == TRACK_BIT_DEPOT && v->tile == origin.tile) SetDepotReservation(v->tile, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2895,7 +2950,13 @@ static inline void AffectSpeedByZChange(Train *v, int old_z)
|
||||
}
|
||||
}
|
||||
|
||||
static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
|
||||
enum TrainMovedChangeSignalEnum {
|
||||
CHANGED_NOTHING, ///< No special signals were changed
|
||||
CHANGED_NORMAL_TO_PBS_BLOCK, ///< A PBS block with a non-PBS signal facing us
|
||||
CHANGED_LR_PBS ///< A long reserve PBS signal
|
||||
};
|
||||
|
||||
static TrainMovedChangeSignalEnum TrainMovedChangeSignal(Train* v, TileIndex tile, DiagDirection dir)
|
||||
{
|
||||
if (IsTileType(tile, MP_RAILWAY) &&
|
||||
GetRailTileType(tile) == RAIL_TILE_SIGNALS) {
|
||||
@@ -2903,10 +2964,13 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir)
|
||||
Trackdir trackdir = FindFirstTrackdir(tracks);
|
||||
if (UpdateSignalsOnSegment(tile, TrackdirToExitdir(trackdir), GetTileOwner(tile)) == SIGSEG_PBS && HasSignalOnTrackdir(tile, trackdir)) {
|
||||
/* A PBS block with a non-PBS signal facing us? */
|
||||
if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
|
||||
if (!IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return CHANGED_NORMAL_TO_PBS_BLOCK;
|
||||
|
||||
if (HasLongReservePbsSignalOnTrackdir(v, tile, trackdir)) return CHANGED_LR_PBS;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return CHANGED_NOTHING;
|
||||
}
|
||||
|
||||
/** Tries to reserve track under whole train consist. */
|
||||
@@ -3367,27 +3431,51 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||
|
||||
if (update_signals_crossing) {
|
||||
if (v->IsFrontEngine()) {
|
||||
if (TrainMovedChangeSignals(gp.new_tile, enterdir)) {
|
||||
/* We are entering a block with PBS signals right now, but
|
||||
* not through a PBS signal. This means we don't have a
|
||||
* reservation right now. As a conventional signal will only
|
||||
* ever be green if no other train is in the block, getting
|
||||
* a path should always be possible. If the player built
|
||||
* such a strange network that it is not possible, the train
|
||||
* will be marked as stuck and the player has to deal with
|
||||
* the problem. */
|
||||
if ((!HasReservedTracks(gp.new_tile, v->track) &&
|
||||
!TryReserveRailTrack(gp.new_tile, FindFirstTrack(v->track))) ||
|
||||
!TryPathReserve(v)) {
|
||||
MarkTrainAsStuck(v);
|
||||
}
|
||||
switch (TrainMovedChangeSignal(v, gp.new_tile, enterdir)) {
|
||||
case CHANGED_NORMAL_TO_PBS_BLOCK:
|
||||
/* We are entering a block with PBS signals right now, but
|
||||
* not through a PBS signal. This means we don't have a
|
||||
* reservation right now. As a conventional signal will only
|
||||
* ever be green if no other train is in the block, getting
|
||||
* a path should always be possible. If the player built
|
||||
* such a strange network that it is not possible, the train
|
||||
* will be marked as stuck and the player has to deal with
|
||||
* the problem. */
|
||||
if ((!HasReservedTracks(gp.new_tile, v->track) &&
|
||||
!TryReserveRailTrack(gp.new_tile, FindFirstTrack(v->track))) ||
|
||||
!TryPathReserve(v)) {
|
||||
MarkTrainAsStuck(v);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CHANGED_LR_PBS:
|
||||
{
|
||||
/* We went past a long reserve PBS signal. Try to extend the
|
||||
* reservation if reserving failed at another LR signal. */
|
||||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
CFollowTrackRail ft(v);
|
||||
|
||||
if (ft.Follow(origin.tile, origin.trackdir)) {
|
||||
Trackdir new_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
|
||||
if (HasLongReservePbsSignalOnTrackdir(v, ft.m_new_tile, new_td)) {
|
||||
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, TrackdirBitsToTrackBits(ft.m_new_td_bits), true, NULL, false);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Signals can only change when the first
|
||||
* (above) or the last vehicle moves. */
|
||||
if (v->Next() == NULL) {
|
||||
TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
|
||||
TrainMovedChangeSignal(v, gp.old_tile, ReverseDiagDir(enterdir));
|
||||
if (IsLevelCrossingTile(gp.old_tile)) UpdateLevelCrossing(gp.old_tile);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user