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_CANT_COPY_ORDER_LIST :{WHITE}Can't copy order list...
|
||||||
STR_END_OF_SHARED_ORDERS :{SETX 10}- - End of Shared Orders - -
|
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_LOST :{WHITE}Train {COMMA} is lost.
|
||||||
STR_TRAIN_IS_UNPROFITABLE :{WHITE}Train {COMMA}'s profit last year was {CURRENCY}
|
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!
|
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 CheckTrainsLengths();
|
||||||
|
|
||||||
void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
|
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.
|
* 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;
|
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)
|
static bool CheckReverseTrain(Vehicle *v)
|
||||||
{
|
{
|
||||||
|
@ -3873,6 +3946,38 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
|
||||||
|
|
||||||
if (!mode) HandleLocomotiveSmokeCloud(v);
|
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);
|
int j = UpdateTrainSpeed(v);
|
||||||
|
|
||||||
/* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
|
/* we need to invalidate the widget if we are stopping from 'Stopping 0 km/h' to 'Stopped' */
|
||||||
|
|
Loading…
Reference in New Issue