train_cmd.c
changeset 2125 3098398bf7ff
parent 2115 71e12444631c
child 2135 48fb9f0322cb
equal deleted inserted replaced
2124:425fb490ae70 2125:3098398bf7ff
   664 	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Train); // updates the replace Train window
   664 	InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Train); // updates the replace Train window
   665 
   665 
   666 	return value;
   666 	return value;
   667 }
   667 }
   668 
   668 
   669 static bool IsTunnelTile(TileIndex tile)
       
   670 {
       
   671 	return IsTileType(tile, MP_TUNNELBRIDGE) && (_m[tile].m5 & 0x80) == 0;
       
   672 }
       
   673 
       
   674 
   669 
   675 /* Check if all the wagons of the given train are in a depot, returns the
   670 /* Check if all the wagons of the given train are in a depot, returns the
   676  * number of cars (including loco) then. If not, sets the error message to
   671  * number of cars (including loco) then. If not, sets the error message to
   677  * STR_881A_TRAINS_CAN_ONLY_BE_ALTERED and returns -1 */
   672  * STR_881A_TRAINS_CAN_ONLY_BE_ALTERED and returns -1 */
   678 int CheckTrainStoppedInDepot(const Vehicle *v)
   673 int CheckTrainStoppedInDepot(const Vehicle *v)
  1305 
  1300 
  1306 	if (v->u.rail.track != 0x40)
  1301 	if (v->u.rail.track != 0x40)
  1307 		return v->tile;
  1302 		return v->tile;
  1308 
  1303 
  1309 	for (tile = v->tile;; tile += delta) {
  1304 	for (tile = v->tile;; tile += delta) {
  1310 		if (IsTileType(tile, MP_TUNNELBRIDGE) &&
  1305 		if (IsTunnelTile(tile) && (_m[tile].m5 & 0x3) != (direction) && GetTileZ(tile) == v->z_pos)
  1311 				(_m[tile].m5 & 0xF3) != (direction) &&
       
  1312 				GetTileZ(tile) == v->z_pos)
       
  1313  			break;
  1306  			break;
  1314  	}
  1307  	}
  1315  	return tile;
  1308  	return tile;
  1316 
  1309 
  1317 };
  1310 };
  1567 	 * value is unused when new depot finding and NPF are both disabled
  1560 	 * value is unused when new depot finding and NPF are both disabled
  1568 	 */
  1561 	 */
  1569 	bool reverse;
  1562 	bool reverse;
  1570 } TrainFindDepotData;
  1563 } TrainFindDepotData;
  1571 
  1564 
  1572 static bool TrainFindDepotEnumProc(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length, byte *state)
  1565 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
  1573 {
  1566 {
  1574 	if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, tfdd->owner)) {
  1567 	if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, tfdd->owner)) {
  1575 		if ((_m[tile].m5 & ~0x3) == 0xC0) {
  1568 		if ((_m[tile].m5 & ~0x3) == 0xC0) {
  1576 			if (length < tfdd->best_length) {
  1569 			tfdd->best_length = length;
  1577 				tfdd->best_length = length;
  1570 			tfdd->tile = tile;
  1578 				tfdd->tile = tile;
       
  1579 			}
       
  1580 			return true;
  1571 			return true;
  1581 		}
  1572 		}
  1582 
  1573 	}
  1583 		// make sure the train doesn't run against a oneway signal
  1574 
  1584 		if ((_m[tile].m5 & 0xC0) == 0x40) {
  1575 	return false;
  1585 			if (!(_m[tile].m3 & SignalAlongTrackdir(track)) && _m[tile].m3 & SignalAgainstTrackdir(track))
       
  1586 				return true;
       
  1587 		}
       
  1588 	}
       
  1589 
       
  1590 	// stop  searching if we've found a destination that is closer already.
       
  1591 	return length >= tfdd->best_length;
       
  1592 }
  1576 }
  1593 
  1577 
  1594 // returns the tile of a depot to goto to. The given vehicle must not be
  1578 // returns the tile of a depot to goto to. The given vehicle must not be
  1595 // crashed!
  1579 // crashed!
  1596 static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
  1580 static TrainFindDepotData FindClosestTrainDepot(Vehicle *v)
  1630 			* is removed. */
  1614 			* is removed. */
  1631 			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  1615 			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  1632 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE))
  1616 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE))
  1633 				tfdd.reverse = true;
  1617 				tfdd.reverse = true;
  1634 		}
  1618 		}
  1635 	} else if (!_patches.new_depot_finding) {
       
  1636 		// search in all directions
       
  1637 		for(i=0; i!=4; i++)
       
  1638 			NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
       
  1639 	} else {
  1619 	} else {
  1640 		// search in the forward direction first.
  1620 		// search in the forward direction first.
  1641 		i = v->direction >> 1;
  1621 		i = v->direction >> 1;
  1642 		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
  1622 		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
  1643 		NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
  1623 		NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1644 		if (tfdd.best_length == (uint)-1){
  1624 		if (tfdd.best_length == (uint)-1){
  1645 			tfdd.reverse = true;
  1625 			tfdd.reverse = true;
  1646 			// search in backwards direction
  1626 			// search in backwards direction
  1647 			i = (v->direction^4) >> 1;
  1627 			i = (v->direction^4) >> 1;
  1648 			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
  1628 			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) { i = (i - 1) & 3; }
  1649 			NewTrainPathfind(tile, i, (TPFEnumProc*)TrainFindDepotEnumProc, &tfdd, NULL);
  1629 			NewTrainPathfind(tile, 0, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1650 		}
  1630 		}
  1651 	}
  1631 	}
  1652 
  1632 
  1653 	return tfdd;
  1633 	return tfdd;
  1654 }
  1634 }
  1885 	uint best_bird_dist;
  1865 	uint best_bird_dist;
  1886 	uint best_track_dist;
  1866 	uint best_track_dist;
  1887 	byte best_track;
  1867 	byte best_track;
  1888 } TrainTrackFollowerData;
  1868 } TrainTrackFollowerData;
  1889 
  1869 
  1890 static bool TrainTrackFollower(TileIndex tile, TrainTrackFollowerData *ttfd, int track, uint length, byte *state)
  1870 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, int track, uint length)
  1891 {
  1871 {
  1892 	// heading for nowhere?
  1872 	// heading for nowhere?
  1893 	if (ttfd->dest_coords == 0)
  1873 	if (ttfd->dest_coords == 0)
  1894 		return false;
  1874 		return false;
  1895 
  1875 
  1898 		(IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_m[tile].m5, 0, 8) && _m[tile].m2 == ttfd->station_index)) {
  1878 		(IsTileType(tile, MP_STATION) && IS_BYTE_INSIDE(_m[tile].m5, 0, 8) && _m[tile].m2 == ttfd->station_index)) {
  1899 		/* We do not check for dest_coords if we have a station_index,
  1879 		/* We do not check for dest_coords if we have a station_index,
  1900 		 * because in that case the dest_coords are just an
  1880 		 * because in that case the dest_coords are just an
  1901 		 * approximation of where the station is */
  1881 		 * approximation of where the station is */
  1902 		// found station
  1882 		// found station
  1903 		ttfd->best_bird_dist = 0;
  1883 		ttfd->best_track = track;
  1904 		if (length < ttfd->best_track_dist) {
       
  1905 			ttfd->best_track_dist = length;
       
  1906 			ttfd->best_track = state[1];
       
  1907 		}
       
  1908 		return true;
  1884 		return true;
  1909 	} else {
  1885 	} else {
  1910 		uint dist;
  1886 		uint dist;
  1911 
  1887 
  1912 		// we've actually found the destination already. no point searching in directions longer than this.
  1888 		// didn't find station, keep track of the best path so far.
  1913 		if (ttfd->best_track_dist != (uint)-1)
       
  1914 			return length >= ttfd->best_track_dist;
       
  1915 
       
  1916 		// didn't find station
       
  1917 		dist = DistanceManhattan(tile, ttfd->dest_coords);
  1889 		dist = DistanceManhattan(tile, ttfd->dest_coords);
  1918 		if (dist < ttfd->best_bird_dist) {
  1890 		if (dist < ttfd->best_bird_dist) {
  1919 			ttfd->best_bird_dist = dist;
  1891 			ttfd->best_bird_dist = dist;
  1920 			ttfd->best_track = state[1];
  1892 			ttfd->best_track = track;
  1921 		}
  1893 		}
  1922 		return false;
  1894 		return false;
  1923 	}
  1895 	}
  1924 }
  1896 }
  1925 
  1897 
  2044 		/* New train pathfinding */
  2016 		/* New train pathfinding */
  2045 		fd.best_bird_dist = (uint)-1;
  2017 		fd.best_bird_dist = (uint)-1;
  2046 		fd.best_track_dist = (uint)-1;
  2018 		fd.best_track_dist = (uint)-1;
  2047 		fd.best_track = 0xFF;
  2019 		fd.best_track = 0xFF;
  2048 
  2020 
  2049 		NewTrainPathfind(tile - TileOffsByDir(enterdir), enterdir, (TPFEnumProc*)TrainTrackFollower, &fd, NULL);
  2021 		NewTrainPathfind(tile - TileOffsByDir(enterdir), v->dest_tile,
       
  2022 			enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2050 
  2023 
  2051 		if (fd.best_track == 0xff) {
  2024 		if (fd.best_track == 0xff) {
  2052 			// blaha
  2025 			// blaha
  2053 			best_track = FIND_FIRST_BIT(trackdirbits);
  2026 			best_track = FIND_FIRST_BIT(trackdirbits);
  2054 		} else {
  2027 		} else {
  2116 	} else {
  2089 	} else {
  2117 		while(true) {
  2090 		while(true) {
  2118 			fd.best_bird_dist = (uint)-1;
  2091 			fd.best_bird_dist = (uint)-1;
  2119 			fd.best_track_dist = (uint)-1;
  2092 			fd.best_track_dist = (uint)-1;
  2120 
  2093 
  2121 			NewTrainPathfind(v->tile, reverse ^ i, (TPFEnumProc*)TrainTrackFollower, &fd, NULL);
  2094 			NewTrainPathfind(v->tile, v->dest_tile, reverse ^ i, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2122 
  2095 
  2123 			if (best_track != -1) {
  2096 			if (best_track != -1) {
  2124 				if (best_bird_dist != 0) {
  2097 				if (best_bird_dist != 0) {
  2125 					if (fd.best_bird_dist != 0) {
  2098 					if (fd.best_bird_dist != 0) {
  2126 						/* neither reached the destination, pick the one with the smallest bird dist */
  2099 						/* neither reached the destination, pick the one with the smallest bird dist */
  2859 			}
  2832 			}
  2860 		} else {
  2833 		} else {
  2861 			/* in tunnel */
  2834 			/* in tunnel */
  2862 			GetNewVehiclePos(v, &gp);
  2835 			GetNewVehiclePos(v, &gp);
  2863 
  2836 
  2864 			if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) &&
  2837 			// Check if to exit the tunnel...
  2865 					!(_m[gp.new_tile].m5 & 0xF0)) {
  2838 			if (!IsTunnelTile(gp.new_tile) ||
  2866 				r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
  2839 					!(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y)&0x4) ) {
  2867 				if (r & 0x4) goto common;
  2840 				v->x_pos = gp.x;
  2868 			}
  2841 				v->y_pos = gp.y;
  2869 
  2842 				VehiclePositionChanged(v);
  2870 			v->x_pos = gp.x;
  2843 				continue;
  2871 			v->y_pos = gp.y;
  2844 			}
  2872 			VehiclePositionChanged(v);
  2845 		}
  2873 			continue;
       
  2874 		}
       
  2875 common:;
       
  2876 
  2846 
  2877 		/* update image of train, as well as delta XY */
  2847 		/* update image of train, as well as delta XY */
  2878 		newdir = GetNewVehicleDirection(v, gp.x, gp.y);
  2848 		newdir = GetNewVehicleDirection(v, gp.x, gp.y);
  2879 		UpdateTrainDeltaXY(v, newdir);
  2849 		UpdateTrainDeltaXY(v, newdir);
  2880 		v->cur_image = GetTrainImage(v, newdir);
  2850 		v->cur_image = GetTrainImage(v, newdir);
  3123 		return true;
  3093 		return true;
  3124 
  3094 
  3125 	tile = v->tile;
  3095 	tile = v->tile;
  3126 
  3096 
  3127 	// tunnel entrance?
  3097 	// tunnel entrance?
  3128 	if (IsTileType(tile, MP_TUNNELBRIDGE) &&
  3098 	if (IsTunnelTile(tile) && (byte)((_m[tile].m5 & 3)*2+1) == v->direction)
  3129 			(_m[tile].m5 & 0xF0) == 0 && (byte)((_m[tile].m5 & 3)*2+1) == v->direction)
       
  3130 				return true;
  3099 				return true;
  3131 
  3100 
  3132 	// depot?
  3101 	// depot?
  3133 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3102 	/* XXX -- When enabled, this makes it possible to crash trains of others
  3134 	     (by building a depot right against a station) */
  3103 	     (by building a depot right against a station) */