--- a/src/train_cmd.cpp Thu Feb 21 22:34:54 2008 +0000
+++ b/src/train_cmd.cpp Fri Feb 22 00:25:54 2008 +0000
@@ -736,6 +736,7 @@
v->x_pos = x;
v->y_pos = y;
v->z_pos = GetSlopeZ(x, y);
+ v->running_ticks = 0;
v->u.rail.track = TRACK_BIT_DEPOT;
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
v->spritenum = rvi->image_index;
@@ -994,7 +995,7 @@
if (HasBit(p2, 0) && src_head == dst_head) return CommandCost();
{
- int max_len = _patches.mammoth_trains ? 100 : 9;
+ int max_len = _patches.mammoth_trains ? 100 : 10;
/* check if all vehicles in the source train are stopped inside a depot. */
int src_len = CheckTrainStoppedInDepot(src_head);
@@ -1445,7 +1446,7 @@
* up on a new line to be added to the newly built loco. Replace it is.
* Totally braindead cause building a new engine adds all loco-less
* engines to its train anyways */
- if (p2 == 2 && HasBit(ori_subtype, Train_Front)) {
+ if (p2 == 2 && HasBit(ori_subtype, TS_FRONT)) {
Vehicle *tmp;
for (v = first; v != NULL; v = tmp) {
tmp = GetNextVehicle(v);
@@ -1544,7 +1545,7 @@
EndVehicleMove(v);
}
-static void SetLastSpeed(Vehicle* v, int spd)
+static inline void SetLastSpeed(Vehicle* v, int spd)
{
int old = v->u.rail.last_speed;
if (spd != old) {
@@ -1667,7 +1668,7 @@
{
assert(IsLevelCrossingTile(tile));
- DiagDirection dir = AxisToDiagDir(OtherAxis(GetCrossingRoadAxis(tile)));
+ DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
TileIndex tile_from = tile + TileOffsByDiagDir(dir);
Vehicle *v = (Vehicle *)VehicleFromPos(tile_from, &tile, &TrainApproachingCrossingEnum);
@@ -2001,7 +2002,7 @@
TrainFindDepotData tfdd;
tfdd.owner = v->owner;
- tfdd.best_length = (uint)-1;
+ tfdd.best_length = UINT_MAX;
tfdd.reverse = false;
TileIndex tile = v->tile;
@@ -2011,36 +2012,43 @@
return tfdd;
}
- if (_patches.yapf.rail_use_yapf) {
- bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
- tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
- } else if (_patches.new_pathfinding_all) {
- Vehicle* last = GetLastVehicleInChain(v);
- Trackdir trackdir = GetVehicleTrackdir(v);
- Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
-
- assert(trackdir != INVALID_TRACKDIR);
- NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
- if (ftd.best_bird_dist == 0) {
- /* Found target */
- tfdd.tile = ftd.node.tile;
- /* Our caller expects a number of tiles, so we just approximate that
- * number by this. It might not be completely what we want, but it will
- * work for now :-) We can possibly change this when the old pathfinder
- * is removed. */
- tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
- if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
- }
- } else {
- /* search in the forward direction first. */
- DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
- NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
- if (tfdd.best_length == (uint)-1){
- tfdd.reverse = true;
- /* search in backwards direction */
- i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
+ switch (_patches.pathfinder_for_trains) {
+ case VPF_YAPF: { /* YAPF */
+ bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
+ tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
+ } break;
+
+ case VPF_NPF: { /* NPF */
+ Vehicle* last = GetLastVehicleInChain(v);
+ Trackdir trackdir = GetVehicleTrackdir(v);
+ Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
+
+ assert(trackdir != INVALID_TRACKDIR);
+ NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
+ if (ftd.best_bird_dist == 0) {
+ /* Found target */
+ tfdd.tile = ftd.node.tile;
+ /* Our caller expects a number of tiles, so we just approximate that
+ * number by this. It might not be completely what we want, but it will
+ * work for now :-) We can possibly change this when the old pathfinder
+ * is removed. */
+ tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
+ if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
+ }
+ } break;
+
+ default:
+ case VPF_NTP: { /* NTP */
+ /* search in the forward direction first. */
+ DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
- }
+ if (tfdd.best_length == UINT_MAX){
+ tfdd.reverse = true;
+ /* search in backwards direction */
+ i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
+ NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
+ }
+ } break;
}
return tfdd;
@@ -2203,7 +2211,7 @@
if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT);
}
-static void TrainPlayLeaveStationSound(const Vehicle* v)
+void Train::PlayLeaveStationSound() const
{
static const SoundFx sfx[] = {
SND_04_TRAIN,
@@ -2213,15 +2221,10 @@
SND_41_MAGLEV
};
- if (PlayVehicleSound(v, VSE_START)) return;
-
- EngineID engtype = v->engine_type;
- SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v);
-}
-
-void Train::PlayLeaveStationSound() const
-{
- TrainPlayLeaveStationSound(this);
+ if (PlayVehicleSound(this, VSE_START)) return;
+
+ EngineID engtype = this->engine_type;
+ SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
}
static bool CheckTrainStayInDepot(Vehicle *v)
@@ -2254,7 +2257,7 @@
VehicleServiceInDepot(v);
InvalidateWindowClasses(WC_TRAINS_LIST);
- TrainPlayLeaveStationSound(v);
+ v->PlayLeaveStationSound();
v->u.rail.track = TRACK_BIT_X;
if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y;
@@ -2364,68 +2367,76 @@
/* quick return in case only one possible track is available */
if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
- if (_patches.yapf.rail_use_yapf) {
- Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
- if (trackdir != INVALID_TRACKDIR) {
- best_track = TrackdirToTrack(trackdir);
- } else {
- best_track = FindFirstTrack(tracks);
- }
- } else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
- void* perf = NpfBeginInterval();
-
- NPFFindStationOrTileData fstd;
- NPFFillWithOrderData(&fstd, v);
- /* The enterdir for the new tile, is the exitdir for the old tile */
- Trackdir trackdir = GetVehicleTrackdir(v);
- assert(trackdir != 0xff);
-
- NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
-
- if (ftd.best_trackdir == 0xff) {
- /* We are already at our target. Just do something
- * @todo maybe display error?
- * @todo: go straight ahead if possible? */
- best_track = FindFirstTrack(tracks);
- } else {
- /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
- the direction we need to take to get there, if ftd.best_bird_dist is not 0,
- we did not find our target, but ftd.best_trackdir contains the direction leading
- to the tile closest to our target. */
- if (ftd.best_bird_dist != 0) path_not_found = true;
- /* Discard enterdir information, making it a normal track */
- best_track = TrackdirToTrack(ftd.best_trackdir);
- }
-
- int time = NpfEndInterval(perf);
- DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
- } else {
- void* perf = NpfBeginInterval();
-
- TrainTrackFollowerData fd;
- FillWithStationData(&fd, v);
-
- /* New train pathfinding */
- fd.best_bird_dist = (uint)-1;
- fd.best_track_dist = (uint)-1;
- fd.best_track = INVALID_TRACKDIR;
-
- NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
- v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
-
- /* check whether the path was found or only 'guessed' */
- if (fd.best_bird_dist != 0) path_not_found = true;
-
- if (fd.best_track == 0xff) {
- /* blaha */
- best_track = FindFirstTrack(tracks);
- } else {
- best_track = TrackdirToTrack(fd.best_track);
- }
-
- int time = NpfEndInterval(perf);
- DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
+ switch (_patches.pathfinder_for_trains) {
+ case VPF_YAPF: { /* YAPF */
+ Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
+ if (trackdir != INVALID_TRACKDIR) {
+ best_track = TrackdirToTrack(trackdir);
+ } else {
+ best_track = FindFirstTrack(tracks);
+ }
+ } break;
+
+ case VPF_NPF: { /* NPF */
+ void *perf = NpfBeginInterval();
+
+ NPFFindStationOrTileData fstd;
+ NPFFillWithOrderData(&fstd, v);
+ /* The enterdir for the new tile, is the exitdir for the old tile */
+ Trackdir trackdir = GetVehicleTrackdir(v);
+ assert(trackdir != INVALID_TRACKDIR);
+
+ NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
+
+ if (ftd.best_trackdir == INVALID_TRACKDIR) {
+ /* We are already at our target. Just do something
+ * @todo maybe display error?
+ * @todo: go straight ahead if possible? */
+ best_track = FindFirstTrack(tracks);
+ } else {
+ /* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
+ * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
+ * we did not find our target, but ftd.best_trackdir contains the direction leading
+ * to the tile closest to our target. */
+ if (ftd.best_bird_dist != 0) path_not_found = true;
+ /* Discard enterdir information, making it a normal track */
+ best_track = TrackdirToTrack(ftd.best_trackdir);
+ }
+
+ int time = NpfEndInterval(perf);
+ DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
+ } break;
+
+ default:
+ case VPF_NTP: { /* NTP */
+ void *perf = NpfBeginInterval();
+
+ TrainTrackFollowerData fd;
+ FillWithStationData(&fd, v);
+
+ /* New train pathfinding */
+ fd.best_bird_dist = UINT_MAX;
+ fd.best_track_dist = UINT_MAX;
+ fd.best_track = INVALID_TRACKDIR;
+
+ NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
+ v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
+
+ /* check whether the path was found or only 'guessed' */
+ if (fd.best_bird_dist != 0) path_not_found = true;
+
+ if (fd.best_track == INVALID_TRACKDIR) {
+ /* blaha */
+ best_track = FindFirstTrack(tracks);
+ } else {
+ best_track = TrackdirToTrack(fd.best_track);
+ }
+
+ int time = NpfEndInterval(perf);
+ DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
+ } break;
}
+
/* handle "path not found" state */
if (path_not_found) {
/* PF didn't find the route */
@@ -2475,81 +2486,87 @@
int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)];
- if (_patches.yapf.rail_use_yapf) {
- reverse_best = YapfCheckReverseTrain(v);
- } else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
- NPFFindStationOrTileData fstd;
- NPFFoundTargetData ftd;
- Trackdir trackdir, trackdir_rev;
- Vehicle* last = GetLastVehicleInChain(v);
-
- NPFFillWithOrderData(&fstd, v);
-
- trackdir = GetVehicleTrackdir(v);
- trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
- assert(trackdir != 0xff);
- assert(trackdir_rev != 0xff);
-
- ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
- if (ftd.best_bird_dist != 0) {
- /* We didn't find anything, just keep on going straight ahead */
- reverse_best = false;
- } else {
- if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
- reverse_best = true;
+ switch (_patches.pathfinder_for_trains) {
+ case VPF_YAPF: { /* YAPF */
+ reverse_best = YapfCheckReverseTrain(v);
+ } break;
+
+ case VPF_NPF: { /* NPF */
+ NPFFindStationOrTileData fstd;
+ NPFFoundTargetData ftd;
+ Vehicle* last = GetLastVehicleInChain(v);
+
+ NPFFillWithOrderData(&fstd, v);
+
+ Trackdir trackdir = GetVehicleTrackdir(v);
+ Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
+ assert(trackdir != INVALID_TRACKDIR);
+ assert(trackdir_rev != INVALID_TRACKDIR);
+
+ ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
+ if (ftd.best_bird_dist != 0) {
+ /* We didn't find anything, just keep on going straight ahead */
+ reverse_best = false;
} else {
- reverse_best = false;
+ if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
+ reverse_best = true;
+ } else {
+ reverse_best = false;
+ }
}
- }
- } else {
- int best_track = -1;
- uint reverse = 0;
- uint best_bird_dist = 0;
- uint best_track_dist = 0;
-
- for (;;) {
- fd.best_bird_dist = (uint)-1;
- fd.best_track_dist = (uint)-1;
-
- NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
-
- if (best_track != -1) {
- if (best_bird_dist != 0) {
- if (fd.best_bird_dist != 0) {
- /* neither reached the destination, pick the one with the smallest bird dist */
- if (fd.best_bird_dist > best_bird_dist) goto bad;
- if (fd.best_bird_dist < best_bird_dist) goto good;
+ } break;
+
+ default:
+ case VPF_NTP: { /* NTP */
+ int best_track = -1;
+ uint reverse = 0;
+ uint best_bird_dist = 0;
+ uint best_track_dist = 0;
+
+ for (;;) {
+ fd.best_bird_dist = UINT_MAX;
+ fd.best_track_dist = UINT_MAX;
+
+ NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
+
+ if (best_track != -1) {
+ if (best_bird_dist != 0) {
+ if (fd.best_bird_dist != 0) {
+ /* neither reached the destination, pick the one with the smallest bird dist */
+ if (fd.best_bird_dist > best_bird_dist) goto bad;
+ if (fd.best_bird_dist < best_bird_dist) goto good;
+ } else {
+ /* we found the destination for the first time */
+ goto good;
+ }
} else {
- /* we found the destination for the first time */
- goto good;
+ if (fd.best_bird_dist != 0) {
+ /* didn't find destination, but we've found the destination previously */
+ goto bad;
+ } else {
+ /* both old & new reached the destination, compare track length */
+ if (fd.best_track_dist > best_track_dist) goto bad;
+ if (fd.best_track_dist < best_track_dist) goto good;
+ }
}
- } else {
- if (fd.best_bird_dist != 0) {
- /* didn't find destination, but we've found the destination previously */
- goto bad;
- } else {
- /* both old & new reached the destination, compare track length */
- if (fd.best_track_dist > best_track_dist) goto bad;
- if (fd.best_track_dist < best_track_dist) goto good;
- }
+
+ /* if we reach this position, there's two paths of equal value so far.
+ * pick one randomly. */
+ int r = GB(Random(), 0, 8);
+ if (_pick_track_table[i] == (v->direction & 3)) r += 80;
+ if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
+ if (r <= 127) goto bad;
}
-
- /* if we reach this position, there's two paths of equal value so far.
- * pick one randomly. */
- int r = GB(Random(), 0, 8);
- if (_pick_track_table[i] == (v->direction & 3)) r += 80;
- if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
- if (r <= 127) goto bad;
+good:;
+ best_track = i;
+ best_bird_dist = fd.best_bird_dist;
+ best_track_dist = fd.best_track_dist;
+ reverse_best = reverse;
+bad:;
+ if (reverse != 0) break;
+ reverse = 2;
}
-good:;
- best_track = i;
- best_bird_dist = fd.best_bird_dist;
- best_track_dist = fd.best_track_dist;
- reverse_best = reverse;
-bad:;
- if (reverse != 0) break;
- reverse = 2;
- }
+ } break;
}
return reverse_best != 0;
@@ -2755,7 +2772,7 @@
DIR_E , DIR_SE, DIR_S
};
-static Direction GetNewVehicleDirectionByTile(TileIndex new_tile, TileIndex old_tile)
+static inline Direction GetNewVehicleDirectionByTile(TileIndex new_tile, TileIndex old_tile)
{
uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
TileX(new_tile) - TileX(old_tile) + 1;
@@ -2763,7 +2780,7 @@
return _new_vehicle_direction_table[offs];
}
-static int GetDirectionToVehicle(const Vehicle *v, int x, int y)
+static inline int GetDirectionToVehicle(const Vehicle *v, int x, int y)
{
byte offs;
@@ -2786,7 +2803,7 @@
}
/* Check if the vehicle is compatible with the specified tile */
-static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
+static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
{
return
IsTileOwner(tile, v->owner) && (
@@ -2810,7 +2827,7 @@
};
/** Modify the speed of the vehicle due to a turn */
-static void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
+static inline void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
{
if (_patches.realistic_acceleration) return;
@@ -2822,7 +2839,7 @@
}
/** Modify the speed of the vehicle due to a change in altitude */
-static void AffectSpeedByZChange(Vehicle *v, byte old_z)
+static inline void AffectSpeedByZChange(Vehicle *v, byte old_z)
{
if (old_z == v->z_pos || _patches.realistic_acceleration) return;
@@ -3025,14 +3042,12 @@
/* Get the status of the tracks in the new tile and mask
* away the bits that aren't reachable. */
- uint32 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0) & _reachable_tracks[enterdir];
-
- /* Combine the from & to directions.
- * Now, the lower byte contains the track status, and the byte at bit 16 contains
- * the signal status. */
- uint32 tracks = ts | (ts >> 8);
- TrackBits bits = (TrackBits)(tracks & TRACK_BIT_MASK);
- if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg && prev == NULL) {
+ TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir)) & _reachable_tracks[enterdir];
+ TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
+ TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts));
+
+ TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
+ if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) {
/* We allow wagons to make 90 deg turns, because forbid_90_deg
* can be switched on halfway a turn */
bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
@@ -3049,14 +3064,12 @@
/* Currently the locomotive is active. Determine which one of the
* available tracks to choose */
chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
- assert(chosen_track & tracks);
+ assert(chosen_track & bits);
/* Check if it's a red signal and that force proceed is not clicked. */
- if ((tracks >> 16) & chosen_track && v->u.rail.force_proceed == 0) {
- /* In front of a red signal
- * find the first set bit in ts. need to do it in 2 steps, since
- * FIND_FIRST_BIT only handles 6 bits at a time. */
- Trackdir i = FindFirstTrackdir((TrackdirBits)(uint16)ts);
+ if (red_signals & chosen_track && v->u.rail.force_proceed == 0) {
+ /* In front of a red signal */
+ Trackdir i = FindFirstTrackdir(trackdirbits);
if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
v->cur_speed = 0;
@@ -3134,7 +3147,7 @@
* - for bridges, only the middle part - without the bridge heads */
if (!(v->vehstatus & VS_HIDDEN)) {
v->cur_speed =
- min(v->cur_speed, GetBridge(GetBridgeType(v->tile))->speed);
+ min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed);
}
if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
@@ -3422,9 +3435,9 @@
DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
TileIndex tile = v->tile + TileOffsByDiagDir(dir);
- /* not a crossing || wrong axis || wrong railtype || wrong owner */
+ /* not a crossing || wrong axis || unusable rail (wrong type or owner) */
if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
- !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner) {
+ !CheckCompatibleRail(v, tile)) {
return INVALID_TILE;
}
@@ -3460,20 +3473,25 @@
TileIndex tile = v->tile + TileOffsByDiagDir(dir);
/* Determine the track status on the next tile */
- uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir];
+ TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir)) & _reachable_tracks[dir];
+ TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
+ TrackdirBits red_signals = TrackStatusToRedSignals(ts);
/* We are sure the train is not entering a depot, it is detected above */
- /* no suitable trackbits at all || wrong railtype || not our track ||
- * tunnel/bridge from opposite side || depot from opposite side */
- if (GB(ts, 0, 16) == 0 || !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner ||
- (IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != dir) ||
- (IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) == dir) ) {
+ /* mask unreachable track bits if we are forbidden to do 90deg turns */
+ TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
+ if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) {
+ bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
+ }
+
+ /* no suitable trackbits at all || unusable rail (wrong type or owner) */
+ if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) {
return TrainApproachingLineEnd(v, false);
}
/* approaching red signal */
- if ((ts & (ts >> 16)) != 0) return TrainApproachingLineEnd(v, true);
+ if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true);
/* approaching a rail/road crossing? then make it red */
if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
@@ -3558,10 +3576,10 @@
do {
const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
- byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
+ byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost);
if (cost_factor == 0) continue;
- cost += cost_factor * _price.running_rail[rvi->running_cost_class];
+ cost += cost_factor * GetPriceByIndex(rvi->running_cost_class);
} while ((v = GetNextVehicle(v)) != NULL);
return cost;
@@ -3575,6 +3593,7 @@
this->tick_counter++;
if (IsFrontEngine(this)) {
+ if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
this->current_order_time++;
TrainLocoHandler(this, false);
@@ -3645,11 +3664,12 @@
if (tile != 0) this->dest_tile = tile;
}
- if ((this->vehstatus & VS_STOPPED) == 0) {
+ if (this->running_ticks != 0) {
/* running costs */
- CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() / 364);
-
- this->profit_this_year -= cost.GetCost() >> 8;
+ CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (364 * DAY_TICKS));
+
+ this->profit_this_year -= cost.GetCost();
+ this->running_ticks = 0;
SubtractMoneyFromPlayerFract(this->owner, cost);
@@ -3669,8 +3689,8 @@
FOR_ALL_VEHICLES(v) {
if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
/* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
- if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
- SetDParam(1, v->profit_this_year);
+ if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) {
+ SetDParam(1, v->GetDisplayProfitThisYear());
SetDParam(0, v->unitnumber);
AddNewsItem(
STR_TRAIN_IS_UNPROFITABLE,