diff -r 7cb2c58f4a7c -r abc40525bd50 train_cmd.c --- 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 */