src/train_cmd.cpp
changeset 10083 eee4e42aa15b
parent 9992 5e68b6f327fb
child 10102 dcd66d9d53af
equal deleted inserted replaced
10082:44931aeaa000 10083:eee4e42aa15b
  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)) {