mirror of https://github.com/OpenTTD/OpenTTD
(svn r13955) -Codechange [YAPP]: Try to extend the path of a stuck train so it is able to continue. (michi_cc)
parent
e9b62103e4
commit
bd0a420744
|
@ -988,6 +988,7 @@ STR_CANT_SHARE_ORDER_LIST :{WHITE}Can't sh
|
|||
STR_CANT_COPY_ORDER_LIST :{WHITE}Can't copy order list...
|
||||
STR_END_OF_SHARED_ORDERS :{SETX 10}- - End of Shared Orders - -
|
||||
|
||||
STR_TRAIN_IS_STUCK :{WHITE}Train {COMMA} can't find a path to continue.
|
||||
STR_TRAIN_IS_LOST :{WHITE}Train {COMMA} is lost.
|
||||
STR_TRAIN_IS_UNPROFITABLE :{WHITE}Train {COMMA}'s profit last year was {CURRENCY}
|
||||
STR_EURO_INTRODUCE :{BLACK}{BIGFONT}European Monetary Union!{}{}The Euro is introduced as the sole currency for everyday transactions in your country!
|
||||
|
|
|
@ -274,6 +274,7 @@ void UpdateTrainAcceleration(Vehicle* v);
|
|||
void CheckTrainsLengths();
|
||||
|
||||
void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
|
||||
bool TryPathReserve(Vehicle *v, bool mark_as_stuck = false, bool first_tile_okay = false);
|
||||
|
||||
/**
|
||||
* This class 'wraps' Vehicle; you do not actually instantiate this class.
|
||||
|
|
|
@ -2833,6 +2833,79 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir
|
|||
return best_track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to reserve a path to a safe position.
|
||||
*
|
||||
* @param v The vehicle
|
||||
* @return True if a path could be reserved
|
||||
*/
|
||||
bool TryPathReserve(Vehicle *v, bool first_tile_okay, bool mark_as_stuck)
|
||||
{
|
||||
assert(v->type == VEH_TRAIN && IsFrontEngine(v));
|
||||
|
||||
/* We have to handle depots specially as the track follower won't look
|
||||
* at the depot tile itself but starts from the next tile. If we are still
|
||||
* inside the depot, a depot reservation can never be ours. */
|
||||
if (v->u.rail.track & TRACK_BIT_DEPOT) {
|
||||
if (GetDepotWaypointReservation(v->tile)) {
|
||||
if (mark_as_stuck) MarkTrainAsStuck(v);
|
||||
return false;
|
||||
} else {
|
||||
/* Depot not reserved, but the next tile might be. */
|
||||
TileIndex next_tile = TileAddByDiagDir(v->tile, GetRailDepotDirection(v->tile));
|
||||
if (HasReservedTracks(next_tile, DiagdirReachesTracks(GetRailDepotDirection(v->tile)))) return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Special check if we are in front of a two-sided conventional signal. */
|
||||
DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
|
||||
TileIndex next_tile = TileAddByDiagDir(v->tile, dir);
|
||||
if (IsTileType(next_tile, MP_RAILWAY) && HasReservedTracks(next_tile, DiagdirReachesTracks(dir))) {
|
||||
/* Can have only one reserved trackdir. */
|
||||
Trackdir td = FindFirstTrackdir((TrackdirBits)(GetReservedTrackbits(next_tile) * 0x101 & DiagdirReachesTrackdirs(dir)));
|
||||
if (HasSignalOnTrackdir(next_tile, td) && HasSignalOnTrackdir(next_tile, ReverseTrackdir(td)) &&
|
||||
!IsPbsSignal(GetSignalType(next_tile, TrackdirToTrack(td)))) {
|
||||
/* Signal already reserved, is not ours. */
|
||||
if (mark_as_stuck) MarkTrainAsStuck(v);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
PBSTileInfo origin = FollowTrainReservation(v);
|
||||
/* If we have a reserved path and the path ends at a safe tile, we are finished already. */
|
||||
if (origin.okay && (v->tile != origin.tile || first_tile_okay)) {
|
||||
/* Can't be stuck then. */
|
||||
if (HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If we are in a depot, tentativly reserve the depot. */
|
||||
if (v->u.rail.track & TRACK_BIT_DEPOT) {
|
||||
SetDepotWaypointReservation(v->tile, true);
|
||||
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile);
|
||||
}
|
||||
|
||||
DiagDirection exitdir = TrackdirToExitdir(origin.trackdir);
|
||||
TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir);
|
||||
TrackBits reachable = TrackdirBitsToTrackBits((TrackdirBits)GetTileTrackStatus(new_tile, TRANSPORT_RAIL, 0) & DiagdirReachesTrackdirs(exitdir));
|
||||
|
||||
if (_settings_game.pf.pathfinder_for_trains != VPF_NTP && _settings_game.pf.forbid_90_deg) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir));
|
||||
|
||||
bool res_made = false;
|
||||
ChooseTrainTrack(v, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck);
|
||||
|
||||
if (!res_made) {
|
||||
/* Free the depot reservation as well. */
|
||||
if (v->u.rail.track & TRACK_BIT_DEPOT) SetDepotWaypointReservation(v->tile, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static bool CheckReverseTrain(Vehicle *v)
|
||||
{
|
||||
|
@ -3873,6 +3946,38 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
|
|||
|
||||
if (!mode) HandleLocomotiveSmokeCloud(v);
|
||||
|
||||
/* Handle stuck trains. */
|
||||
if (!mode && HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) {
|
||||
++v->load_unload_time_rem;
|
||||
|
||||
/* Should we try reversing this tick if still stuck? */
|
||||
bool turn_around = v->load_unload_time_rem % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.wait_for_pbs_path < 255;
|
||||
|
||||
if (!turn_around && v->u.rail.force_proceed == 0) return;
|
||||
if (!TryPathReserve(v)) {
|
||||
/* Still stuck. */
|
||||
if (turn_around) ReverseTrainDirection(v);
|
||||
|
||||
if (HasBit(v->u.rail.flags, VRF_TRAIN_STUCK) && v->load_unload_time_rem > 2 * _settings_game.pf.wait_for_pbs_path * DAY_TICKS) {
|
||||
/* Show message to player. */
|
||||
if (_settings_client.gui.lost_train_warn && v->owner == _local_player) {
|
||||
SetDParam(0, v->unitnumber);
|
||||
AddNewsItem(
|
||||
STR_TRAIN_IS_STUCK,
|
||||
NS_ADVICE,
|
||||
v->index,
|
||||
0);
|
||||
}
|
||||
v->load_unload_time_rem = 0;
|
||||
}
|
||||
/* Exit if force proceed not pressed, else reset stuck flag anyway. */
|
||||
if (v->u.rail.force_proceed == 0) return;
|
||||
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
|
||||
v->load_unload_time_rem = 0;
|
||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
}
|
||||
}
|
||||
|
||||
int j = UpdateTrainSpeed(v);
|
||||
|
||||
/* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
|
||||
|
|
Loading…
Reference in New Issue