--- a/train_cmd.c Mon Jan 01 23:37:39 2007 +0000
+++ b/train_cmd.c Mon Jan 01 23:43:24 2007 +0000
@@ -3029,11 +3029,42 @@
/* For every vehicle after and including the given vehicle */
for (prev = GetPrevVehicleInChain(v); v != NULL; prev = v, v = v->next) {
+
+ bool in_tunnel_or_bridge = (v->u.rail.track == 0x40);
+ bool entering_new_tile;
+
BeginVehicleMove(v);
- if (v->u.rail.track != 0x40) {
+ entering_new_tile = !GetNewVehiclePos(v, &gp);
+
+ if (in_tunnel_or_bridge) {
+ uint32 res;
+ /* in tunnel or on a bridge */
+
+ SetSpeedLimitOnBridge(v);
+
+ if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !((res = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)) & 0x4)) {
+ /* stay in tunnel/bridge wormhole */
+ v->x_pos = gp.x;
+ v->y_pos = gp.y;
+ VehiclePositionChanged(v);
+ if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
+ continue;
+ }
+ /* left tunnel/bridge wormhole */
+ dir = v->direction;
+ enterdir = INVALID_DIAGDIR;
+ if (IsBridgeTile(gp.new_tile) && res & 0x4) {
+ /* ok we have just left the bridge (because the status was "onbridge" before and we got
+ a return value of 4 from VehicleEnterTile. we know the enterdir from the bridge ramp
+ direction, and act as if we entered the tile normally (hence the goto) */
+ dir = v->direction;
+ enterdir = ReverseDiagDir(GetBridgeRampDirection(gp.new_tile));
+ in_tunnel_or_bridge = false;
+ }
+ } else {
/* Not inside tunnel */
- if (GetNewVehiclePos(v, &gp)) {
+ if (!entering_new_tile) {
/* Staying in the old tile */
if (v->u.rail.track == 0x80) {
/* inside depot */
@@ -3061,126 +3092,105 @@
}
}
} else {
- /* A new tile is about to be entered. */
-
- byte bits;
+ /* A new tile is about to be entered normally (not from bridge wormhole to ramp) */
/* Determine what direction we're entering the new tile from */
dir = GetNewVehicleDirectionByTile(gp.new_tile, gp.old_tile);
enterdir = DirToDiagDir(dir);
assert(enterdir==0 || enterdir==1 || enterdir==2 || enterdir==3);
-new_tile:
-
- /* Get the status of the tracks in the new tile and mask
- * away the bits that aren't reachable. */
- ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _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. */
- tracks = ts | (ts >> 8);
- bits = tracks & 0xFF;
- if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _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(FIND_FIRST_BIT(v->u.rail.track));
- }
-
- if (bits == 0) {
- DEBUG(misc, 2, "%x == 0", bits);
- goto invalid_rail;
- }
-
- /* Check if the new tile contrains tracks that are compatible
- * with the current train, if not, bail out. */
- if (!CheckCompatibleRail(v, gp.new_tile)) {
- DEBUG(misc, 2, "!CheckCompatibleRail(%p, %x)", v, gp.new_tile);
- goto invalid_rail;
- }
-
- if (prev == NULL) {
- /* Currently the locomotive is active. Determine which one of the
- * available tracks to choose */
- chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits);
- assert(chosen_track & tracks);
-
- /* 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) goto red_light;
- } else {
- static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2};
-
- /* The wagon is active, simply follow the prev vehicle. */
- chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits);
- }
-
- /* make sure chosen track is a valid track */
- assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32);
-
- /* Update XY to reflect the entrance to the new tile, and select the direction to use */
- {
- const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir];
- gp.x = (gp.x & ~0xF) | b[0];
- gp.y = (gp.y & ~0xF) | b[1];
- chosen_dir = b[2];
+ }
+ }
+ if (entering_new_tile && !in_tunnel_or_bridge) {
+ /* A new tile is about to be entered. */
+ byte bits;
+
+ /* Get the status of the tracks in the new tile and mask
+ * away the bits that aren't reachable. */
+ ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL) & _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. */
+ tracks = ts | (ts >> 8);
+ bits = tracks & 0xFF;
+ if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _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(FIND_FIRST_BIT(v->u.rail.track));
+ }
+
+ if (bits == 0) {
+ DEBUG(misc, 2, "%x == 0", bits);
+ goto invalid_rail;
+ }
+
+ /* Check if the new tile contrains tracks that are compatible
+ * with the current train, if not, bail out. */
+ if (!CheckCompatibleRail(v, gp.new_tile)) {
+ DEBUG(misc, 2, "!CheckCompatibleRail(%p, %x)", v, gp.new_tile);
+ goto invalid_rail;
+ }
+
+ if (prev == NULL) {
+ /* Currently the locomotive is active. Determine which one of the
+ * available tracks to choose */
+ chosen_track = 1 << ChooseTrainTrack(v, gp.new_tile, enterdir, bits);
+ assert(chosen_track & tracks);
+
+ /* 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) goto red_light;
+ } else {
+ static byte _matching_tracks[8] = {0x30, 1, 0xC, 2, 0x30, 1, 0xC, 2};
+
+ /* The wagon is active, simply follow the prev vehicle. */
+ chosen_track = (byte)(_matching_tracks[GetDirectionToVehicle(prev, gp.x, gp.y)] & bits);
+ }
+
+ /* make sure chosen track is a valid track */
+ assert(chosen_track==1 || chosen_track==2 || chosen_track==4 || chosen_track==8 || chosen_track==16 || chosen_track==32);
+
+ /* Update XY to reflect the entrance to the new tile, and select the direction to use */
+ {
+ const byte *b = _initial_tile_subcoord[FIND_FIRST_BIT(chosen_track)][enterdir];
+ gp.x = (gp.x & ~0xF) | b[0];
+ gp.y = (gp.y & ~0xF) | b[1];
+ chosen_dir = b[2];
+ }
+
+ /* Call the landscape function and tell it that the vehicle entered the tile */
+ r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
+ if (r & 0x8) {
+ DEBUG(misc, 2, "%x & 0x8 (new tile)", r);
+ goto invalid_rail;
+ }
+
+ if (IsLevelCrossingTile(v->tile) && v->next == NULL) {
+ UnbarCrossing(v->tile);
+ MarkTileDirtyByTile(v->tile);
+ }
+
+ if (IsFrontEngine(v)) v->load_unload_time_rem = 0;
+
+ if (!(r&0x4)) {
+ v->tile = gp.new_tile;
+
+ if (GetTileRailType(gp.new_tile, chosen_track) != GetTileRailType(gp.old_tile, v->u.rail.track)) {
+ TrainPowerChanged(GetFirstVehicleInChain(v));
}
- /* Call the landscape function and tell it that the vehicle entered the tile */
- r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
- if (r & 0x8) {
- DEBUG(misc, 2, "%x & 0x8 (new tile)", r);
- goto invalid_rail;
- }
-
- if (IsLevelCrossingTile(v->tile) && v->next == NULL) {
- UnbarCrossing(v->tile);
- MarkTileDirtyByTile(v->tile);
- }
-
- if (IsFrontEngine(v)) v->load_unload_time_rem = 0;
-
- if (!(r&0x4)) {
- v->tile = gp.new_tile;
-
- if (GetTileRailType(gp.new_tile, chosen_track) != GetTileRailType(gp.old_tile, v->u.rail.track)) {
- TrainPowerChanged(GetFirstVehicleInChain(v));
- }
-
- v->u.rail.track = chosen_track;
- assert(v->u.rail.track);
- }
-
- if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir);
-
- /* Signals can only change when the first
- * (above) or the last vehicle moves. */
- if (v->next == NULL)
- TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
-
- if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
-
- v->direction = chosen_dir;
+ v->u.rail.track = chosen_track;
+ assert(v->u.rail.track);
}
- } else {
- uint32 res;
- /* in tunnel on on a bridge */
- GetNewVehiclePos(v, &gp);
-
- SetSpeedLimitOnBridge(v);
-
- if (!(IsTunnelTile(gp.new_tile) || IsBridgeTile(gp.new_tile)) || !((res = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)) & 0x4)) {
- v->x_pos = gp.x;
- v->y_pos = gp.y;
- VehiclePositionChanged(v);
- if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v);
- continue;
- }
-
- if (IsBridgeTile(gp.new_tile) && res & 0x4) {
- /* ok we have just left the bridge (because the status was "onbridge" before and we got
- a return value of 4 from VehicleEnterTile. we know the enterdir from the bridge ramp
- direction, and act as if we entered the tile normally (hence the goto) */
- enterdir = ReverseDiagDir(GetBridgeRampDirection(gp.new_tile));
- goto new_tile;
- }
+
+ if (IsFrontEngine(v)) TrainMovedChangeSignals(gp.new_tile, enterdir);
+
+ /* Signals can only change when the first
+ * (above) or the last vehicle moves. */
+ if (v->next == NULL)
+ TrainMovedChangeSignals(gp.old_tile, ReverseDiagDir(enterdir));
+
+ if (prev == NULL) AffectSpeedByDirChange(v, chosen_dir);
+
+ v->direction = chosen_dir;
}
/* update image of train, as well as delta XY */