1692 |
1692 |
1693 |
1693 |
1694 /** |
1694 /** |
1695 * Finds a vehicle approaching rail-road crossing |
1695 * Finds a vehicle approaching rail-road crossing |
1696 * @param tile tile to test |
1696 * @param tile tile to test |
1697 * @return pointer to vehicle approaching the crossing |
1697 * @return true if a vehicle is approaching the crossing |
1698 * @pre tile is a rail-road crossing |
1698 * @pre tile is a rail-road crossing |
1699 */ |
1699 */ |
1700 static Vehicle *TrainApproachingCrossing(TileIndex tile) |
1700 static bool TrainApproachingCrossing(TileIndex tile) |
1701 { |
1701 { |
1702 assert(IsLevelCrossingTile(tile)); |
1702 assert(IsLevelCrossingTile(tile)); |
1703 |
1703 |
1704 DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile)); |
1704 DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile)); |
1705 TileIndex tile_from = tile + TileOffsByDiagDir(dir); |
1705 TileIndex tile_from = tile + TileOffsByDiagDir(dir); |
1706 |
1706 |
1707 Vehicle *v = VehicleFromPos(tile_from, &tile, &TrainApproachingCrossingEnum); |
1707 if (HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum)) return true; |
1708 |
|
1709 if (v != NULL) return v; |
|
1710 |
1708 |
1711 dir = ReverseDiagDir(dir); |
1709 dir = ReverseDiagDir(dir); |
1712 tile_from = tile + TileOffsByDiagDir(dir); |
1710 tile_from = tile + TileOffsByDiagDir(dir); |
1713 |
1711 |
1714 return VehicleFromPos(tile_from, &tile, &TrainApproachingCrossingEnum); |
1712 return HasVehicleOnPos(tile_from, &tile, &TrainApproachingCrossingEnum); |
1715 } |
1713 } |
1716 |
1714 |
1717 |
1715 |
1718 /** |
1716 /** |
1719 * Sets correct crossing state |
1717 * Sets correct crossing state |
1724 void UpdateLevelCrossing(TileIndex tile, bool sound) |
1722 void UpdateLevelCrossing(TileIndex tile, bool sound) |
1725 { |
1723 { |
1726 assert(IsLevelCrossingTile(tile)); |
1724 assert(IsLevelCrossingTile(tile)); |
1727 |
1725 |
1728 /* train on crossing || train approaching crossing || reserved */ |
1726 /* train on crossing || train approaching crossing || reserved */ |
1729 bool new_state = VehicleFromPos(tile, NULL, &TrainOnTileEnum) != NULL || TrainApproachingCrossing(tile) || GetCrossingReservation(tile); |
1727 bool new_state = HasVehicleOnPos(tile, NULL, &TrainOnTileEnum) || TrainApproachingCrossing(tile) || GetCrossingReservation(tile); |
1730 |
1728 |
1731 if (new_state != IsCrossingBarred(tile)) { |
1729 if (new_state != IsCrossingBarred(tile)) { |
1732 if (new_state && sound) { |
1730 if (new_state && sound) { |
1733 SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile); |
1731 SndPlayTileFx(SND_0E_LEVEL_CROSSING, tile); |
1734 } |
1732 } |
3026 if (mark_as_stuck) MarkTrainAsStuck(v); |
3024 if (mark_as_stuck) MarkTrainAsStuck(v); |
3027 return false; |
3025 return false; |
3028 } |
3026 } |
3029 } |
3027 } |
3030 |
3028 |
3031 Vehicle *other_train = NULL; |
3029 bool other_train = false; |
3032 PBSTileInfo origin = FollowTrainReservation(v, &other_train); |
3030 PBSTileInfo origin = FollowTrainReservation(v, &other_train); |
3033 /* If we have a reserved path and the path ends at a safe tile, we are finished already. */ |
3031 /* If we have a reserved path and the path ends at a safe tile, we are finished already. */ |
3034 if (origin.okay && (v->tile != origin.tile || first_tile_okay)) { |
3032 if (origin.okay && (v->tile != origin.tile || first_tile_okay)) { |
3035 /* Can't be stuck then. */ |
3033 /* Can't be stuck then. */ |
3036 if (HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
3034 if (HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
3039 } |
3037 } |
3040 /* The path we are driving on is alread blocked by some other train. |
3038 /* The path we are driving on is alread blocked by some other train. |
3041 * This can only happen when tracks and signals are changed. A crash |
3039 * This can only happen when tracks and signals are changed. A crash |
3042 * is probably imminent, don't do any further reservation because |
3040 * is probably imminent, don't do any further reservation because |
3043 * it might cause stale reservations. */ |
3041 * it might cause stale reservations. */ |
3044 if (other_train != NULL && v->tile != origin.tile) { |
3042 if (other_train && v->tile != origin.tile) { |
3045 if (mark_as_stuck) MarkTrainAsStuck(v); |
3043 if (mark_as_stuck) MarkTrainAsStuck(v); |
3046 return false; |
3044 return false; |
3047 } |
3045 } |
3048 |
3046 |
3049 /* If we are in a depot, tentativly reserve the depot. */ |
3047 /* If we are in a depot, tentativly reserve the depot. */ |
3516 tcc.v = v; |
3514 tcc.v = v; |
3517 tcc.num = 0; |
3515 tcc.num = 0; |
3518 |
3516 |
3519 /* find colliding vehicles */ |
3517 /* find colliding vehicles */ |
3520 if (v->u.rail.track == TRACK_BIT_WORMHOLE) { |
3518 if (v->u.rail.track == TRACK_BIT_WORMHOLE) { |
3521 VehicleFromPos(v->tile, &tcc, FindTrainCollideEnum); |
3519 FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum); |
3522 VehicleFromPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum); |
3520 FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum); |
3523 } else { |
3521 } else { |
3524 VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum); |
3522 FindVehicleOnPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum); |
3525 } |
3523 } |
3526 |
3524 |
3527 /* any dead -> no crash */ |
3525 /* any dead -> no crash */ |
3528 if (tcc.num == 0) return; |
3526 if (tcc.num == 0) return; |
3529 |
3527 |
3650 TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir); |
3648 TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir); |
3651 |
3649 |
3652 exitdir = ReverseDiagDir(exitdir); |
3650 exitdir = ReverseDiagDir(exitdir); |
3653 |
3651 |
3654 /* check if a train is waiting on the other side */ |
3652 /* check if a train is waiting on the other side */ |
3655 if (VehicleFromPos(o_tile, &exitdir, &CheckVehicleAtSignal) == NULL) return; |
3653 if (!HasVehicleOnPos(o_tile, &exitdir, &CheckVehicleAtSignal)) return; |
3656 } |
3654 } |
3657 } |
3655 } |
3658 |
3656 |
3659 /* If we would reverse but are currently in a PBS block and |
3657 /* If we would reverse but are currently in a PBS block and |
3660 * reversing of stuck trains is disabled, don't reverse. */ |
3658 * reversing of stuck trains is disabled, don't reverse. */ |
3817 v->subspeed = 0; |
3815 v->subspeed = 0; |
3818 ReverseTrainDirection(v); |
3816 ReverseTrainDirection(v); |
3819 } |
3817 } |
3820 |
3818 |
3821 /** Collect trackbits of all crashed train vehicles on a tile |
3819 /** Collect trackbits of all crashed train vehicles on a tile |
3822 * @param v Vehicle passed from VehicleFromPos() |
3820 * @param v Vehicle passed from Find/HasVehicleOnPos() |
3823 * @param data trackdirbits for the result |
3821 * @param data trackdirbits for the result |
3824 * @return NULL to not abort VehicleFromPos() |
3822 * @return NULL to iterate over all vehicles on the tile. |
3825 */ |
3823 */ |
3826 static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data) |
3824 static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data) |
3827 { |
3825 { |
3828 TrackBits *trackbits = (TrackBits *)data; |
3826 TrackBits *trackbits = (TrackBits *)data; |
3829 |
3827 |
3892 if (HasReservedTracks(tile, trackbits)) { |
3890 if (HasReservedTracks(tile, trackbits)) { |
3893 UnreserveRailTrack(tile, track); |
3891 UnreserveRailTrack(tile, track); |
3894 |
3892 |
3895 /* If there are still crashed vehicles on the tile, give the track reservation to them */ |
3893 /* If there are still crashed vehicles on the tile, give the track reservation to them */ |
3896 TrackBits remaining_trackbits = TRACK_BIT_NONE; |
3894 TrackBits remaining_trackbits = TRACK_BIT_NONE; |
3897 VehicleFromPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum); |
3895 FindVehicleOnPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum); |
3898 |
3896 |
3899 /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */ |
3897 /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */ |
3900 assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1); |
3898 assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1); |
3901 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) { |
3899 for (Track t = TRACK_BEGIN; t < TRACK_END; t++) { |
3902 if (HasBit(remaining_trackbits, t)) { |
3900 if (HasBit(remaining_trackbits, t)) { |