src/train_cmd.cpp
branchNewGRF_ports
changeset 6878 7d1ff2f621c7
parent 6877 889301acc299
child 10184 fcf5fb2548eb
equal deleted inserted replaced
6877:889301acc299 6878:7d1ff2f621c7
   733 			v->tile = tile;
   733 			v->tile = tile;
   734 			v->owner = _current_player;
   734 			v->owner = _current_player;
   735 			v->x_pos = x;
   735 			v->x_pos = x;
   736 			v->y_pos = y;
   736 			v->y_pos = y;
   737 			v->z_pos = GetSlopeZ(x, y);
   737 			v->z_pos = GetSlopeZ(x, y);
       
   738 			v->running_ticks = 0;
   738 			v->u.rail.track = TRACK_BIT_DEPOT;
   739 			v->u.rail.track = TRACK_BIT_DEPOT;
   739 			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   740 			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   740 			v->spritenum = rvi->image_index;
   741 			v->spritenum = rvi->image_index;
   741 			v->cargo_type = rvi->cargo_type;
   742 			v->cargo_type = rvi->cargo_type;
   742 			v->cargo_subtype = 0;
   743 			v->cargo_subtype = 0;
   991 
   992 
   992 	/* when moving all wagons, we can't have the same src_head and dst_head */
   993 	/* when moving all wagons, we can't have the same src_head and dst_head */
   993 	if (HasBit(p2, 0) && src_head == dst_head) return CommandCost();
   994 	if (HasBit(p2, 0) && src_head == dst_head) return CommandCost();
   994 
   995 
   995 	{
   996 	{
   996 		int max_len = _patches.mammoth_trains ? 100 : 9;
   997 		int max_len = _patches.mammoth_trains ? 100 : 10;
   997 
   998 
   998 		/* check if all vehicles in the source train are stopped inside a depot. */
   999 		/* check if all vehicles in the source train are stopped inside a depot. */
   999 		int src_len = CheckTrainStoppedInDepot(src_head);
  1000 		int src_len = CheckTrainStoppedInDepot(src_head);
  1000 		if (src_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1001 		if (src_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1001 
  1002 
  1442 
  1443 
  1443 				/* (6.) Borked AI. If it sells an engine it expects all wagons lined
  1444 				/* (6.) Borked AI. If it sells an engine it expects all wagons lined
  1444 				 * up on a new line to be added to the newly built loco. Replace it is.
  1445 				 * up on a new line to be added to the newly built loco. Replace it is.
  1445 				 * Totally braindead cause building a new engine adds all loco-less
  1446 				 * Totally braindead cause building a new engine adds all loco-less
  1446 				 * engines to its train anyways */
  1447 				 * engines to its train anyways */
  1447 				if (p2 == 2 && HasBit(ori_subtype, Train_Front)) {
  1448 				if (p2 == 2 && HasBit(ori_subtype, TS_FRONT)) {
  1448 					Vehicle *tmp;
  1449 					Vehicle *tmp;
  1449 					for (v = first; v != NULL; v = tmp) {
  1450 					for (v = first; v != NULL; v = tmp) {
  1450 						tmp = GetNextVehicle(v);
  1451 						tmp = GetNextVehicle(v);
  1451 						DoCommand(v->tile, v->index | INVALID_VEHICLE << 16, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
  1452 						DoCommand(v->tile, v->index | INVALID_VEHICLE << 16, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
  1452 					}
  1453 					}
  1541 	BeginVehicleMove(v);
  1542 	BeginVehicleMove(v);
  1542 	VehiclePositionChanged(v);
  1543 	VehiclePositionChanged(v);
  1543 	EndVehicleMove(v);
  1544 	EndVehicleMove(v);
  1544 }
  1545 }
  1545 
  1546 
  1546 static void SetLastSpeed(Vehicle* v, int spd)
  1547 static inline void SetLastSpeed(Vehicle* v, int spd)
  1547 {
  1548 {
  1548 	int old = v->u.rail.last_speed;
  1549 	int old = v->u.rail.last_speed;
  1549 	if (spd != old) {
  1550 	if (spd != old) {
  1550 		v->u.rail.last_speed = spd;
  1551 		v->u.rail.last_speed = spd;
  1551 		if (_patches.vehicle_speed || (old == 0) != (spd == 0))
  1552 		if (_patches.vehicle_speed || (old == 0) != (spd == 0))
  1664  */
  1665  */
  1665 static Vehicle *TrainApproachingCrossing(TileIndex tile)
  1666 static Vehicle *TrainApproachingCrossing(TileIndex tile)
  1666 {
  1667 {
  1667 	assert(IsLevelCrossingTile(tile));
  1668 	assert(IsLevelCrossingTile(tile));
  1668 
  1669 
  1669 	DiagDirection dir = AxisToDiagDir(OtherAxis(GetCrossingRoadAxis(tile)));
  1670 	DiagDirection dir = AxisToDiagDir(GetCrossingRailAxis(tile));
  1670 	TileIndex tile_from = tile + TileOffsByDiagDir(dir);
  1671 	TileIndex tile_from = tile + TileOffsByDiagDir(dir);
  1671 
  1672 
  1672 	Vehicle *v = (Vehicle *)VehicleFromPos(tile_from, &tile, &TrainApproachingCrossingEnum);
  1673 	Vehicle *v = (Vehicle *)VehicleFromPos(tile_from, &tile, &TrainApproachingCrossingEnum);
  1673 
  1674 
  1674 	if (v != NULL) return v;
  1675 	if (v != NULL) return v;
  1783 
  1784 
  1784 	if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
  1785 	if (IsTileDepotType(v->tile, TRANSPORT_RAIL)) {
  1785 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
  1786 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
  1786 	}
  1787 	}
  1787 
  1788 
       
  1789 	/* set reversed flag on all parts */
       
  1790 	for (Vehicle *u = v; u != NULL; u = u->Next()) ToggleBit(u->u.rail.flags, VRF_TOGGLE_REVERSE);
       
  1791 
       
  1792 	ClrBit(v->u.rail.flags, VRF_REVERSING);
       
  1793 
       
  1794 	/* recalculate cached data */
       
  1795 	TrainConsistChanged(v);
       
  1796 
  1788 	/* update all images */
  1797 	/* update all images */
  1789 	for (Vehicle *u = v; u != NULL; u = u->Next()) { u->cur_image = u->GetImage(u->direction); }
  1798 	for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction);
  1790 
       
  1791 	ClrBit(v->u.rail.flags, VRF_REVERSING);
       
  1792 
  1799 
  1793 	/* update crossing we were approaching */
  1800 	/* update crossing we were approaching */
  1794 	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
  1801 	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
  1795 
  1802 
  1796 	/* maybe we are approaching crossing now, after reversal */
  1803 	/* maybe we are approaching crossing now, after reversal */
  1998 {
  2005 {
  1999 	assert(!(v->vehstatus & VS_CRASHED));
  2006 	assert(!(v->vehstatus & VS_CRASHED));
  2000 
  2007 
  2001 	TrainFindDepotData tfdd;
  2008 	TrainFindDepotData tfdd;
  2002 	tfdd.owner = v->owner;
  2009 	tfdd.owner = v->owner;
  2003 	tfdd.best_length = (uint)-1;
  2010 	tfdd.best_length = UINT_MAX;
  2004 	tfdd.reverse = false;
  2011 	tfdd.reverse = false;
  2005 
  2012 
  2006 	TileIndex tile = v->tile;
  2013 	TileIndex tile = v->tile;
  2007 	if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
  2014 	if (IsTileDepotType(tile, TRANSPORT_RAIL)) {
  2008 		tfdd.tile = tile;
  2015 		tfdd.tile = tile;
  2009 		tfdd.best_length = 0;
  2016 		tfdd.best_length = 0;
  2010 		return tfdd;
  2017 		return tfdd;
  2011 	}
  2018 	}
  2012 
  2019 
  2013 	if (_patches.yapf.rail_use_yapf) {
  2020 	switch (_patches.pathfinder_for_trains) {
  2014 		bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  2021 		case VPF_YAPF: { /* YAPF */
  2015 		tfdd.best_length = found ? max_distance / 2 : -1; // some fake distance or NOT_FOUND
  2022 			bool found = YapfFindNearestRailDepotTwoWay(v, max_distance, NPF_INFINITE_PENALTY, &tfdd.tile, &tfdd.reverse);
  2016 	} else if (_patches.new_pathfinding_all) {
  2023 			tfdd.best_length = found ? max_distance / 2 : UINT_MAX; // some fake distance or NOT_FOUND
  2017 		Vehicle* last = GetLastVehicleInChain(v);
  2024 		} break;
  2018 		Trackdir trackdir = GetVehicleTrackdir(v);
  2025 
  2019 		Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
  2026 		case VPF_NPF: { /* NPF */
  2020 
  2027 			Vehicle* last = GetLastVehicleInChain(v);
  2021 		assert(trackdir != INVALID_TRACKDIR);
  2028 			Trackdir trackdir = GetVehicleTrackdir(v);
  2022 		NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, last->tile, trackdir_rev, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
  2029 			Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
  2023 		if (ftd.best_bird_dist == 0) {
  2030 
  2024 			/* Found target */
  2031 			assert(trackdir != INVALID_TRACKDIR);
  2025 			tfdd.tile = ftd.node.tile;
  2032 			NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
  2026 			/* Our caller expects a number of tiles, so we just approximate that
  2033 			if (ftd.best_bird_dist == 0) {
  2027 			 * number by this. It might not be completely what we want, but it will
  2034 				/* Found target */
  2028 			 * work for now :-) We can possibly change this when the old pathfinder
  2035 				tfdd.tile = ftd.node.tile;
  2029 			 * is removed. */
  2036 				/* Our caller expects a number of tiles, so we just approximate that
  2030 			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  2037 				* number by this. It might not be completely what we want, but it will
  2031 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
  2038 				* work for now :-) We can possibly change this when the old pathfinder
  2032 		}
  2039 				* is removed. */
  2033 	} else {
  2040 				tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  2034 		/* search in the forward direction first. */
  2041 				if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
  2035 		DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
  2042 			}
  2036 		NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  2043 		} break;
  2037 		if (tfdd.best_length == (uint)-1){
  2044 
  2038 			tfdd.reverse = true;
  2045 		default:
  2039 			/* search in backwards direction */
  2046 		case VPF_NTP: { /* NTP */
  2040 			i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
  2047 			/* search in the forward direction first. */
       
  2048 			DiagDirection i = TrainExitDir(v->direction, v->u.rail.track);
  2041 			NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  2049 			NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  2042 		}
  2050 			if (tfdd.best_length == UINT_MAX){
       
  2051 				tfdd.reverse = true;
       
  2052 				/* search in backwards direction */
       
  2053 				i = TrainExitDir(ReverseDir(v->direction), v->u.rail.track);
       
  2054 				NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
       
  2055 			}
       
  2056 		} break;
  2043 	}
  2057 	}
  2044 
  2058 
  2045 	return tfdd;
  2059 	return tfdd;
  2046 }
  2060 }
  2047 
  2061 
  2200 	} while ((v = v->Next()) != NULL);
  2214 	} while ((v = v->Next()) != NULL);
  2201 
  2215 
  2202 	if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT);
  2216 	if (sound) PlayVehicleSound(u, VSE_TRAIN_EFFECT);
  2203 }
  2217 }
  2204 
  2218 
  2205 static void TrainPlayLeaveStationSound(const Vehicle* v)
  2219 void Train::PlayLeaveStationSound() const
  2206 {
  2220 {
  2207 	static const SoundFx sfx[] = {
  2221 	static const SoundFx sfx[] = {
  2208 		SND_04_TRAIN,
  2222 		SND_04_TRAIN,
  2209 		SND_0A_TRAIN_HORN,
  2223 		SND_0A_TRAIN_HORN,
  2210 		SND_0A_TRAIN_HORN,
  2224 		SND_0A_TRAIN_HORN,
  2211 		SND_47_MAGLEV_2,
  2225 		SND_47_MAGLEV_2,
  2212 		SND_41_MAGLEV
  2226 		SND_41_MAGLEV
  2213 	};
  2227 	};
  2214 
  2228 
  2215 	if (PlayVehicleSound(v, VSE_START)) return;
  2229 	if (PlayVehicleSound(this, VSE_START)) return;
  2216 
  2230 
  2217 	EngineID engtype = v->engine_type;
  2231 	EngineID engtype = this->engine_type;
  2218 	SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], v);
  2232 	SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
  2219 }
       
  2220 
       
  2221 void Train::PlayLeaveStationSound() const
       
  2222 {
       
  2223 	TrainPlayLeaveStationSound(this);
       
  2224 }
  2233 }
  2225 
  2234 
  2226 static bool CheckTrainStayInDepot(Vehicle *v)
  2235 static bool CheckTrainStayInDepot(Vehicle *v)
  2227 {
  2236 {
  2228 	/* bail out if not all wagons are in the same depot or not in a depot at all */
  2237 	/* bail out if not all wagons are in the same depot or not in a depot at all */
  2251 		}
  2260 		}
  2252 	}
  2261 	}
  2253 
  2262 
  2254 	VehicleServiceInDepot(v);
  2263 	VehicleServiceInDepot(v);
  2255 	InvalidateWindowClasses(WC_TRAINS_LIST);
  2264 	InvalidateWindowClasses(WC_TRAINS_LIST);
  2256 	TrainPlayLeaveStationSound(v);
  2265 	v->PlayLeaveStationSound();
  2257 
  2266 
  2258 	v->u.rail.track = TRACK_BIT_X;
  2267 	v->u.rail.track = TRACK_BIT_X;
  2259 	if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y;
  2268 	if (v->direction & 2) v->u.rail.track = TRACK_BIT_Y;
  2260 
  2269 
  2261 	v->vehstatus &= ~VS_HIDDEN;
  2270 	v->vehstatus &= ~VS_HIDDEN;
  2361 	assert((tracks & ~TRACK_BIT_MASK) == 0);
  2370 	assert((tracks & ~TRACK_BIT_MASK) == 0);
  2362 
  2371 
  2363 	/* quick return in case only one possible track is available */
  2372 	/* quick return in case only one possible track is available */
  2364 	if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
  2373 	if (KillFirstBit(tracks) == TRACK_BIT_NONE) return FindFirstTrack(tracks);
  2365 
  2374 
  2366 	if (_patches.yapf.rail_use_yapf) {
  2375 	switch (_patches.pathfinder_for_trains) {
  2367 		Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
  2376 		case VPF_YAPF: { /* YAPF */
  2368 		if (trackdir != INVALID_TRACKDIR) {
  2377 			Trackdir trackdir = YapfChooseRailTrack(v, tile, enterdir, tracks, &path_not_found);
  2369 			best_track = TrackdirToTrack(trackdir);
  2378 			if (trackdir != INVALID_TRACKDIR) {
  2370 		} else {
  2379 				best_track = TrackdirToTrack(trackdir);
  2371 			best_track = FindFirstTrack(tracks);
  2380 			} else {
  2372 		}
  2381 				best_track = FindFirstTrack(tracks);
  2373 	} else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
  2382 			}
  2374 		void* perf = NpfBeginInterval();
  2383 		} break;
  2375 
  2384 
  2376 		NPFFindStationOrTileData fstd;
  2385 		case VPF_NPF: { /* NPF */
  2377 		NPFFillWithOrderData(&fstd, v);
  2386 			void *perf = NpfBeginInterval();
  2378 		/* The enterdir for the new tile, is the exitdir for the old tile */
  2387 
  2379 		Trackdir trackdir = GetVehicleTrackdir(v);
  2388 			NPFFindStationOrTileData fstd;
  2380 		assert(trackdir != 0xff);
  2389 			NPFFillWithOrderData(&fstd, v);
  2381 
  2390 			/* The enterdir for the new tile, is the exitdir for the old tile */
  2382 		NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
  2391 			Trackdir trackdir = GetVehicleTrackdir(v);
  2383 
  2392 			assert(trackdir != INVALID_TRACKDIR);
  2384 		if (ftd.best_trackdir == 0xff) {
  2393 
  2385 			/* We are already at our target. Just do something
  2394 			NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, true, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
  2386 			 * @todo maybe display error?
  2395 
  2387 			 * @todo: go straight ahead if possible? */
  2396 			if (ftd.best_trackdir == INVALID_TRACKDIR) {
  2388 			best_track = FindFirstTrack(tracks);
  2397 				/* We are already at our target. Just do something
  2389 		} else {
  2398 				 * @todo maybe display error?
  2390 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  2399 				 * @todo: go straight ahead if possible? */
  2391 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  2400 				best_track = FindFirstTrack(tracks);
  2392 			we did not find our target, but ftd.best_trackdir contains the direction leading
  2401 			} else {
  2393 			to the tile closest to our target. */
  2402 				/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  2394 			if (ftd.best_bird_dist != 0) path_not_found = true;
  2403 				 * the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  2395 			/* Discard enterdir information, making it a normal track */
  2404 				 * we did not find our target, but ftd.best_trackdir contains the direction leading
  2396 			best_track = TrackdirToTrack(ftd.best_trackdir);
  2405 				 * to the tile closest to our target. */
  2397 		}
  2406 				if (ftd.best_bird_dist != 0) path_not_found = true;
  2398 
  2407 				/* Discard enterdir information, making it a normal track */
  2399 		int time = NpfEndInterval(perf);
  2408 				best_track = TrackdirToTrack(ftd.best_trackdir);
  2400 		DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
  2409 			}
  2401 	} else {
  2410 
  2402 		void* perf = NpfBeginInterval();
  2411 			int time = NpfEndInterval(perf);
  2403 
  2412 			DEBUG(yapf, 4, "[NPFT] %d us - %d rounds - %d open - %d closed -- ", time, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
  2404 		TrainTrackFollowerData fd;
  2413 		} break;
  2405 		FillWithStationData(&fd, v);
  2414 
  2406 
  2415 		default:
  2407 		/* New train pathfinding */
  2416 		case VPF_NTP: { /* NTP */
  2408 		fd.best_bird_dist = (uint)-1;
  2417 			void *perf = NpfBeginInterval();
  2409 		fd.best_track_dist = (uint)-1;
  2418 
  2410 		fd.best_track = INVALID_TRACKDIR;
  2419 			TrainTrackFollowerData fd;
  2411 
  2420 			FillWithStationData(&fd, v);
  2412 		NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
  2421 
  2413 			v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2422 			/* New train pathfinding */
  2414 
  2423 			fd.best_bird_dist = UINT_MAX;
  2415 		/* check whether the path was found or only 'guessed' */
  2424 			fd.best_track_dist = UINT_MAX;
  2416 		if (fd.best_bird_dist != 0) path_not_found = true;
  2425 			fd.best_track = INVALID_TRACKDIR;
  2417 
  2426 
  2418 		if (fd.best_track == 0xff) {
  2427 			NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
  2419 			/* blaha */
  2428 				v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2420 			best_track = FindFirstTrack(tracks);
  2429 
  2421 		} else {
  2430 			/* check whether the path was found or only 'guessed' */
  2422 			best_track = TrackdirToTrack(fd.best_track);
  2431 			if (fd.best_bird_dist != 0) path_not_found = true;
  2423 		}
  2432 
  2424 
  2433 			if (fd.best_track == INVALID_TRACKDIR) {
  2425 		int time = NpfEndInterval(perf);
  2434 				/* blaha */
  2426 		DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
  2435 				best_track = FindFirstTrack(tracks);
  2427 	}
  2436 			} else {
       
  2437 				best_track = TrackdirToTrack(fd.best_track);
       
  2438 			}
       
  2439 
       
  2440 			int time = NpfEndInterval(perf);
       
  2441 			DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
       
  2442 		} break;
       
  2443 	}
       
  2444 
  2428 	/* handle "path not found" state */
  2445 	/* handle "path not found" state */
  2429 	if (path_not_found) {
  2446 	if (path_not_found) {
  2430 		/* PF didn't find the route */
  2447 		/* PF didn't find the route */
  2431 		if (!HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2448 		if (!HasBit(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2432 			/* it is first time the problem occurred, set the "path not found" flag */
  2449 			/* it is first time the problem occurred, set the "path not found" flag */
  2472 
  2489 
  2473 	assert(v->u.rail.track);
  2490 	assert(v->u.rail.track);
  2474 
  2491 
  2475 	int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)];
  2492 	int i = _search_directions[FIND_FIRST_BIT(v->u.rail.track)][DirToDiagDir(v->direction)];
  2476 
  2493 
  2477 	if (_patches.yapf.rail_use_yapf) {
  2494 	switch (_patches.pathfinder_for_trains) {
  2478 		reverse_best = YapfCheckReverseTrain(v);
  2495 		case VPF_YAPF: { /* YAPF */
  2479 	} else if (_patches.new_pathfinding_all) { /* Use a new pathfinding for everything */
  2496 			reverse_best = YapfCheckReverseTrain(v);
  2480 		NPFFindStationOrTileData fstd;
  2497 		} break;
  2481 		NPFFoundTargetData ftd;
  2498 
  2482 		Trackdir trackdir, trackdir_rev;
  2499 		case VPF_NPF: { /* NPF */
  2483 		Vehicle* last = GetLastVehicleInChain(v);
  2500 			NPFFindStationOrTileData fstd;
  2484 
  2501 			NPFFoundTargetData ftd;
  2485 		NPFFillWithOrderData(&fstd, v);
  2502 			Vehicle* last = GetLastVehicleInChain(v);
  2486 
  2503 
  2487 		trackdir = GetVehicleTrackdir(v);
  2504 			NPFFillWithOrderData(&fstd, v);
  2488 		trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
  2505 
  2489 		assert(trackdir != 0xff);
  2506 			Trackdir trackdir = GetVehicleTrackdir(v);
  2490 		assert(trackdir_rev != 0xff);
  2507 			Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
  2491 
  2508 			assert(trackdir != INVALID_TRACKDIR);
  2492 		ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, last->tile, trackdir_rev, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
  2509 			assert(trackdir_rev != INVALID_TRACKDIR);
  2493 		if (ftd.best_bird_dist != 0) {
  2510 
  2494 			/* We didn't find anything, just keep on going straight ahead */
  2511 			ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, &fstd, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes);
  2495 			reverse_best = false;
  2512 			if (ftd.best_bird_dist != 0) {
  2496 		} else {
  2513 				/* We didn't find anything, just keep on going straight ahead */
  2497 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
  2514 				reverse_best = false;
  2498 				reverse_best = true;
       
  2499 			} else {
  2515 			} else {
  2500 				reverse_best = false;
  2516 				if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) {
  2501 			}
  2517 					reverse_best = true;
  2502 		}
  2518 				} else {
  2503 	} else {
  2519 					reverse_best = false;
  2504 		int best_track = -1;
  2520 				}
  2505 		uint reverse = 0;
  2521 			}
  2506 		uint best_bird_dist  = 0;
  2522 		} break;
  2507 		uint best_track_dist = 0;
  2523 
  2508 
  2524 		default:
  2509 		for (;;) {
  2525 		case VPF_NTP: { /* NTP */
  2510 			fd.best_bird_dist = (uint)-1;
  2526 			int best_track = -1;
  2511 			fd.best_track_dist = (uint)-1;
  2527 			uint reverse = 0;
  2512 
  2528 			uint best_bird_dist  = 0;
  2513 			NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
  2529 			uint best_track_dist = 0;
  2514 
  2530 
  2515 			if (best_track != -1) {
  2531 			for (;;) {
  2516 				if (best_bird_dist != 0) {
  2532 				fd.best_bird_dist = UINT_MAX;
  2517 					if (fd.best_bird_dist != 0) {
  2533 				fd.best_track_dist = UINT_MAX;
  2518 						/* neither reached the destination, pick the one with the smallest bird dist */
  2534 
  2519 						if (fd.best_bird_dist > best_bird_dist) goto bad;
  2535 				NewTrainPathfind(v->tile, v->dest_tile, v->u.rail.compatible_railtypes, (DiagDirection)(reverse ^ i), (NTPEnumProc*)NtpCallbFindStation, &fd);
  2520 						if (fd.best_bird_dist < best_bird_dist) goto good;
  2536 
       
  2537 				if (best_track != -1) {
       
  2538 					if (best_bird_dist != 0) {
       
  2539 						if (fd.best_bird_dist != 0) {
       
  2540 							/* neither reached the destination, pick the one with the smallest bird dist */
       
  2541 							if (fd.best_bird_dist > best_bird_dist) goto bad;
       
  2542 							if (fd.best_bird_dist < best_bird_dist) goto good;
       
  2543 						} else {
       
  2544 							/* we found the destination for the first time */
       
  2545 							goto good;
       
  2546 						}
  2521 					} else {
  2547 					} else {
  2522 						/* we found the destination for the first time */
  2548 						if (fd.best_bird_dist != 0) {
  2523 						goto good;
  2549 							/* didn't find destination, but we've found the destination previously */
       
  2550 							goto bad;
       
  2551 						} else {
       
  2552 							/* both old & new reached the destination, compare track length */
       
  2553 							if (fd.best_track_dist > best_track_dist) goto bad;
       
  2554 							if (fd.best_track_dist < best_track_dist) goto good;
       
  2555 						}
  2524 					}
  2556 					}
  2525 				} else {
  2557 
  2526 					if (fd.best_bird_dist != 0) {
  2558 					/* if we reach this position, there's two paths of equal value so far.
  2527 						/* didn't find destination, but we've found the destination previously */
  2559 					 * pick one randomly. */
  2528 						goto bad;
  2560 					int r = GB(Random(), 0, 8);
  2529 					} else {
  2561 					if (_pick_track_table[i] == (v->direction & 3)) r += 80;
  2530 						/* both old & new reached the destination, compare track length */
  2562 					if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
  2531 						if (fd.best_track_dist > best_track_dist) goto bad;
  2563 					if (r <= 127) goto bad;
  2532 						if (fd.best_track_dist < best_track_dist) goto good;
       
  2533 					}
       
  2534 				}
  2564 				}
  2535 
       
  2536 				/* if we reach this position, there's two paths of equal value so far.
       
  2537 				 * pick one randomly. */
       
  2538 				int r = GB(Random(), 0, 8);
       
  2539 				if (_pick_track_table[i] == (v->direction & 3)) r += 80;
       
  2540 				if (_pick_track_table[best_track] == (v->direction & 3)) r -= 80;
       
  2541 				if (r <= 127) goto bad;
       
  2542 			}
       
  2543 good:;
  2565 good:;
  2544 			best_track = i;
  2566 				best_track = i;
  2545 			best_bird_dist = fd.best_bird_dist;
  2567 				best_bird_dist = fd.best_bird_dist;
  2546 			best_track_dist = fd.best_track_dist;
  2568 				best_track_dist = fd.best_track_dist;
  2547 			reverse_best = reverse;
  2569 				reverse_best = reverse;
  2548 bad:;
  2570 bad:;
  2549 			if (reverse != 0) break;
  2571 				if (reverse != 0) break;
  2550 			reverse = 2;
  2572 				reverse = 2;
  2551 		}
  2573 			}
       
  2574 		} break;
  2552 	}
  2575 	}
  2553 
  2576 
  2554 	return reverse_best != 0;
  2577 	return reverse_best != 0;
  2555 }
  2578 }
  2556 
  2579 
  2752 	DIR_N , DIR_NW, DIR_W , INVALID_DIR,
  2775 	DIR_N , DIR_NW, DIR_W , INVALID_DIR,
  2753 	DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
  2776 	DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
  2754 	DIR_E , DIR_SE, DIR_S
  2777 	DIR_E , DIR_SE, DIR_S
  2755 };
  2778 };
  2756 
  2779 
  2757 static Direction GetNewVehicleDirectionByTile(TileIndex new_tile, TileIndex old_tile)
  2780 static inline Direction GetNewVehicleDirectionByTile(TileIndex new_tile, TileIndex old_tile)
  2758 {
  2781 {
  2759 	uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
  2782 	uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
  2760 							TileX(new_tile) - TileX(old_tile) + 1;
  2783 							TileX(new_tile) - TileX(old_tile) + 1;
  2761 	assert(offs < 11);
  2784 	assert(offs < 11);
  2762 	return _new_vehicle_direction_table[offs];
  2785 	return _new_vehicle_direction_table[offs];
  2763 }
  2786 }
  2764 
  2787 
  2765 static int GetDirectionToVehicle(const Vehicle *v, int x, int y)
  2788 static inline int GetDirectionToVehicle(const Vehicle *v, int x, int y)
  2766 {
  2789 {
  2767 	byte offs;
  2790 	byte offs;
  2768 
  2791 
  2769 	x -= v->x_pos;
  2792 	x -= v->x_pos;
  2770 	if (x >= 0) {
  2793 	if (x >= 0) {
  2783 	assert(offs < 11);
  2806 	assert(offs < 11);
  2784 	return _new_vehicle_direction_table[offs];
  2807 	return _new_vehicle_direction_table[offs];
  2785 }
  2808 }
  2786 
  2809 
  2787 /* Check if the vehicle is compatible with the specified tile */
  2810 /* Check if the vehicle is compatible with the specified tile */
  2788 static bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
  2811 static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
  2789 {
  2812 {
  2790 	return
  2813 	return
  2791 		IsTileOwner(tile, v->owner) && (
  2814 		IsTileOwner(tile, v->owner) && (
  2792 			!IsFrontEngine(v) ||
  2815 			!IsFrontEngine(v) ||
  2793 			HasBit(v->u.rail.compatible_railtypes, GetRailType(tile))
  2816 			HasBit(v->u.rail.compatible_railtypes, GetRailType(tile))
  2807 	{256 / 4, 256 / 2, 256 / 4, 2}, ///< monorail
  2830 	{256 / 4, 256 / 2, 256 / 4, 2}, ///< monorail
  2808 	{0,       256 / 2, 256 / 4, 2}, ///< maglev
  2831 	{0,       256 / 2, 256 / 4, 2}, ///< maglev
  2809 };
  2832 };
  2810 
  2833 
  2811 /** Modify the speed of the vehicle due to a turn */
  2834 /** Modify the speed of the vehicle due to a turn */
  2812 static void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
  2835 static inline void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
  2813 {
  2836 {
  2814 	if (_patches.realistic_acceleration) return;
  2837 	if (_patches.realistic_acceleration) return;
  2815 
  2838 
  2816 	DirDiff diff = DirDifference(v->direction, new_dir);
  2839 	DirDiff diff = DirDifference(v->direction, new_dir);
  2817 	if (diff == DIRDIFF_SAME) return;
  2840 	if (diff == DIRDIFF_SAME) return;
  2819 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2842 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2820 	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
  2843 	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
  2821 }
  2844 }
  2822 
  2845 
  2823 /** Modify the speed of the vehicle due to a change in altitude */
  2846 /** Modify the speed of the vehicle due to a change in altitude */
  2824 static void AffectSpeedByZChange(Vehicle *v, byte old_z)
  2847 static inline void AffectSpeedByZChange(Vehicle *v, byte old_z)
  2825 {
  2848 {
  2826 	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
  2849 	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
  2827 
  2850 
  2828 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2851 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2829 
  2852 
  3021 				enterdir = DirToDiagDir(dir);
  3044 				enterdir = DirToDiagDir(dir);
  3022 				assert(IsValidDiagDirection(enterdir));
  3045 				assert(IsValidDiagDirection(enterdir));
  3023 
  3046 
  3024 				/* Get the status of the tracks in the new tile and mask
  3047 				/* Get the status of the tracks in the new tile and mask
  3025 				 * away the bits that aren't reachable. */
  3048 				 * away the bits that aren't reachable. */
  3026 				uint32 ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0) & _reachable_tracks[enterdir];
  3049 				TrackStatus ts = GetTileTrackStatus(gp.new_tile, TRANSPORT_RAIL, 0, ReverseDiagDir(enterdir)) & _reachable_tracks[enterdir];
  3027 
  3050 				TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
  3028 				/* Combine the from & to directions.
  3051 				TrackBits red_signals = TrackdirBitsToTrackBits(TrackStatusToRedSignals(ts));
  3029 				 * Now, the lower byte contains the track status, and the byte at bit 16 contains
  3052 
  3030 				 * the signal status. */
  3053 				TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
  3031 				uint32 tracks = ts | (ts >> 8);
  3054 				if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg && prev == NULL) {
  3032 				TrackBits bits = (TrackBits)(tracks & TRACK_BIT_MASK);
       
  3033 				if ((_patches.new_pathfinding_all || _patches.yapf.rail_use_yapf) && _patches.forbid_90_deg && prev == NULL) {
       
  3034 					/* We allow wagons to make 90 deg turns, because forbid_90_deg
  3055 					/* We allow wagons to make 90 deg turns, because forbid_90_deg
  3035 					 * can be switched on halfway a turn */
  3056 					 * can be switched on halfway a turn */
  3036 					bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
  3057 					bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
  3037 				}
  3058 				}
  3038 
  3059 
  3045 				TrackBits chosen_track;
  3066 				TrackBits chosen_track;
  3046 				if (prev == NULL) {
  3067 				if (prev == NULL) {
  3047 					/* Currently the locomotive is active. Determine which one of the
  3068 					/* Currently the locomotive is active. Determine which one of the
  3048 					 * available tracks to choose */
  3069 					 * available tracks to choose */
  3049 					chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
  3070 					chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
  3050 					assert(chosen_track & tracks);
  3071 					assert(chosen_track & bits);
  3051 
  3072 
  3052 					/* Check if it's a red signal and that force proceed is not clicked. */
  3073 					/* Check if it's a red signal and that force proceed is not clicked. */
  3053 					if ((tracks >> 16) & chosen_track && v->u.rail.force_proceed == 0) {
  3074 					if (red_signals & chosen_track && v->u.rail.force_proceed == 0) {
  3054 						/* In front of a red signal
  3075 						/* In front of a red signal */
  3055 						 * find the first set bit in ts. need to do it in 2 steps, since
  3076 						Trackdir i = FindFirstTrackdir(trackdirbits);
  3056 						 * FIND_FIRST_BIT only handles 6 bits at a time. */
       
  3057 						Trackdir i = FindFirstTrackdir((TrackdirBits)(uint16)ts);
       
  3058 
  3077 
  3059 						if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
  3078 						if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
  3060 							v->cur_speed = 0;
  3079 							v->cur_speed = 0;
  3061 							v->subspeed = 0;
  3080 							v->subspeed = 0;
  3062 							v->progress = 255 - 100;
  3081 							v->progress = 255 - 100;
  3130 			/* In a tunnel or on a bridge
  3149 			/* In a tunnel or on a bridge
  3131 			 * - for tunnels, only the part when the vehicle is not visible (part of enter/exit tile too)
  3150 			 * - for tunnels, only the part when the vehicle is not visible (part of enter/exit tile too)
  3132 			 * - for bridges, only the middle part - without the bridge heads */
  3151 			 * - for bridges, only the middle part - without the bridge heads */
  3133 			if (!(v->vehstatus & VS_HIDDEN)) {
  3152 			if (!(v->vehstatus & VS_HIDDEN)) {
  3134 				v->cur_speed =
  3153 				v->cur_speed =
  3135 					min(v->cur_speed, GetBridge(GetBridgeType(v->tile))->speed);
  3154 					min(v->cur_speed, GetBridgeSpec(GetBridgeType(v->tile))->speed);
  3136 			}
  3155 			}
  3137 
  3156 
  3138 			if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
  3157 			if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
  3139 				v->x_pos = gp.x;
  3158 				v->x_pos = gp.x;
  3140 				v->y_pos = gp.y;
  3159 				v->y_pos = gp.y;
  3418 	if (!TrainCanLeaveTile(v)) return INVALID_TILE;
  3437 	if (!TrainCanLeaveTile(v)) return INVALID_TILE;
  3419 
  3438 
  3420 	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
  3439 	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
  3421 	TileIndex tile = v->tile + TileOffsByDiagDir(dir);
  3440 	TileIndex tile = v->tile + TileOffsByDiagDir(dir);
  3422 
  3441 
  3423 	/* not a crossing || wrong axis || wrong railtype || wrong owner */
  3442 	/* not a crossing || wrong axis || unusable rail (wrong type or owner) */
  3424 	if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
  3443 	if (!IsLevelCrossingTile(tile) || DiagDirToAxis(dir) == GetCrossingRoadAxis(tile) ||
  3425 			!CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner) {
  3444 			!CheckCompatibleRail(v, tile)) {
  3426 		return INVALID_TILE;
  3445 		return INVALID_TILE;
  3427 	}
  3446 	}
  3428 
  3447 
  3429 	return tile;
  3448 	return tile;
  3430 }
  3449 }
  3456 	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
  3475 	DiagDirection dir = TrainExitDir(v->direction, v->u.rail.track);
  3457 	/* Calculate next tile */
  3476 	/* Calculate next tile */
  3458 	TileIndex tile = v->tile + TileOffsByDiagDir(dir);
  3477 	TileIndex tile = v->tile + TileOffsByDiagDir(dir);
  3459 
  3478 
  3460 	/* Determine the track status on the next tile */
  3479 	/* Determine the track status on the next tile */
  3461 	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0) & _reachable_tracks[dir];
  3480 	TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0, ReverseDiagDir(dir)) & _reachable_tracks[dir];
       
  3481 	TrackdirBits trackdirbits = TrackStatusToTrackdirBits(ts);
       
  3482 	TrackdirBits red_signals = TrackStatusToRedSignals(ts);
  3462 
  3483 
  3463 	/* We are sure the train is not entering a depot, it is detected above */
  3484 	/* We are sure the train is not entering a depot, it is detected above */
  3464 
  3485 
  3465 	/* no suitable trackbits at all || wrong railtype || not our track ||
  3486 	/* mask unreachable track bits if we are forbidden to do 90deg turns */
  3466 	 *   tunnel/bridge from opposite side || depot from opposite side */
  3487 	TrackBits bits = TrackdirBitsToTrackBits(trackdirbits);
  3467 	if (GB(ts, 0, 16) == 0 || !CheckCompatibleRail(v, tile) || GetTileOwner(tile) != v->owner ||
  3488 	if (_patches.pathfinder_for_trains != VPF_NTP && _patches.forbid_90_deg) {
  3468 			(IsTileType(tile, MP_TUNNELBRIDGE) && GetTunnelBridgeDirection(tile) != dir) ||
  3489 		bits &= ~TrackCrossesTracks(FindFirstTrack(v->u.rail.track));
  3469 			(IsTileDepotType(tile, TRANSPORT_RAIL) && GetRailDepotDirection(tile) == dir) ) {
  3490 	}
       
  3491 
       
  3492 	/* no suitable trackbits at all || unusable rail (wrong type or owner) */
       
  3493 	if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(v, tile)) {
  3470 		return TrainApproachingLineEnd(v, false);
  3494 		return TrainApproachingLineEnd(v, false);
  3471 	}
  3495 	}
  3472 
  3496 
  3473 	/* approaching red signal */
  3497 	/* approaching red signal */
  3474 	if ((ts & (ts >> 16)) != 0) return TrainApproachingLineEnd(v, true);
  3498 	if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(v, true);
  3475 
  3499 
  3476 	/* approaching a rail/road crossing? then make it red */
  3500 	/* approaching a rail/road crossing? then make it red */
  3477 	if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
  3501 	if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
  3478 
  3502 
  3479 	return true;
  3503 	return true;
  3554 	const Vehicle *v = this;
  3578 	const Vehicle *v = this;
  3555 
  3579 
  3556 	do {
  3580 	do {
  3557 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  3581 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  3558 
  3582 
  3559 		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
  3583 		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost);
  3560 		if (cost_factor == 0) continue;
  3584 		if (cost_factor == 0) continue;
  3561 
  3585 
  3562 		cost += cost_factor * _price.running_rail[rvi->running_cost_class];
  3586 		cost += cost_factor * GetPriceByIndex(rvi->running_cost_class);
  3563 	} while ((v = GetNextVehicle(v)) != NULL);
  3587 	} while ((v = GetNextVehicle(v)) != NULL);
  3564 
  3588 
  3565 	return cost;
  3589 	return cost;
  3566 }
  3590 }
  3567 
  3591 
  3571 	if (_age_cargo_skip_counter == 0) this->cargo.AgeCargo();
  3595 	if (_age_cargo_skip_counter == 0) this->cargo.AgeCargo();
  3572 
  3596 
  3573 	this->tick_counter++;
  3597 	this->tick_counter++;
  3574 
  3598 
  3575 	if (IsFrontEngine(this)) {
  3599 	if (IsFrontEngine(this)) {
       
  3600 		if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
  3576 		this->current_order_time++;
  3601 		this->current_order_time++;
  3577 
  3602 
  3578 		TrainLocoHandler(this, false);
  3603 		TrainLocoHandler(this, false);
  3579 
  3604 
  3580 		/* make sure vehicle wasn't deleted. */
  3605 		/* make sure vehicle wasn't deleted. */
  3641 		if (this->current_order.type == OT_GOTO_STATION) {
  3666 		if (this->current_order.type == OT_GOTO_STATION) {
  3642 			TileIndex tile = GetStation(this->current_order.dest)->train_tile;
  3667 			TileIndex tile = GetStation(this->current_order.dest)->train_tile;
  3643 			if (tile != 0) this->dest_tile = tile;
  3668 			if (tile != 0) this->dest_tile = tile;
  3644 		}
  3669 		}
  3645 
  3670 
  3646 		if ((this->vehstatus & VS_STOPPED) == 0) {
  3671 		if (this->running_ticks != 0) {
  3647 			/* running costs */
  3672 			/* running costs */
  3648 			CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() / 364);
  3673 			CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (364 * DAY_TICKS));
  3649 
  3674 
  3650 			this->profit_this_year -= cost.GetCost() >> 8;
  3675 			this->profit_this_year -= cost.GetCost();
       
  3676 			this->running_ticks = 0;
  3651 
  3677 
  3652 			SubtractMoneyFromPlayerFract(this->owner, cost);
  3678 			SubtractMoneyFromPlayerFract(this->owner, cost);
  3653 
  3679 
  3654 			InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
  3680 			InvalidateWindow(WC_VEHICLE_DETAILS, this->index);
  3655 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3681 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3665 	Vehicle *v;
  3691 	Vehicle *v;
  3666 
  3692 
  3667 	FOR_ALL_VEHICLES(v) {
  3693 	FOR_ALL_VEHICLES(v) {
  3668 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3694 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3669 			/* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
  3695 			/* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
  3670 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3696 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->GetDisplayProfitThisYear() < 0) {
  3671 				SetDParam(1, v->profit_this_year);
  3697 				SetDParam(1, v->GetDisplayProfitThisYear());
  3672 				SetDParam(0, v->unitnumber);
  3698 				SetDParam(0, v->unitnumber);
  3673 				AddNewsItem(
  3699 				AddNewsItem(
  3674 					STR_TRAIN_IS_UNPROFITABLE,
  3700 					STR_TRAIN_IS_UNPROFITABLE,
  3675 					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
  3701 					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
  3676 					v->index,
  3702 					v->index,