src/train_cmd.cpp
branchgamebalance
changeset 9908 0fa543611bbe
parent 9906 6f41b8713b65
child 9909 dce9a6923bb7
equal deleted inserted replaced
9907:3b068c3a1c74 9908:0fa543611bbe
     1 /* $Id$ */
     1 /* $Id$ */
       
     2 
       
     3 /** @file train_cmd.cpp */
     2 
     4 
     3 #include "stdafx.h"
     5 #include "stdafx.h"
     4 #include "openttd.h"
     6 #include "openttd.h"
     5 #include "bridge_map.h"
     7 #include "bridge_map.h"
     6 #include "debug.h"
     8 #include "debug.h"
     7 #include "functions.h"
     9 #include "functions.h"
       
    10 #include "landscape.h"
     8 #include "gui.h"
    11 #include "gui.h"
     9 #include "station_map.h"
    12 #include "station_map.h"
    10 #include "table/strings.h"
    13 #include "table/strings.h"
    11 #include "map.h"
    14 #include "map.h"
    12 #include "tile.h"
    15 #include "tile.h"
   103 	uint32 weight = 0;
   106 	uint32 weight = 0;
   104 
   107 
   105 	for (Vehicle *u = v; u != NULL; u = u->next) {
   108 	for (Vehicle *u = v; u != NULL; u = u->next) {
   106 		uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo_count * FreightWagonMult(u->cargo_type) / 16;
   109 		uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo_count * FreightWagonMult(u->cargo_type) / 16;
   107 
   110 
   108 		// Vehicle weight is not added for articulated parts.
   111 		/* Vehicle weight is not added for articulated parts. */
   109 		if (!IsArticulatedPart(u)) {
   112 		if (!IsArticulatedPart(u)) {
   110 			// vehicle weight is the sum of the weight of the vehicle and the weight of its cargo
   113 			/* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */
   111 			vweight += RailVehInfo(u->engine_type)->weight;
   114 			vweight += RailVehInfo(u->engine_type)->weight;
   112 
   115 
   113 			// powered wagons have extra weight added
   116 			/* powered wagons have extra weight added */
   114 			if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON))
   117 			if (HASBIT(u->u.rail.flags, VRF_POWEREDWAGON))
   115 				vweight += RailVehInfo(u->u.rail.first_engine)->pow_wag_weight;
   118 				vweight += RailVehInfo(u->u.rail.first_engine)->pow_wag_weight;
   116 		}
   119 		}
   117 
   120 
   118 		// consist weight is the sum of the weight of all vehicles in the consist
   121 		/* consist weight is the sum of the weight of all vehicles in the consist */
   119 		weight += vweight;
   122 		weight += vweight;
   120 
   123 
   121 		// store vehicle weight in cache
   124 		/* store vehicle weight in cache */
   122 		u->u.rail.cached_veh_weight = vweight;
   125 		u->u.rail.cached_veh_weight = vweight;
   123 	}
   126 	}
   124 
   127 
   125 	// store consist weight in cache
   128 	/* store consist weight in cache */
   126 	v->u.rail.cached_weight = weight;
   129 	v->u.rail.cached_weight = weight;
   127 
   130 
   128 	/* Now update train power (tractive effort is dependent on weight) */
   131 	/* Now update train power (tractive effort is dependent on weight) */
   129 	TrainPowerChanged(v);
   132 	TrainPowerChanged(v);
   130 }
   133 }
   149 	v->u.rail.compatible_railtypes = 0;
   152 	v->u.rail.compatible_railtypes = 0;
   150 
   153 
   151 	for (Vehicle *u = v; u != NULL; u = u->next) {
   154 	for (Vehicle *u = v; u != NULL; u = u->next) {
   152 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
   155 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
   153 
   156 
   154 		// Update the v->first cache. This is faster than having to brute force it later.
   157 		/* Update the v->first cache. This is faster than having to brute force it later. */
   155 		if (u->first == NULL) u->first = v;
   158 		if (u->first == NULL) u->first = v;
   156 
   159 
   157 		// update the 'first engine'
   160 		/* update the 'first engine' */
   158 		u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine;
   161 		u->u.rail.first_engine = v == u ? INVALID_ENGINE : first_engine;
   159 		u->u.rail.railtype = rvi_u->railtype;
   162 		u->u.rail.railtype = rvi_u->railtype;
   160 
   163 
   161 		if (IsTrainEngine(u)) first_engine = u->engine_type;
   164 		if (IsTrainEngine(u)) first_engine = u->engine_type;
   162 
   165 
   163 		if (rvi_u->visual_effect != 0) {
   166 		if (rvi_u->visual_effect != 0) {
   164 			u->u.rail.cached_vis_effect = rvi_u->visual_effect;
   167 			u->u.rail.cached_vis_effect = rvi_u->visual_effect;
   165 		} else {
   168 		} else {
   166 			if (IsTrainWagon(u) || IsArticulatedPart(u)) {
   169 			if (IsTrainWagon(u) || IsArticulatedPart(u)) {
   167 				// Wagons and articulated parts have no effect by default
   170 				/* Wagons and articulated parts have no effect by default */
   168 				u->u.rail.cached_vis_effect = 0x40;
   171 				u->u.rail.cached_vis_effect = 0x40;
   169 			} else if (rvi_u->engclass == 0) {
   172 			} else if (rvi_u->engclass == 0) {
   170 				// Steam is offset by -4 units
   173 				/* Steam is offset by -4 units */
   171 				u->u.rail.cached_vis_effect = 4;
   174 				u->u.rail.cached_vis_effect = 4;
   172 			} else {
   175 			} else {
   173 				// Diesel fumes and sparks come from the centre
   176 				/* Diesel fumes and sparks come from the centre */
   174 				u->u.rail.cached_vis_effect = 8;
   177 				u->u.rail.cached_vis_effect = 8;
   175 			}
   178 			}
   176 		}
   179 		}
   177 
   180 
   178 		if (!IsArticulatedPart(u)) {
   181 		if (!IsArticulatedPart(u)) {
   202 			if (HASBIT(u->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
   205 			if (HASBIT(u->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL)) {
   203 				u->u.rail.railtype = RAILTYPE_RAIL;
   206 				u->u.rail.railtype = RAILTYPE_RAIL;
   204 				u->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
   207 				u->u.rail.compatible_railtypes |= (1 << RAILTYPE_RAIL);
   205 			}
   208 			}
   206 
   209 
   207 			// max speed is the minimum of the speed limits of all vehicles in the consist
   210 			/* max speed is the minimum of the speed limits of all vehicles in the consist */
   208 			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) &&
   211 			if ((rvi_u->railveh_type != RAILVEH_WAGON || _patches.wagon_speed_limits) &&
   209 				rvi_u->max_speed != 0 && !UsesWagonOverride(u))
   212 				rvi_u->max_speed != 0 && !UsesWagonOverride(u))
   210 				max_speed = min(rvi_u->max_speed, max_speed);
   213 				max_speed = min(rvi_u->max_speed, max_speed);
   211 		}
   214 		}
   212 
   215 
   213 		// check the vehicle length (callback)
   216 		/* check the vehicle length (callback) */
   214 		uint16 veh_len = CALLBACK_FAILED;
   217 		uint16 veh_len = CALLBACK_FAILED;
   215 		if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) {
   218 		if (HASBIT(EngInfo(u->engine_type)->callbackmask, CBM_VEHICLE_LENGTH)) {
   216 			veh_len = GetVehicleCallback(CBID_TRAIN_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
   219 			veh_len = GetVehicleCallback(CBID_TRAIN_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
   217 		}
   220 		}
   218 		if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
   221 		if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
   219 		veh_len = clamp(veh_len, 0, u->next == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
   222 		veh_len = clamp(veh_len, 0, u->next == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
   220 		u->u.rail.cached_veh_length = 8 - veh_len;
   223 		u->u.rail.cached_veh_length = 8 - veh_len;
   221 		v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
   224 		v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
   222 	}
   225 	}
   223 
   226 
   224 	// store consist weight/max speed in cache
   227 	/* store consist weight/max speed in cache */
   225 	v->u.rail.cached_max_speed = max_speed;
   228 	v->u.rail.cached_max_speed = max_speed;
   226 
   229 
   227 	// recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added)
   230 	/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
   228 	TrainCargoChanged(v);
   231 	TrainCargoChanged(v);
   229 }
   232 }
   230 
   233 
   231 /* These two arrays are used for realistic acceleration. XXX: How should they
   234 /* These two arrays are used for realistic acceleration. XXX: How should they
   232  * be interpreted? */
   235  * be interpreted? */
   261 {
   264 {
   262 	const Order* o = &v->current_order;
   265 	const Order* o = &v->current_order;
   263 	StationID sid = GetStationIndex(tile);
   266 	StationID sid = GetStationIndex(tile);
   264 
   267 
   265 	assert(v->type == VEH_TRAIN);
   268 	assert(v->type == VEH_TRAIN);
   266 	//When does a train drive through a station
   269 	/* When does a train drive through a station
   267 	//first we deal with the "new nonstop handling"
   270 	 * first we deal with the "new nonstop handling" */
   268 	if (_patches.new_nonstop && o->flags & OF_NON_STOP && sid == o->dest) {
   271 	if (_patches.new_nonstop && o->flags & OF_NON_STOP && sid == o->dest) {
   269 		return false;
   272 		return false;
   270 	}
   273 	}
   271 
   274 
   272 	if (v->last_station_visited == sid) return false;
   275 	if (v->last_station_visited == sid) return false;
   276 	}
   279 	}
   277 
   280 
   278 	return true;
   281 	return true;
   279 }
   282 }
   280 
   283 
   281 //new acceleration
   284 /** new acceleration*/
   282 static int GetTrainAcceleration(Vehicle *v, bool mode)
   285 static int GetTrainAcceleration(Vehicle *v, bool mode)
   283 {
   286 {
   284 	int max_speed = 2000;
   287 	int max_speed = 2000;
   285 	int speed = v->cur_speed * 10 / 16; //[mph]
   288 	int speed = v->cur_speed * 10 / 16; //[mph]
   286 	int curvecount[2] = {0, 0};
   289 	int curvecount[2] = {0, 0};
   287 
   290 
   288 	//first find the curve speed limit
   291 	/*first find the curve speed limit */
   289 	int numcurve = 0;
   292 	int numcurve = 0;
   290 	int sum = 0;
   293 	int sum = 0;
   291 	int pos = 0;
   294 	int pos = 0;
   292 	int lastpos = -1;
   295 	int lastpos = -1;
   293 	for (const Vehicle *u = v; u->next != NULL; u = u->next, pos++) {
   296 	for (const Vehicle *u = v; u->next != NULL; u = u->next, pos++) {
   307 				}
   310 				}
   308 				lastpos = pos;
   311 				lastpos = pos;
   309 			}
   312 			}
   310 		}
   313 		}
   311 
   314 
   312 		//if we have a 90 degree turn, fix the speed limit to 60
   315 		/*if we have a 90 degree turn, fix the speed limit to 60 */
   313 		if (_curve_neighbours90[dir][0] == ndir ||
   316 		if (_curve_neighbours90[dir][0] == ndir ||
   314 				_curve_neighbours90[dir][1] == ndir) {
   317 				_curve_neighbours90[dir][1] == ndir) {
   315 			max_speed = 61;
   318 			max_speed = 61;
   316 		}
   319 		}
   317 	}
   320 	}
   400 			case RAILTYPE_MAGLEV:
   403 			case RAILTYPE_MAGLEV:
   401 				force = power / 25;
   404 				force = power / 25;
   402 				break;
   405 				break;
   403 		}
   406 		}
   404 	} else {
   407 	} else {
   405 		//"kickoff" acceleration
   408 		/* "kickoff" acceleration */
   406 		force = (mode == AM_ACCEL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? min(max_te, power) : power;
   409 		force = (mode == AM_ACCEL && v->u.rail.railtype != RAILTYPE_MAGLEV) ? min(max_te, power) : power;
   407 		force = max(force, (mass * 8) + resistance);
   410 		force = max(force, (mass * 8) + resistance);
   408 	}
   411 	}
   409 
   412 
   410 	if (force <= 0) force = 10000;
   413 	if (force <= 0) force = 10000;
   519 
   522 
   520 		EngineID engine_type = GB(callback, 0, 7);
   523 		EngineID engine_type = GB(callback, 0, 7);
   521 		bool flip_image = HASBIT(callback, 7);
   524 		bool flip_image = HASBIT(callback, 7);
   522 		const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
   525 		const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type);
   523 
   526 
   524 		// get common values from first engine
   527 		/* get common values from first engine */
   525 		u->direction = v->direction;
   528 		u->direction = v->direction;
   526 		u->owner = v->owner;
   529 		u->owner = v->owner;
   527 		u->tile = v->tile;
   530 		u->tile = v->tile;
   528 		u->x_pos = v->x_pos;
   531 		u->x_pos = v->x_pos;
   529 		u->y_pos = v->y_pos;
   532 		u->y_pos = v->y_pos;
   533 		u->u.rail.railtype = v->u.rail.railtype;
   536 		u->u.rail.railtype = v->u.rail.railtype;
   534 		u->build_year = v->build_year;
   537 		u->build_year = v->build_year;
   535 		u->vehstatus = v->vehstatus & ~VS_STOPPED;
   538 		u->vehstatus = v->vehstatus & ~VS_STOPPED;
   536 		u->u.rail.first_engine = v->engine_type;
   539 		u->u.rail.first_engine = v->engine_type;
   537 
   540 
   538 		// get more settings from rail vehicle info
   541 		/* get more settings from rail vehicle info */
   539 		u->spritenum = rvi_artic->image_index;
   542 		u->spritenum = rvi_artic->image_index;
   540 		if (flip_image) u->spritenum++;
   543 		if (flip_image) u->spritenum++;
   541 		u->cargo_type = rvi_artic->cargo_type;
   544 		u->cargo_type = rvi_artic->cargo_type;
   542 		u->cargo_subtype = 0;
   545 		u->cargo_subtype = 0;
   543 		u->cargo_cap = rvi_artic->capacity;
   546 		u->cargo_cap = rvi_artic->capacity;
   643 	}
   646 	}
   644 
   647 
   645 	return value;
   648 	return value;
   646 }
   649 }
   647 
   650 
   648 // Move all free vehicles in the depot to the train
   651 /** Move all free vehicles in the depot to the train */
   649 static void NormalizeTrainVehInDepot(const Vehicle* u)
   652 static void NormalizeTrainVehInDepot(const Vehicle* u)
   650 {
   653 {
   651 	const Vehicle* v;
   654 	const Vehicle* v;
   652 
   655 
   653 	FOR_ALL_VEHICLES(v) {
   656 	FOR_ALL_VEHICLES(v) {
   695 	VehiclePositionChanged(u);
   698 	VehiclePositionChanged(u);
   696 }
   699 }
   697 
   700 
   698 /** Build a railroad vehicle.
   701 /** Build a railroad vehicle.
   699  * @param tile tile of the depot where rail-vehicle is built
   702  * @param tile tile of the depot where rail-vehicle is built
       
   703  * @param flags type of operation
   700  * @param p1 engine type id
   704  * @param p1 engine type id
   701  * @param p2 bit 0 when set, the train will get number 0, otherwise it will get a free number
   705  * @param p2 bit 0 when set, the train will get number 0, otherwise it will get a free number
   702  *           bit 1 prevents any free cars from being added to the train
   706  *           bit 1 prevents any free cars from being added to the train
   703  */
   707  */
   704 int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   708 int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   705 {
   709 {
   706 	/* Check if the engine-type is valid (for the player) */
   710 	/* Check if the engine-type is valid (for the player) */
   707 	if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   711 	if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_RAIL_VEHICLE_NOT_AVAILABLE);
   708 
   712 
   709 	/* Check if the train is actually being built in a depot belonging
   713 	/* Check if the train is actually being built in a depot belonging
   710 	 * to the player. Doesn't matter if only the cost is queried */
   714 	 * to the player. Doesn't matter if only the cost is queried */
   711 	if (!(flags & DC_QUERY_COST)) {
   715 	if (!(flags & DC_QUERY_COST)) {
   712 		if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
   716 		if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
   872  * @param first The first vehicle of the consist.
   876  * @param first The first vehicle of the consist.
   873  * @return The first vehicle of the consist.
   877  * @return The first vehicle of the consist.
   874  */
   878  */
   875 static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
   879 static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
   876 {
   880 {
   877 	// unlinking the first vehicle of the chain?
   881 	/* unlinking the first vehicle of the chain? */
   878 	if (v == first) {
   882 	if (v == first) {
   879 		v = GetNextVehicle(v);
   883 		v = GetNextVehicle(v);
   880 		if (v == NULL) return NULL;
   884 		if (v == NULL) return NULL;
   881 
   885 
   882 		if (IsTrainWagon(v)) SetFreeWagon(v);
   886 		if (IsTrainWagon(v)) SetFreeWagon(v);
   896 	EngineID eng = src->engine_type;
   900 	EngineID eng = src->engine_type;
   897 	TileIndex tile = src->tile;
   901 	TileIndex tile = src->tile;
   898 
   902 
   899 	FOR_ALL_VEHICLES(dst) {
   903 	FOR_ALL_VEHICLES(dst) {
   900 		if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile) {
   904 		if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile) {
   901 			// check so all vehicles in the line have the same engine.
   905 			/* check so all vehicles in the line have the same engine. */
   902 			Vehicle *v = dst;
   906 			Vehicle *v = dst;
   903 
   907 
   904 			while (v->engine_type == eng) {
   908 			while (v->engine_type == eng) {
   905 				v = v->next;
   909 				v = v->next;
   906 				if (v == NULL) return dst;
   910 				if (v == NULL) return dst;
   948 	}
   952 	}
   949 }
   953 }
   950 
   954 
   951 /** Move a rail vehicle around inside the depot.
   955 /** Move a rail vehicle around inside the depot.
   952  * @param tile unused
   956  * @param tile unused
       
   957  * @param flags type of operation
   953  * @param p1 various bitstuffed elements
   958  * @param p1 various bitstuffed elements
   954  * - p1 (bit  0 - 15) source vehicle index
   959  * - p1 (bit  0 - 15) source vehicle index
   955  * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line
   960  * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line
   956  * @param p2 (bit 0) move all vehicles following the source vehicle
   961  * @param p2 (bit 0) move all vehicles following the source vehicle
   957  */
   962  */
   964 
   969 
   965 	Vehicle *src = GetVehicle(s);
   970 	Vehicle *src = GetVehicle(s);
   966 
   971 
   967 	if (src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR;
   972 	if (src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR;
   968 
   973 
   969 	// if nothing is selected as destination, try and find a matching vehicle to drag to.
   974 	/* if nothing is selected as destination, try and find a matching vehicle to drag to. */
   970 	Vehicle *dst;
   975 	Vehicle *dst;
   971 	if (d == INVALID_VEHICLE) {
   976 	if (d == INVALID_VEHICLE) {
   972 		dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
   977 		dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
   973 	} else {
   978 	} else {
   974 		if (!IsValidVehicleID(d)) return CMD_ERROR;
   979 		if (!IsValidVehicleID(d)) return CMD_ERROR;
   975 		dst = GetVehicle(d);
   980 		dst = GetVehicle(d);
   976 		if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR;
   981 		if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR;
   977 	}
   982 	}
   978 
   983 
   979 	// if an articulated part is being handled, deal with its parent vehicle
   984 	/* if an articulated part is being handled, deal with its parent vehicle */
   980 	while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src);
   985 	while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src);
   981 	if (dst != NULL) {
   986 	if (dst != NULL) {
   982 		while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst);
   987 		while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst);
   983 	}
   988 	}
   984 
   989 
   985 	// don't move the same vehicle..
   990 	/* don't move the same vehicle.. */
   986 	if (src == dst) return 0;
   991 	if (src == dst) return 0;
   987 
   992 
   988 	/* locate the head of the two chains */
   993 	/* locate the head of the two chains */
   989 	Vehicle *src_head = GetFirstVehicleInChain(src);
   994 	Vehicle *src_head = GetFirstVehicleInChain(src);
   990 	Vehicle *dst_head;
   995 	Vehicle *dst_head;
   991 	if (dst != NULL) {
   996 	if (dst != NULL) {
   992 		dst_head = GetFirstVehicleInChain(dst);
   997 		dst_head = GetFirstVehicleInChain(dst);
   993 		if (dst_head->tile != src_head->tile) return CMD_ERROR;
   998 		if (dst_head->tile != src_head->tile) return CMD_ERROR;
   994 		// Now deal with articulated part of destination wagon
   999 		/* Now deal with articulated part of destination wagon */
   995 		dst = GetLastEnginePart(dst);
  1000 		dst = GetLastEnginePart(dst);
   996 	} else {
  1001 	} else {
   997 		dst_head = NULL;
  1002 		dst_head = NULL;
   998 	}
  1003 	}
   999 
  1004 
  1002 		if (dst->next == NULL) {
  1007 		if (dst->next == NULL) {
  1003 			/* It's the last one, so we will add the wagon just before the rear engine */
  1008 			/* It's the last one, so we will add the wagon just before the rear engine */
  1004 			dst = GetPrevVehicleInChain(dst);
  1009 			dst = GetPrevVehicleInChain(dst);
  1005 			/* Now if the vehicle we want to link to is the vehicle itself, drop out */
  1010 			/* Now if the vehicle we want to link to is the vehicle itself, drop out */
  1006 			if (dst == src) return CMD_ERROR;
  1011 			if (dst == src) return CMD_ERROR;
  1007 			// if dst is NULL, it means that dst got a rear multiheaded engine as first engine. We can't use that
  1012 			/* if dst is NULL, it means that dst got a rear multiheaded engine as first engine. We can't use that */
  1008 			if (dst == NULL) return CMD_ERROR;
  1013 			if (dst == NULL) return CMD_ERROR;
  1009 		} else {
  1014 		} else {
  1010 			/* there are more units on this train, so we will add the wagon after the next one*/
  1015 			/* there are more units on this train, so we will add the wagon after the next one*/
  1011 			dst = dst->next;
  1016 			dst = dst->next;
  1012 		}
  1017 		}
  1030 		}
  1035 		}
  1031 	}
  1036 	}
  1032 
  1037 
  1033 	if (IsMultiheaded(src) && !IsTrainEngine(src)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
  1038 	if (IsMultiheaded(src) && !IsTrainEngine(src)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
  1034 
  1039 
  1035 	// when moving all wagons, we can't have the same src_head and dst_head
  1040 	/* when moving all wagons, we can't have the same src_head and dst_head */
  1036 	if (HASBIT(p2, 0) && src_head == dst_head) return 0;
  1041 	if (HASBIT(p2, 0) && src_head == dst_head) return 0;
  1037 
  1042 
  1038 	{
  1043 	{
  1039 		int max_len = _patches.mammoth_trains ? 100 : 9;
  1044 		int max_len = _patches.mammoth_trains ? 100 : 9;
  1040 
  1045 
  1041 		// check if all vehicles in the source train are stopped inside a depot.
  1046 		/* check if all vehicles in the source train are stopped inside a depot. */
  1042 		int src_len = CheckTrainStoppedInDepot(src_head);
  1047 		int src_len = CheckTrainStoppedInDepot(src_head);
  1043 		if (src_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1048 		if (src_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1044 
  1049 
  1045 		// check the destination row if the source and destination aren't the same.
  1050 		/* check the destination row if the source and destination aren't the same. */
  1046 		if (src_head != dst_head) {
  1051 		if (src_head != dst_head) {
  1047 			int dst_len = 0;
  1052 			int dst_len = 0;
  1048 
  1053 
  1049 			if (dst_head != NULL) {
  1054 			if (dst_head != NULL) {
  1050 				// check if all vehicles in the dest train are stopped.
  1055 				/* check if all vehicles in the dest train are stopped. */
  1051 				dst_len = CheckTrainStoppedInDepot(dst_head);
  1056 				dst_len = CheckTrainStoppedInDepot(dst_head);
  1052 				if (dst_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1057 				if (dst_len < 0) return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1053 			}
  1058 			}
  1054 
  1059 
  1055 			// We are moving between rows, so only count the wagons from the source
  1060 			/* We are moving between rows, so only count the wagons from the source
  1056 			// row that are being moved.
  1061 			 * row that are being moved. */
  1057 			if (HASBIT(p2, 0)) {
  1062 			if (HASBIT(p2, 0)) {
  1058 				const Vehicle *u;
  1063 				const Vehicle *u;
  1059 				for (u = src_head; u != src && u != NULL; u = GetNextVehicle(u))
  1064 				for (u = src_head; u != src && u != NULL; u = GetNextVehicle(u))
  1060 					src_len--;
  1065 					src_len--;
  1061 			} else {
  1066 			} else {
  1062 				// If moving only one vehicle, just count that.
  1067 				/* If moving only one vehicle, just count that. */
  1063 				src_len = 1;
  1068 				src_len = 1;
  1064 			}
  1069 			}
  1065 
  1070 
  1066 			if (src_len + dst_len > max_len) {
  1071 			if (src_len + dst_len > max_len) {
  1067 				// Abort if we're adding too many wagons to a train.
  1072 				/* Abort if we're adding too many wagons to a train. */
  1068 				if (dst_head != NULL && IsFrontEngine(dst_head)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1073 				if (dst_head != NULL && IsFrontEngine(dst_head)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1069 				// Abort if we're making a train on a new row.
  1074 				/* Abort if we're making a train on a new row. */
  1070 				if (dst_head == NULL && IsTrainEngine(src)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1075 				if (dst_head == NULL && IsTrainEngine(src)) return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1071 			}
  1076 			}
  1072 		} else {
  1077 		} else {
  1073 			// Abort if we're creating a new train on an existing row.
  1078 			/* Abort if we're creating a new train on an existing row. */
  1074 			if (src_len > max_len && src == src_head && IsTrainEngine(GetNextVehicle(src_head)))
  1079 			if (src_len > max_len && src == src_head && IsTrainEngine(GetNextVehicle(src_head)))
  1075 				return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1080 				return_cmd_error(STR_8819_TRAIN_TOO_LONG);
  1076 		}
  1081 		}
  1077 	}
  1082 	}
  1078 
  1083 
  1079 	// moving a loco to a new line?, then we need to assign a unitnumber.
  1084 	/* moving a loco to a new line?, then we need to assign a unitnumber. */
  1080 	if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
  1085 	if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
  1081 		UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN);
  1086 		UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN);
  1082 		if (unit_num > _patches.max_trains)
  1087 		if (unit_num > _patches.max_trains)
  1083 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
  1088 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
  1084 
  1089 
  1102 		/* clear the ->first cache */
  1107 		/* clear the ->first cache */
  1103 		for (Vehicle *u = src_head; u != NULL; u = u->next) u->first = NULL;
  1108 		for (Vehicle *u = src_head; u != NULL; u = u->next) u->first = NULL;
  1104 		for (Vehicle *u = dst_head; u != NULL; u = u->next) u->first = NULL;
  1109 		for (Vehicle *u = dst_head; u != NULL; u = u->next) u->first = NULL;
  1105 
  1110 
  1106 		if (HASBIT(p2, 0)) {
  1111 		if (HASBIT(p2, 0)) {
  1107 			// unlink ALL wagons
  1112 			/* unlink ALL wagons */
  1108 			if (src != src_head) {
  1113 			if (src != src_head) {
  1109 				Vehicle *v = src_head;
  1114 				Vehicle *v = src_head;
  1110 				while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
  1115 				while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
  1111 				GetLastEnginePart(v)->next = NULL;
  1116 				GetLastEnginePart(v)->next = NULL;
  1112 			} else {
  1117 			} else {
  1113 				InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
  1118 				InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
  1114 				src_head = NULL;
  1119 				src_head = NULL;
  1115 			}
  1120 			}
  1116 		} else {
  1121 		} else {
  1117 			// if moving within the same chain, dont use dst_head as it may get invalidated
  1122 			/* if moving within the same chain, dont use dst_head as it may get invalidated */
  1118 			if (src_head == dst_head) dst_head = NULL;
  1123 			if (src_head == dst_head) dst_head = NULL;
  1119 			// unlink single wagon from linked list
  1124 			/* unlink single wagon from linked list */
  1120 			src_head = UnlinkWagon(src, src_head);
  1125 			src_head = UnlinkWagon(src, src_head);
  1121 			GetLastEnginePart(src)->next = NULL;
  1126 			GetLastEnginePart(src)->next = NULL;
  1122 		}
  1127 		}
  1123 
  1128 
  1124 		if (dst == NULL) {
  1129 		if (dst == NULL) {
  1125 			/* We make a new line in the depot, so we know already that we invalidate the window data */
  1130 			/* We make a new line in the depot, so we know already that we invalidate the window data */
  1126 			InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
  1131 			InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
  1127 
  1132 
  1128 			// move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4.
  1133 			/* move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4. */
  1129 			if (IsTrainEngine(src)) {
  1134 			if (IsTrainEngine(src)) {
  1130 				if (!IsFrontEngine(src)) {
  1135 				if (!IsFrontEngine(src)) {
  1131 					// setting the type to 0 also involves setting up the orders field.
  1136 					/* setting the type to 0 also involves setting up the orders field. */
  1132 					SetFrontEngine(src);
  1137 					SetFrontEngine(src);
  1133 					assert(src->orders == NULL);
  1138 					assert(src->orders == NULL);
  1134 					src->num_orders = 0;
  1139 					src->num_orders = 0;
  1135 				}
  1140 				}
  1136 			} else {
  1141 			} else {
  1137 				SetFreeWagon(src);
  1142 				SetFreeWagon(src);
  1138 			}
  1143 			}
  1139 			dst_head = src;
  1144 			dst_head = src;
  1140 		} else {
  1145 		} else {
  1141 			if (IsFrontEngine(src)) {
  1146 			if (IsFrontEngine(src)) {
  1142 				// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
  1147 				/* the vehicle was previously a loco. need to free the order list and delete vehicle windows etc. */
  1143 				DeleteWindowById(WC_VEHICLE_VIEW, src->index);
  1148 				DeleteWindowById(WC_VEHICLE_VIEW, src->index);
  1144 				DeleteVehicleOrders(src);
  1149 				DeleteVehicleOrders(src);
  1145 			}
  1150 			}
  1146 
  1151 
  1147 			if (IsFrontEngine(src) || IsFreeWagon(src)) {
  1152 			if (IsFrontEngine(src) || IsFreeWagon(src)) {
  1149 				ClearFrontEngine(src);
  1154 				ClearFrontEngine(src);
  1150 				ClearFreeWagon(src);
  1155 				ClearFreeWagon(src);
  1151 				src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
  1156 				src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
  1152 			}
  1157 			}
  1153 
  1158 
  1154 			// link in the wagon(s) in the chain.
  1159 			/* link in the wagon(s) in the chain. */
  1155 			{
  1160 			{
  1156 				Vehicle *v;
  1161 				Vehicle *v;
  1157 
  1162 
  1158 				for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v));
  1163 				for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v));
  1159 				GetLastEnginePart(v)->next = dst->next;
  1164 				GetLastEnginePart(v)->next = dst->next;
  1163 		if (src->u.rail.other_multiheaded_part != NULL) {
  1168 		if (src->u.rail.other_multiheaded_part != NULL) {
  1164 			if (src->u.rail.other_multiheaded_part == src_head) {
  1169 			if (src->u.rail.other_multiheaded_part == src_head) {
  1165 				src_head = src_head->next;
  1170 				src_head = src_head->next;
  1166 			}
  1171 			}
  1167 			AddWagonToConsist(src->u.rail.other_multiheaded_part, src);
  1172 			AddWagonToConsist(src->u.rail.other_multiheaded_part, src);
  1168 			// previous line set the front engine to the old front. We need to clear that
  1173 			/* previous line set the front engine to the old front. We need to clear that */
  1169 			src->u.rail.other_multiheaded_part->first = NULL;
  1174 			src->u.rail.other_multiheaded_part->first = NULL;
  1170 		}
  1175 		}
  1171 
  1176 
  1172 		if (HASBIT(p2, 0) && src_head != NULL && src_head != src) {
  1177 		if (HASBIT(p2, 0) && src_head != NULL && src_head != src) {
  1173 			/* if we stole a rear multiheaded engine, we better give it back to the front end */
  1178 			/* if we stole a rear multiheaded engine, we better give it back to the front end */
  1182 					engine = NULL;
  1187 					engine = NULL;
  1183 				}
  1188 				}
  1184 			}
  1189 			}
  1185 			if (engine != NULL && engine->u.rail.other_multiheaded_part != NULL) {
  1190 			if (engine != NULL && engine->u.rail.other_multiheaded_part != NULL) {
  1186 				AddWagonToConsist(engine->u.rail.other_multiheaded_part, engine);
  1191 				AddWagonToConsist(engine->u.rail.other_multiheaded_part, engine);
  1187 				// previous line set the front engine to the old front. We need to clear that
  1192 				/* previous line set the front engine to the old front. We need to clear that */
  1188 				engine->u.rail.other_multiheaded_part->first = NULL;
  1193 				engine->u.rail.other_multiheaded_part->first = NULL;
  1189 			}
  1194 			}
  1190 		}
  1195 		}
  1191 
  1196 
  1192 		/* If there is an engine behind first_engine we moved away, it should become new first_engine
  1197 		/* If there is an engine behind first_engine we moved away, it should become new first_engine
  1231 	return 0;
  1236 	return 0;
  1232 }
  1237 }
  1233 
  1238 
  1234 /** Start/Stop a train.
  1239 /** Start/Stop a train.
  1235  * @param tile unused
  1240  * @param tile unused
       
  1241  * @param flags type of operation
  1236  * @param p1 train to start/stop
  1242  * @param p1 train to start/stop
  1237  * @param p2 unused
  1243  * @param p2 unused
  1238  */
  1244  */
  1239 int32 CmdStartStopTrain(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1245 int32 CmdStartStopTrain(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1240 {
  1246 {
  1267 	return 0;
  1273 	return 0;
  1268 }
  1274 }
  1269 
  1275 
  1270 /** Sell a (single) train wagon/engine.
  1276 /** Sell a (single) train wagon/engine.
  1271  * @param tile unused
  1277  * @param tile unused
       
  1278  * @param flags type of operation
  1272  * @param p1 the wagon/engine index
  1279  * @param p1 the wagon/engine index
  1273  * @param p2 the selling mode
  1280  * @param p2 the selling mode
  1274  * - p2 = 0: only sell the single dragged wagon/engine (and any belonging rear-engines)
  1281  * - p2 = 0: only sell the single dragged wagon/engine (and any belonging rear-engines)
  1275  * - p2 = 1: sell the vehicle and all vehicles following it in the chain
  1282  * - p2 = 1: sell the vehicle and all vehicles following it in the chain
  1276              if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
  1283              if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
  1288 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
  1295 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
  1289 
  1296 
  1290 	while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v);
  1297 	while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v);
  1291 	Vehicle *first = GetFirstVehicleInChain(v);
  1298 	Vehicle *first = GetFirstVehicleInChain(v);
  1292 
  1299 
  1293 	// make sure the vehicle is stopped in the depot
  1300 	/* make sure the vehicle is stopped in the depot */
  1294 	if (CheckTrainStoppedInDepot(first) < 0) {
  1301 	if (CheckTrainStoppedInDepot(first) < 0) {
  1295 		return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1302 		return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1296 	}
  1303 	}
  1297 
  1304 
  1298 	if (IsMultiheaded(v) && !IsTrainEngine(v)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
  1305 	if (IsMultiheaded(v) && !IsTrainEngine(v)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
  1594 	Vehicle *base = v;
  1601 	Vehicle *base = v;
  1595 	Vehicle *first = base->next;
  1602 	Vehicle *first = base->next;
  1596 	uint length = CountVehiclesInChain(v);
  1603 	uint length = CountVehiclesInChain(v);
  1597 
  1604 
  1598 	while (length > 2) {
  1605 	while (length > 2) {
  1599 		// find pairwise matching wagon
  1606 		/* find pairwise matching wagon
  1600 		// start<>end, start+1<>end-1, ...
  1607 		 * start<>end, start+1<>end-1, ... */
  1601 		Vehicle *last = first;
  1608 		Vehicle *last = first;
  1602 		for (uint i = length - 3; i > 0; i--) last = last->next;
  1609 		for (uint i = length - 3; i > 0; i--) last = last->next;
  1603 
  1610 
  1604 		int differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length;
  1611 		int differential = last->u.rail.cached_veh_length - base->u.rail.cached_veh_length;
  1605 		if (before) differential *= -1;
  1612 		if (before) differential *= -1;
  1606 
  1613 
  1607 		if (differential > 0) {
  1614 		if (differential > 0) {
  1608 			// disconnect last car to make sure only this subset moves
  1615 			/* disconnect last car to make sure only this subset moves */
  1609 			Vehicle *tempnext = last->next;
  1616 			Vehicle *tempnext = last->next;
  1610 			last->next = NULL;
  1617 			last->next = NULL;
  1611 
  1618 
  1612 			for (int i = 0; i < differential; i++) TrainController(first, false);
  1619 			for (int i = 0; i < differential; i++) TrainController(first, false);
  1613 
  1620 
  1641 
  1648 
  1642 		/* Check if the train left a rail/road-crossing */
  1649 		/* Check if the train left a rail/road-crossing */
  1643 		DisableTrainCrossing(tile);
  1650 		DisableTrainCrossing(tile);
  1644 	}
  1651 	}
  1645 
  1652 
  1646 	// count number of vehicles
  1653 	/* count number of vehicles */
  1647 	int r = -1;
  1654 	int r = -1;
  1648 	const Vehicle *u = v;
  1655 	const Vehicle *u = v;
  1649 	do r++; while ( (u = u->next) != NULL );
  1656 	do r++; while ( (u = u->next) != NULL );
  1650 
  1657 
  1651 	AdvanceWagons(v, true);
  1658 	AdvanceWagons(v, true);
  1665 	CLRBIT(v->u.rail.flags, VRF_REVERSING);
  1672 	CLRBIT(v->u.rail.flags, VRF_REVERSING);
  1666 }
  1673 }
  1667 
  1674 
  1668 /** Reverse train.
  1675 /** Reverse train.
  1669  * @param tile unused
  1676  * @param tile unused
       
  1677  * @param flags type of operation
  1670  * @param p1 train to reverse
  1678  * @param p1 train to reverse
  1671  * @param p2 if true, reverse a unit in a train (needs to be in a depot)
  1679  * @param p2 if true, reverse a unit in a train (needs to be in a depot)
  1672  */
  1680  */
  1673 int32 CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1681 int32 CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1674 {
  1682 {
  1677 	Vehicle *v = GetVehicle(p1);
  1685 	Vehicle *v = GetVehicle(p1);
  1678 
  1686 
  1679 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1687 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1680 
  1688 
  1681 	if (p2) {
  1689 	if (p2) {
  1682 		// turn a single unit around
  1690 		/* turn a single unit around */
  1683 
  1691 
  1684 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1692 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1685 			return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT);
  1693 			return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT);
  1686 		}
  1694 		}
  1687 
  1695 
  1688 		Vehicle *front = GetFirstVehicleInChain(v);
  1696 		Vehicle *front = GetFirstVehicleInChain(v);
  1689 		// make sure the vehicle is stopped in the depot
  1697 		/* make sure the vehicle is stopped in the depot */
  1690 		if (CheckTrainStoppedInDepot(front) < 0) {
  1698 		if (CheckTrainStoppedInDepot(front) < 0) {
  1691 			return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1699 			return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED);
  1692 		}
  1700 		}
  1693 
  1701 
  1694 		if (flags & DC_EXEC) {
  1702 		if (flags & DC_EXEC) {
  1695 			TOGGLEBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION);
  1703 			TOGGLEBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION);
  1696 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1704 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1697 			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1705 			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1698 		}
  1706 		}
  1699 	} else {
  1707 	} else {
  1700 		//turn the whole train around
  1708 		/*turn the whole train around */
  1701 		if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) return CMD_ERROR;
  1709 		if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) return CMD_ERROR;
  1702 
  1710 
  1703 		if (flags & DC_EXEC) {
  1711 		if (flags & DC_EXEC) {
  1704 			if (_patches.realistic_acceleration && v->cur_speed != 0) {
  1712 			if (_patches.realistic_acceleration && v->cur_speed != 0) {
  1705 				TOGGLEBIT(v->u.rail.flags, VRF_REVERSING);
  1713 				TOGGLEBIT(v->u.rail.flags, VRF_REVERSING);
  1713 	return 0;
  1721 	return 0;
  1714 }
  1722 }
  1715 
  1723 
  1716 /** Force a train through a red signal
  1724 /** Force a train through a red signal
  1717  * @param tile unused
  1725  * @param tile unused
       
  1726  * @param flags type of operation
  1718  * @param p1 train to ignore the red signal
  1727  * @param p1 train to ignore the red signal
  1719  * @param p2 unused
  1728  * @param p2 unused
  1720  */
  1729  */
  1721 int32 CmdForceTrainProceed(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1730 int32 CmdForceTrainProceed(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1722 {
  1731 {
  1731 	return 0;
  1740 	return 0;
  1732 }
  1741 }
  1733 
  1742 
  1734 /** Refits a train to the specified cargo type.
  1743 /** Refits a train to the specified cargo type.
  1735  * @param tile unused
  1744  * @param tile unused
       
  1745  * @param flags type of operation
  1736  * @param p1 vehicle ID of the train to refit
  1746  * @param p1 vehicle ID of the train to refit
  1737  * param p2 various bitstuffed elements
  1747  * param p2 various bitstuffed elements
  1738  * - p2 = (bit 0-7) - the new cargo type to refit to
  1748  * - p2 = (bit 0-7) - the new cargo type to refit to
  1739  * - p2 = (bit 8-15) - the new cargo subtype to refit to
  1749  * - p2 = (bit 8-15) - the new cargo subtype to refit to
  1740  */
  1750  */
  1852 	}
  1862 	}
  1853 
  1863 
  1854 	return false;
  1864 	return false;
  1855 }
  1865 }
  1856 
  1866 
  1857 // returns the tile of a depot to goto to. The given vehicle must not be
  1867 /** returns the tile of a depot to goto to. The given vehicle must not be
  1858 // crashed!
  1868  * crashed! */
  1859 static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
  1869 static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
  1860 {
  1870 {
  1861 	assert(!(v->vehstatus & VS_CRASHED));
  1871 	assert(!(v->vehstatus & VS_CRASHED));
  1862 
  1872 
  1863 	TrainFindDepotData tfdd;
  1873 	TrainFindDepotData tfdd;
  1891 			 * is removed. */
  1901 			 * is removed. */
  1892 			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  1902 			tfdd.best_length = ftd.best_path_dist / NPF_TILE_LENGTH;
  1893 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
  1903 			if (NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE)) tfdd.reverse = true;
  1894 		}
  1904 		}
  1895 	} else {
  1905 	} else {
  1896 		// search in the forward direction first.
  1906 		/* search in the forward direction first. */
  1897 		DiagDirection i = DirToDiagDir(v->direction);
  1907 		DiagDirection i = DirToDiagDir(v->direction);
  1898 		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) {
  1908 		if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) {
  1899 			i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT);
  1909 			i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT);
  1900 		}
  1910 		}
  1901 		NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1911 		NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1902 		if (tfdd.best_length == (uint)-1){
  1912 		if (tfdd.best_length == (uint)-1){
  1903 			tfdd.reverse = true;
  1913 			tfdd.reverse = true;
  1904 			// search in backwards direction
  1914 			/* search in backwards direction */
  1905 			i = ReverseDiagDir(DirToDiagDir(v->direction));
  1915 			i = ReverseDiagDir(DirToDiagDir(v->direction));
  1906 			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) {
  1916 			if (!(v->direction & 1) && v->u.rail.track != _state_dir_table[i]) {
  1907 				i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT);
  1917 				i = ChangeDiagDir(i, DIAGDIRDIFF_90LEFT);
  1908 			}
  1918 			}
  1909 			NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1919 			NewTrainPathfind(tile, 0, v->u.rail.compatible_railtypes, i, (NTPEnumProc*)NtpCallbFindDepot, &tfdd);
  1913 	return tfdd;
  1923 	return tfdd;
  1914 }
  1924 }
  1915 
  1925 
  1916 /** Send a train to a depot
  1926 /** Send a train to a depot
  1917  * @param tile unused
  1927  * @param tile unused
       
  1928  * @param flags type of operation
  1918  * @param p1 train to send to the depot
  1929  * @param p1 train to send to the depot
  1919  * @param p2 various bitmasked elements
  1930  * @param p2 various bitmasked elements
  1920  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
  1931  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
  1921  * - p2 bit 8-10 - VLW flag (for mass goto depot)
  1932  * - p2 bit 8-10 - VLW flag (for mass goto depot)
  1922  */
  1933  */
  2008 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  2019 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  2009 		int effect_offset = GB(v->u.rail.cached_vis_effect, 0, 4) - 8;
  2020 		int effect_offset = GB(v->u.rail.cached_vis_effect, 0, 4) - 8;
  2010 		byte effect_type = GB(v->u.rail.cached_vis_effect, 4, 2);
  2021 		byte effect_type = GB(v->u.rail.cached_vis_effect, 4, 2);
  2011 		bool disable_effect = HASBIT(v->u.rail.cached_vis_effect, 6);
  2022 		bool disable_effect = HASBIT(v->u.rail.cached_vis_effect, 6);
  2012 
  2023 
  2013 		// no smoke?
  2024 		/* no smoke? */
  2014 		if ((rvi->railveh_type == RAILVEH_WAGON && effect_type == 0) ||
  2025 		if ((rvi->railveh_type == RAILVEH_WAGON && effect_type == 0) ||
  2015 				disable_effect ||
  2026 				disable_effect ||
  2016 				rvi->railtype > RAILTYPE_ELECTRIC ||
  2027 				rvi->railtype > RAILTYPE_ELECTRIC ||
  2017 				v->vehstatus & VS_HIDDEN) {
  2028 				v->vehstatus & VS_HIDDEN) {
  2018 			continue;
  2029 			continue;
  2019 		}
  2030 		}
  2020 
  2031 
  2021 		// No smoke in depots or tunnels
  2032 		/* No smoke in depots or tunnels */
  2022 		if (IsTileDepotType(v->tile, TRANSPORT_RAIL) || IsTunnelTile(v->tile)) continue;
  2033 		if (IsTileDepotType(v->tile, TRANSPORT_RAIL) || IsTunnelTile(v->tile)) continue;
  2023 
  2034 
  2024 		// No sparks for electric vehicles on nonelectrified tracks
  2035 		/* No sparks for electric vehicles on nonelectrified tracks */
  2025 		if (!HasPowerOnRail(v->u.rail.railtype, GetTileRailType(v->tile))) continue;
  2036 		if (!HasPowerOnRail(v->u.rail.railtype, GetTileRailType(v->tile))) continue;
  2026 
  2037 
  2027 		if (effect_type == 0) {
  2038 		if (effect_type == 0) {
  2028 			// Use default effect type for engine class.
  2039 			/* Use default effect type for engine class. */
  2029 			effect_type = rvi->engclass;
  2040 			effect_type = rvi->engclass;
  2030 		} else {
  2041 		} else {
  2031 			effect_type--;
  2042 			effect_type--;
  2032 		}
  2043 		}
  2033 
  2044 
  2039 			y = -y;
  2050 			y = -y;
  2040 		}
  2051 		}
  2041 
  2052 
  2042 		switch (effect_type) {
  2053 		switch (effect_type) {
  2043 		case 0:
  2054 		case 0:
  2044 			// steam smoke.
  2055 			/* steam smoke. */
  2045 			if (GB(v->tick_counter, 0, 4) == 0) {
  2056 			if (GB(v->tick_counter, 0, 4) == 0) {
  2046 				CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE);
  2057 				CreateEffectVehicleRel(v, x, y, 10, EV_STEAM_SMOKE);
  2047 				sound = true;
  2058 				sound = true;
  2048 			}
  2059 			}
  2049 			break;
  2060 			break;
  2050 
  2061 
  2051 		case 1:
  2062 		case 1:
  2052 			// diesel smoke
  2063 			/* diesel smoke */
  2053 			if (u->cur_speed <= 40 && CHANCE16(15, 128)) {
  2064 			if (u->cur_speed <= 40 && CHANCE16(15, 128)) {
  2054 				CreateEffectVehicleRel(v, 0, 0, 10, EV_DIESEL_SMOKE);
  2065 				CreateEffectVehicleRel(v, 0, 0, 10, EV_DIESEL_SMOKE);
  2055 				sound = true;
  2066 				sound = true;
  2056 			}
  2067 			}
  2057 			break;
  2068 			break;
  2058 
  2069 
  2059 		case 2:
  2070 		case 2:
  2060 			// blue spark
  2071 			/* blue spark */
  2061 			if (GB(v->tick_counter, 0, 2) == 0 && CHANCE16(1, 45)) {
  2072 			if (GB(v->tick_counter, 0, 2) == 0 && CHANCE16(1, 45)) {
  2062 				CreateEffectVehicleRel(v, 0, 0, 10, EV_ELECTRIC_SPARK);
  2073 				CreateEffectVehicleRel(v, 0, 0, 10, EV_ELECTRIC_SPARK);
  2063 				sound = true;
  2074 				sound = true;
  2064 			}
  2075 			}
  2065 			break;
  2076 			break;
  2092 	}
  2103 	}
  2093 }
  2104 }
  2094 
  2105 
  2095 static bool CheckTrainStayInDepot(Vehicle *v)
  2106 static bool CheckTrainStayInDepot(Vehicle *v)
  2096 {
  2107 {
  2097 	// bail out if not all wagons are in the same depot or not in a depot at all
  2108 	/* bail out if not all wagons are in the same depot or not in a depot at all */
  2098 	for (const Vehicle *u = v; u != NULL; u = u->next) {
  2109 	for (const Vehicle *u = v; u != NULL; u = u->next) {
  2099 		if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
  2110 		if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
  2100 	}
  2111 	}
  2101 
  2112 
  2102 	// if the train got no power, then keep it in the depot
  2113 	/* if the train got no power, then keep it in the depot */
  2103 	if (v->u.rail.cached_power == 0) {
  2114 	if (v->u.rail.cached_power == 0) {
  2104 		v->vehstatus |= VS_STOPPED;
  2115 		v->vehstatus |= VS_STOPPED;
  2105 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  2116 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  2106 		return true;
  2117 		return true;
  2107 	}
  2118 	}
  2149 	TrackdirByte best_track;
  2160 	TrackdirByte best_track;
  2150 };
  2161 };
  2151 
  2162 
  2152 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2163 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2153 {
  2164 {
  2154 	// heading for nowhere?
  2165 	/* heading for nowhere? */
  2155 	if (ttfd->dest_coords == 0) return false;
  2166 	if (ttfd->dest_coords == 0) return false;
  2156 
  2167 
  2157 	// did we reach the final station?
  2168 	/* did we reach the final station? */
  2158 	if ((ttfd->station_index == INVALID_STATION && tile == ttfd->dest_coords) || (
  2169 	if ((ttfd->station_index == INVALID_STATION && tile == ttfd->dest_coords) || (
  2159 				IsTileType(tile, MP_STATION) &&
  2170 				IsTileType(tile, MP_STATION) &&
  2160 				IsRailwayStation(tile) &&
  2171 				IsRailwayStation(tile) &&
  2161 				GetStationIndex(tile) == ttfd->station_index
  2172 				GetStationIndex(tile) == ttfd->station_index
  2162 			)) {
  2173 			)) {
  2163 		/* We do not check for dest_coords if we have a station_index,
  2174 		/* We do not check for dest_coords if we have a station_index,
  2164 		 * because in that case the dest_coords are just an
  2175 		 * because in that case the dest_coords are just an
  2165 		 * approximation of where the station is */
  2176 		 * approximation of where the station is */
  2166 		// found station
  2177 
       
  2178 		/* found station */
  2167 		ttfd->best_track = track;
  2179 		ttfd->best_track = track;
  2168 		ttfd->best_bird_dist = 0;
  2180 		ttfd->best_bird_dist = 0;
  2169 		return true;
  2181 		return true;
  2170 	} else {
  2182 	} else {
  2171 		// didn't find station, keep track of the best path so far.
  2183 		/* didn't find station, keep track of the best path so far. */
  2172 		uint dist = DistanceManhattan(tile, ttfd->dest_coords);
  2184 		uint dist = DistanceManhattan(tile, ttfd->dest_coords);
  2173 		if (dist < ttfd->best_bird_dist) {
  2185 		if (dist < ttfd->best_bird_dist) {
  2174 			ttfd->best_bird_dist = dist;
  2186 			ttfd->best_bird_dist = dist;
  2175 			ttfd->best_track = track;
  2187 			ttfd->best_track = track;
  2176 		}
  2188 		}
  2203 	0x05200520,
  2215 	0x05200520,
  2204 	0x2A002A00,
  2216 	0x2A002A00,
  2205 };
  2217 };
  2206 
  2218 
  2207 static const byte _search_directions[6][4] = {
  2219 static const byte _search_directions[6][4] = {
  2208 	{ 0, 9, 2, 9 }, // track 1
  2220 	{ 0, 9, 2, 9 }, ///< track 1
  2209 	{ 9, 1, 9, 3 }, // track 2
  2221 	{ 9, 1, 9, 3 }, ///< track 2
  2210 	{ 9, 0, 3, 9 }, // track upper
  2222 	{ 9, 0, 3, 9 }, ///< track upper
  2211 	{ 1, 9, 9, 2 }, // track lower
  2223 	{ 1, 9, 9, 2 }, ///< track lower
  2212 	{ 3, 2, 9, 9 }, // track left
  2224 	{ 3, 2, 9, 9 }, ///< track left
  2213 	{ 9, 9, 1, 0 }, // track right
  2225 	{ 9, 9, 1, 0 }, ///< track right
  2214 };
  2226 };
  2215 
  2227 
  2216 static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0};
  2228 static const byte _pick_track_table[6] = {1, 3, 2, 2, 0, 0};
  2217 
  2229 
  2218 /* choose a track */
  2230 /* choose a track */
  2219 static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
  2231 static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
  2220 {
  2232 {
  2221 	Track best_track;
  2233 	Track best_track;
  2222 	// pathfinders are able to tell that route was only 'guessed'
  2234 	/* pathfinders are able to tell that route was only 'guessed' */
  2223 	bool path_not_found = false;
  2235 	bool path_not_found = false;
  2224 
  2236 
  2225 #ifdef PF_BENCHMARK
  2237 #ifdef PF_BENCHMARK
  2226 	TIC()
  2238 	TIC()
  2227 #endif
  2239 #endif
  2248 		assert(trackdir != 0xff);
  2260 		assert(trackdir != 0xff);
  2249 
  2261 
  2250 		NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
  2262 		NPFFoundTargetData ftd = NPFRouteToStationOrTile(tile - TileOffsByDiagDir(enterdir), trackdir, &fstd, TRANSPORT_RAIL, v->owner, v->u.rail.compatible_railtypes);
  2251 
  2263 
  2252 		if (ftd.best_trackdir == 0xff) {
  2264 		if (ftd.best_trackdir == 0xff) {
  2253 			/* We are already at our target. Just do something */
  2265 			/* We are already at our target. Just do something
  2254 			//TODO: maybe display error?
  2266 			 * @todo maybe display error?
  2255 			//TODO: go straight ahead if possible?
  2267 			 * @todo: go straight ahead if possible? */
  2256 			best_track = FindFirstTrack(tracks);
  2268 			best_track = FindFirstTrack(tracks);
  2257 		} else {
  2269 		} else {
  2258 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  2270 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
  2259 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  2271 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
  2260 			we did not find our target, but ftd.best_trackdir contains the direction leading
  2272 			we did not find our target, but ftd.best_trackdir contains the direction leading
  2278 		fd.best_track = INVALID_TRACKDIR;
  2290 		fd.best_track = INVALID_TRACKDIR;
  2279 
  2291 
  2280 		NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
  2292 		NewTrainPathfind(tile - TileOffsByDiagDir(enterdir), v->dest_tile,
  2281 			v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2293 			v->u.rail.compatible_railtypes, enterdir, (NTPEnumProc*)NtpCallbFindStation, &fd);
  2282 
  2294 
  2283 		// check whether the path was found or only 'guessed'
  2295 		/* check whether the path was found or only 'guessed' */
  2284 		if (fd.best_bird_dist != 0) path_not_found = true;
  2296 		if (fd.best_bird_dist != 0) path_not_found = true;
  2285 
  2297 
  2286 		if (fd.best_track == 0xff) {
  2298 		if (fd.best_track == 0xff) {
  2287 			// blaha
  2299 			/* blaha */
  2288 			best_track = FindFirstTrack(tracks);
  2300 			best_track = FindFirstTrack(tracks);
  2289 		} else {
  2301 		} else {
  2290 			best_track = TrackdirToTrack(fd.best_track);
  2302 			best_track = TrackdirToTrack(fd.best_track);
  2291 		}
  2303 		}
  2292 
  2304 
  2293 		int time = NpfEndInterval(perf);
  2305 		int time = NpfEndInterval(perf);
  2294 		DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
  2306 		DEBUG(yapf, 4, "[NTPT] %d us - %d rounds - %d open - %d closed -- ", time, 0, 0, 0);
  2295 	}
  2307 	}
  2296 	// handle "path not found" state
  2308 	/* handle "path not found" state */
  2297 	if (path_not_found) {
  2309 	if (path_not_found) {
  2298 		// PF didn't find the route
  2310 		/* PF didn't find the route */
  2299 		if (!HASBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2311 		if (!HASBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2300 			// it is first time the problem occurred, set the "path not found" flag
  2312 			/* it is first time the problem occurred, set the "path not found" flag */
  2301 			SETBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
  2313 			SETBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
  2302 			// and notify user about the event
  2314 			/* and notify user about the event */
  2303 			if (_patches.lost_train_warn && v->owner == _local_player) {
  2315 			if (_patches.lost_train_warn && v->owner == _local_player) {
  2304 				SetDParam(0, v->unitnumber);
  2316 				SetDParam(0, v->unitnumber);
  2305 				AddNewsItem(
  2317 				AddNewsItem(
  2306 					STR_TRAIN_IS_LOST,
  2318 					STR_TRAIN_IS_LOST,
  2307 					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
  2319 					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
  2308 					v->index,
  2320 					v->index,
  2309 					0);
  2321 					0);
  2310 			}
  2322 			}
  2311 		}
  2323 		}
  2312 	} else {
  2324 	} else {
  2313 		// route found, is the train marked with "path not found" flag?
  2325 		/* route found, is the train marked with "path not found" flag? */
  2314 		if (HASBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2326 		if (HASBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION)) {
  2315 			// clear the flag as the PF's problem was solved
  2327 			/* clear the flag as the PF's problem was solved */
  2316 			CLRBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
  2328 			CLRBIT(v->u.rail.flags, VRF_NO_PATH_TO_DESTINATION);
  2317 			// can we also delete the "News" item somehow?
  2329 			/* can we also delete the "News" item somehow? */
  2318 		}
  2330 		}
  2319 	}
  2331 	}
  2320 
  2332 
  2321 #ifdef PF_BENCHMARK
  2333 #ifdef PF_BENCHMARK
  2322 	TOC("PF time = ", 1)
  2334 	TOC("PF time = ", 1)
  2438 			return false;
  2450 			return false;
  2439 
  2451 
  2440 		default: break;
  2452 		default: break;
  2441 	}
  2453 	}
  2442 
  2454 
  2443 	// check if we've reached the waypoint?
  2455 	/* check if we've reached the waypoint? */
  2444 	bool at_waypoint = false;
  2456 	bool at_waypoint = false;
  2445 	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
  2457 	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
  2446 		v->cur_order_index++;
  2458 		v->cur_order_index++;
  2447 		at_waypoint = true;
  2459 		at_waypoint = true;
  2448 	}
  2460 	}
  2449 
  2461 
  2450 	// check if we've reached a non-stop station while TTDPatch nonstop is enabled..
  2462 	/* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
  2451 	if (_patches.new_nonstop &&
  2463 	if (_patches.new_nonstop &&
  2452 			v->current_order.flags & OF_NON_STOP &&
  2464 			v->current_order.flags & OF_NON_STOP &&
  2453 			IsTileType(v->tile, MP_STATION) &&
  2465 			IsTileType(v->tile, MP_STATION) &&
  2454 			v->current_order.dest == GetStationIndex(v->tile)) {
  2466 			v->current_order.dest == GetStationIndex(v->tile)) {
  2455 		v->cur_order_index++;
  2467 		v->cur_order_index++;
  2456 	}
  2468 	}
  2457 
  2469 
  2458 	// Get the current order
  2470 	/* Get the current order */
  2459 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
  2471 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
  2460 
  2472 
  2461 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2473 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2462 
  2474 
  2463 	// If no order, do nothing.
  2475 	/* If no order, do nothing. */
  2464 	if (order == NULL) {
  2476 	if (order == NULL) {
  2465 		v->current_order.Free();
  2477 		v->current_order.Free();
  2466 		v->dest_tile = 0;
  2478 		v->dest_tile = 0;
  2467 		return false;
  2479 		return false;
  2468 	}
  2480 	}
  2469 
  2481 
  2470 	// If it is unchanged, keep it.
  2482 	/* If it is unchanged, keep it. */
  2471 	if (order->type  == v->current_order.type &&
  2483 	if (order->type  == v->current_order.type &&
  2472 			order->flags == v->current_order.flags &&
  2484 			order->flags == v->current_order.flags &&
  2473 			order->dest  == v->current_order.dest)
  2485 			order->dest  == v->current_order.dest)
  2474 		return false;
  2486 		return false;
  2475 
  2487 
  2476 	// Otherwise set it, and determine the destination tile.
  2488 	/* Otherwise set it, and determine the destination tile. */
  2477 	v->current_order = *order;
  2489 	v->current_order = *order;
  2478 
  2490 
  2479 	v->dest_tile = 0;
  2491 	v->dest_tile = 0;
  2480 
  2492 
  2481 	InvalidateVehicleOrder(v);
  2493 	InvalidateVehicleOrder(v);
  2514 {
  2526 {
  2515 	switch (v->current_order.type) {
  2527 	switch (v->current_order.type) {
  2516 		case OT_LOADING: {
  2528 		case OT_LOADING: {
  2517 			if (mode) return;
  2529 			if (mode) return;
  2518 
  2530 
  2519 			// don't mark the train as lost if we're loading on the final station.
  2531 			/* don't mark the train as lost if we're loading on the final station. */
  2520 			if (v->current_order.flags & OF_NON_STOP) {
  2532 			if (v->current_order.flags & OF_NON_STOP) {
  2521 				v->u.rail.days_since_order_progr = 0;
  2533 				v->u.rail.days_since_order_progr = 0;
  2522 			}
  2534 			}
  2523 
  2535 
  2524 			if (--v->load_unload_time_rem) return;
  2536 			if (--v->load_unload_time_rem) return;
  2525 
  2537 
  2526 			if (CanFillVehicle(v) && (
  2538 			if (CanFillVehicle(v) && (
  2527 						v->current_order.flags & OF_FULL_LOAD ||
  2539 						v->current_order.flags & OF_FULL_LOAD ||
  2528 						(_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED))
  2540 						(_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED))
  2529 					)) {
  2541 					)) {
  2530 				v->u.rail.days_since_order_progr = 0; /* Prevent a train lost message for full loading trains */
  2542 				v->u.rail.days_since_order_progr = 0; // Prevent a train lost message for full loading trains
  2531 				SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC);
  2543 				SET_EXPENSES_TYPE(EXPENSES_TRAIN_INC);
  2532 				if (LoadUnloadVehicle(v, false)) {
  2544 				if (LoadUnloadVehicle(v, false)) {
  2533 					InvalidateWindow(WC_TRAINS_LIST, v->owner);
  2545 					InvalidateWindow(WC_TRAINS_LIST, v->owner);
  2534 					MarkTrainDirty(v);
  2546 					MarkTrainDirty(v);
  2535 
  2547 
  2536 					// need to update acceleration and cached values since the goods on the train changed.
  2548 					/* need to update acceleration and cached values since the goods on the train changed. */
  2537 					TrainCargoChanged(v);
  2549 					TrainCargoChanged(v);
  2538 					UpdateTrainAcceleration(v);
  2550 					UpdateTrainAcceleration(v);
  2539 				}
  2551 				}
  2540 				return;
  2552 				return;
  2541 			}
  2553 			}
  2543 			TrainPlayLeaveStationSound(v);
  2555 			TrainPlayLeaveStationSound(v);
  2544 
  2556 
  2545 			Order b = v->current_order;
  2557 			Order b = v->current_order;
  2546 			v->LeaveStation();
  2558 			v->LeaveStation();
  2547 
  2559 
  2548 			// If this was not the final order, don't remove it from the list.
  2560 			/* If this was not the final order, don't remove it from the list. */
  2549 			if (!(b.flags & OF_NON_STOP)) return;
  2561 			if (!(b.flags & OF_NON_STOP)) return;
  2550 			break;
  2562 			break;
  2551 		}
  2563 		}
  2552 
  2564 
  2553 		case OT_DUMMY: break;
  2565 		case OT_DUMMY: break;
  2612 			v->index,
  2624 			v->index,
  2613 			0
  2625 			0
  2614 		);
  2626 		);
  2615 	}
  2627 	}
  2616 
  2628 
  2617 	// Did we reach the final destination?
  2629 	/* Did we reach the final destination? */
  2618 	if (v->current_order.type == OT_GOTO_STATION &&
  2630 	if (v->current_order.type == OT_GOTO_STATION &&
  2619 			v->current_order.dest == station) {
  2631 			v->current_order.dest == station) {
  2620 		// Yeah, keep the load/unload flags
  2632 		/* Yeah, keep the load/unload flags
  2621 		// Non Stop now means if the order should be increased.
  2633 		 * Non Stop now means if the order should be increased. */
  2622 		v->BeginLoading();
  2634 		v->BeginLoading();
  2623 		v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER;
  2635 		v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER;
  2624 		v->current_order.flags |= OF_NON_STOP;
  2636 		v->current_order.flags |= OF_NON_STOP;
  2625 	} else {
  2637 	} else {
  2626 		// No, just do a simple load
  2638 		/* No, just do a simple load */
  2627 		v->BeginLoading();
  2639 		v->BeginLoading();
  2628 		v->current_order.flags = 0;
  2640 		v->current_order.flags = 0;
  2629 	}
  2641 	}
  2630 	v->current_order.dest = 0;
  2642 	v->current_order.dest = 0;
  2631 
  2643 
  2639 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2651 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2640 }
  2652 }
  2641 
  2653 
  2642 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2654 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2643 {
  2655 {
  2644 	// need this hint so it returns the right z coordinate on bridges.
  2656 	/* need this hint so it returns the right z coordinate on bridges. */
  2645 	byte new_z = GetSlopeZ(v->x_pos, v->y_pos);
  2657 	byte new_z = GetSlopeZ(v->x_pos, v->y_pos);
  2646 
  2658 
  2647 	byte old_z = v->z_pos;
  2659 	byte old_z = v->z_pos;
  2648 	v->z_pos = new_z;
  2660 	v->z_pos = new_z;
  2649 
  2661 
  2652 		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
  2664 		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
  2653 
  2665 
  2654 		if (new_z != old_z) {
  2666 		if (new_z != old_z) {
  2655 			TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
  2667 			TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
  2656 
  2668 
  2657 			// XXX workaround, whole UP/DOWN detection needs overhaul
  2669 			/* XXX workaround, whole UP/DOWN detection needs overhaul */
  2658 			if (!IsTunnelTile(tile)) {
  2670 			if (!IsTunnelTile(tile)) {
  2659 				SETBIT(v->u.rail.flags, (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
  2671 				SETBIT(v->u.rail.flags, (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
  2660 			}
  2672 			}
  2661 		}
  2673 		}
  2662 	}
  2674 	}
  2725 	byte z_down; // fraction to remove when moving down
  2737 	byte z_down; // fraction to remove when moving down
  2726 };
  2738 };
  2727 
  2739 
  2728 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2740 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2729 	// normal accel
  2741 	// normal accel
  2730 	{256 / 4, 256 / 2, 256 / 4, 2}, // normal
  2742 	{256 / 4, 256 / 2, 256 / 4, 2}, ///< normal
  2731 	{256 / 4, 256 / 2, 256 / 4, 2}, // electrified
  2743 	{256 / 4, 256 / 2, 256 / 4, 2}, ///< electrified
  2732 	{256 / 4, 256 / 2, 256 / 4, 2}, // monorail
  2744 	{256 / 4, 256 / 2, 256 / 4, 2}, ///< monorail
  2733 	{0,       256 / 2, 256 / 4, 2}, // maglev
  2745 	{0,       256 / 2, 256 / 4, 2}, ///< maglev
  2734 };
  2746 };
  2735 
  2747 
  2736 /* Modify the speed of the vehicle due to a turn */
  2748 /** Modify the speed of the vehicle due to a turn */
  2737 static void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
  2749 static void AffectSpeedByDirChange(Vehicle* v, Direction new_dir)
  2738 {
  2750 {
  2739 	if (_patches.realistic_acceleration) return;
  2751 	if (_patches.realistic_acceleration) return;
  2740 
  2752 
  2741 	DirDiff diff = DirDifference(v->direction, new_dir);
  2753 	DirDiff diff = DirDifference(v->direction, new_dir);
  2743 
  2755 
  2744 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2756 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2745 	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
  2757 	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
  2746 }
  2758 }
  2747 
  2759 
  2748 /* Modify the speed of the vehicle due to a change in altitude */
  2760 /** Modify the speed of the vehicle due to a change in altitude */
  2749 static void AffectSpeedByZChange(Vehicle *v, byte old_z)
  2761 static void AffectSpeedByZChange(Vehicle *v, byte old_z)
  2750 {
  2762 {
  2751 	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
  2763 	if (old_z == v->z_pos || _patches.realistic_acceleration) return;
  2752 
  2764 
  2753 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2765 	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
  2818 		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo_count;
  2830 		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo_count;
  2819 	END_ENUM_WAGONS(v)
  2831 	END_ENUM_WAGONS(v)
  2820 	return num;
  2832 	return num;
  2821 }
  2833 }
  2822 
  2834 
  2823 /*
  2835 /**
  2824  * Checks whether the specified train has a collision with another vehicle. If
  2836  * Checks whether the specified train has a collision with another vehicle. If
  2825  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2837  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2826  * Reports the incident in a flashy news item, modifies station ratings and
  2838  * Reports the incident in a flashy news item, modifies station ratings and
  2827  * plays a sound.
  2839  * plays a sound.
  2828  */
  2840  */
  2846 	/* it can't collide with its own wagons */
  2858 	/* it can't collide with its own wagons */
  2847 	if (v == coll ||
  2859 	if (v == coll ||
  2848 			(v->u.rail.track == TRACK_BIT_WORMHOLE && (v->direction & 2) != (realcoll->direction & 2)))
  2860 			(v->u.rail.track == TRACK_BIT_WORMHOLE && (v->direction & 2) != (realcoll->direction & 2)))
  2849 		return;
  2861 		return;
  2850 
  2862 
  2851 	//two drivers + passangers killed in train v
  2863 	/* two drivers + passangers killed in train v */
  2852 	uint num = 2 + CountPassengersInTrain(v);
  2864 	uint num = 2 + CountPassengersInTrain(v);
  2853 	if (!(coll->vehstatus & VS_CRASHED))
  2865 	if (!(coll->vehstatus & VS_CRASHED))
  2854 		//two drivers + passangers killed in train coll (if it was not crashed already)
  2866 		/* two drivers + passangers killed in train coll (if it was not crashed already) */
  2855 		num += 2 + CountPassengersInTrain(coll);
  2867 		num += 2 + CountPassengersInTrain(coll);
  2856 
  2868 
  2857 	SetVehicleCrashed(v);
  2869 	SetVehicleCrashed(v);
  2858 	if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
  2870 	if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
  2859 
  2871 
  2957 					chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
  2969 					chosen_track = TrackToTrackBits(ChooseTrainTrack(v, gp.new_tile, enterdir, bits));
  2958 					assert(chosen_track & tracks);
  2970 					assert(chosen_track & tracks);
  2959 
  2971 
  2960 					/* Check if it's a red signal and that force proceed is not clicked. */
  2972 					/* Check if it's a red signal and that force proceed is not clicked. */
  2961 					if ((tracks >> 16) & chosen_track && v->u.rail.force_proceed == 0) {
  2973 					if ((tracks >> 16) & chosen_track && v->u.rail.force_proceed == 0) {
  2962 						// In front of a red signal
  2974 						/* In front of a red signal
  2963 						/* find the first set bit in ts. need to do it in 2 steps, since
  2975 						 * find the first set bit in ts. need to do it in 2 steps, since
  2964 						 * FIND_FIRST_BIT only handles 6 bits at a time. */
  2976 						 * FIND_FIRST_BIT only handles 6 bits at a time. */
  2965 						Trackdir i = FindFirstTrackdir((TrackdirBits)(uint16)ts);
  2977 						Trackdir i = FindFirstTrackdir((TrackdirBits)(uint16)ts);
  2966 
  2978 
  2967 						if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
  2979 						if (!HasSignalOnTrackdir(gp.new_tile, ReverseTrackdir(i))) {
  2968 							v->cur_speed = 0;
  2980 							v->cur_speed = 0;
  3298 			v->cur_speed = 0;
  3310 			v->cur_speed = 0;
  3299 			ReverseTrainDirection(v);
  3311 			ReverseTrainDirection(v);
  3300 			return false;
  3312 			return false;
  3301 		}
  3313 		}
  3302 		if ((ts &= (ts >> 16)) == 0) {
  3314 		if ((ts &= (ts >> 16)) == 0) {
  3303 			// make a rail/road crossing red
  3315 			/* make a rail/road crossing red */
  3304 			if (IsLevelCrossingTile(tile)) {
  3316 			if (IsLevelCrossingTile(tile)) {
  3305 				if (!IsCrossingBarred(tile)) {
  3317 				if (!IsCrossingBarred(tile)) {
  3306 					BarCrossing(tile);
  3318 					BarCrossing(tile);
  3307 					SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v);
  3319 					SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v);
  3308 					MarkTileDirtyByTile(tile);
  3320 					MarkTileDirtyByTile(tile);
  3314 		v->cur_speed = 0;
  3326 		v->cur_speed = 0;
  3315 		ReverseTrainDirection(v);
  3327 		ReverseTrainDirection(v);
  3316 		return false;
  3328 		return false;
  3317 	}
  3329 	}
  3318 
  3330 
  3319 	// slow down
  3331 	/* slow down */
  3320 	v->vehstatus |= VS_TRAIN_SLOWING;
  3332 	v->vehstatus |= VS_TRAIN_SLOWING;
  3321 	uint16 break_speed = _breakdown_speeds[x & 0xF];
  3333 	uint16 break_speed = _breakdown_speeds[x & 0xF];
  3322 	if (!(v->direction & 1)) break_speed >>= 1;
  3334 	if (!(v->direction & 1)) break_speed >>= 1;
  3323 	if (break_speed < v->cur_speed) v->cur_speed = break_speed;
  3335 	if (break_speed < v->cur_speed) v->cur_speed = break_speed;
  3324 
  3336 
  3367 
  3379 
  3368 	if (!mode) HandleLocomotiveSmokeCloud(v);
  3380 	if (!mode) HandleLocomotiveSmokeCloud(v);
  3369 
  3381 
  3370 	int j = UpdateTrainSpeed(v);
  3382 	int j = UpdateTrainSpeed(v);
  3371 	if (j == 0) {
  3383 	if (j == 0) {
  3372 		// if the vehicle has speed 0, update the last_speed field.
  3384 		/* if the vehicle has speed 0, update the last_speed field. */
  3373 		if (v->cur_speed != 0) return;
  3385 		if (v->cur_speed != 0) return;
  3374 	} else {
  3386 	} else {
  3375 		TrainCheckIfLineEnds(v);
  3387 		TrainCheckIfLineEnds(v);
  3376 
  3388 
  3377 		do {
  3389 		do {
  3394 	v->tick_counter++;
  3406 	v->tick_counter++;
  3395 
  3407 
  3396 	if (IsFrontEngine(v)) {
  3408 	if (IsFrontEngine(v)) {
  3397 		TrainLocoHandler(v, false);
  3409 		TrainLocoHandler(v, false);
  3398 
  3410 
  3399 		// make sure vehicle wasn't deleted.
  3411 		/* make sure vehicle wasn't deleted. */
  3400 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3412 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3401 			TrainLocoHandler(v, true);
  3413 			TrainLocoHandler(v, true);
  3402 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3414 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3403 		// Delete flooded standalone wagon
  3415 		/* Delete flooded standalone wagon */
  3404 		if (++v->u.rail.crash_anim_pos >= 4400)
  3416 		if (++v->u.rail.crash_anim_pos >= 4400)
  3405 			DeleteVehicle(v);
  3417 			DeleteVehicle(v);
  3406 	}
  3418 	}
  3407 }
  3419 }
  3408 
  3420 
  3413 	if (_patches.servint_trains == 0)                   return;
  3425 	if (_patches.servint_trains == 0)                   return;
  3414 	if (!VehicleNeedsService(v))                        return;
  3426 	if (!VehicleNeedsService(v))                        return;
  3415 	if (v->vehstatus & VS_STOPPED)                      return;
  3427 	if (v->vehstatus & VS_STOPPED)                      return;
  3416 	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
  3428 	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
  3417 
  3429 
  3418 	// Don't interfere with a depot visit scheduled by the user, or a
  3430 	/* Don't interfere with a depot visit scheduled by the user, or a
  3419 	// depot visit by the order list.
  3431 	 * depot visit by the order list. */
  3420 	if (v->current_order.type == OT_GOTO_DEPOT &&
  3432 	if (v->current_order.type == OT_GOTO_DEPOT &&
  3421 			(v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
  3433 			(v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
  3422 		return;
  3434 		return;
  3423 
  3435 
  3424 	if (CheckTrainIsInsideDepot(v)) {
  3436 	if (CheckTrainIsInsideDepot(v)) {
  3513 {
  3525 {
  3514 	Vehicle *v;
  3526 	Vehicle *v;
  3515 
  3527 
  3516 	FOR_ALL_VEHICLES(v) {
  3528 	FOR_ALL_VEHICLES(v) {
  3517 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3529 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3518 			// show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list)
  3530 			/* show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
  3519 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3531 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3520 				SetDParam(1, v->profit_this_year);
  3532 				SetDParam(1, v->profit_this_year);
  3521 				SetDParam(0, v->unitnumber);
  3533 				SetDParam(0, v->unitnumber);
  3522 				AddNewsItem(
  3534 				AddNewsItem(
  3523 					STR_TRAIN_IS_UNPROFITABLE,
  3535 					STR_TRAIN_IS_UNPROFITABLE,
  3585 			} END_ENUM_WAGONS(u)
  3597 			} END_ENUM_WAGONS(u)
  3586 		}
  3598 		}
  3587 	}
  3599 	}
  3588 }
  3600 }
  3589 
  3601 
  3590 /*
  3602 /**
  3591  *  Converts all trains to the new subtype format introduced in savegame 16.2
  3603  *  Converts all trains to the new subtype format introduced in savegame 16.2
  3592  *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
  3604  *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
  3593  */
  3605  */
  3594 void ConvertOldMultiheadToNew()
  3606 void ConvertOldMultiheadToNew()
  3595 {
  3607 {