src/train_cmd.cpp
branchnoai
changeset 9629 66dde6412125
parent 9628 b5c2449616b5
child 9631 8a2d1c2ceb88
equal deleted inserted replaced
9628:b5c2449616b5 9629:66dde6412125
    13 #include "table/strings.h"
    13 #include "table/strings.h"
    14 #include "map.h"
    14 #include "map.h"
    15 #include "tile.h"
    15 #include "tile.h"
    16 #include "tunnel_map.h"
    16 #include "tunnel_map.h"
    17 #include "vehicle.h"
    17 #include "vehicle.h"
       
    18 #include "timetable.h"
    18 #include "articulated_vehicles.h"
    19 #include "articulated_vehicles.h"
    19 #include "command.h"
    20 #include "command.h"
    20 #include "pathfind.h"
    21 #include "pathfind.h"
    21 #include "npf.h"
    22 #include "npf.h"
    22 #include "station.h"
    23 #include "station.h"
   109 static void TrainCargoChanged(Vehicle* v)
   110 static void TrainCargoChanged(Vehicle* v)
   110 {
   111 {
   111 	uint32 weight = 0;
   112 	uint32 weight = 0;
   112 
   113 
   113 	for (Vehicle *u = v; u != NULL; u = u->next) {
   114 	for (Vehicle *u = v; u != NULL; u = u->next) {
   114 		uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo_count * FreightWagonMult(u->cargo_type) / 16;
   115 		uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo.Count() * FreightWagonMult(u->cargo_type) / 16;
   115 
   116 
   116 		/* Vehicle weight is not added for articulated parts. */
   117 		/* Vehicle weight is not added for articulated parts. */
   117 		if (!IsArticulatedPart(u)) {
   118 		if (!IsArticulatedPart(u)) {
   118 			/* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */
   119 			/* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */
   119 			vweight += GetVehicleProperty(u, 0x16, RailVehInfo(u->engine_type)->weight);
   120 			vweight += GetVehicleProperty(u, 0x16, RailVehInfo(u->engine_type)->weight);
   460 		img = orig_rail_vehicle_info[v->engine_type].image_index;
   461 		img = orig_rail_vehicle_info[v->engine_type].image_index;
   461 	}
   462 	}
   462 
   463 
   463 	base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]);
   464 	base = _engine_sprite_base[img] + ((direction + _engine_sprite_add[img]) & _engine_sprite_and[img]);
   464 
   465 
   465 	if (v->cargo_count >= v->cargo_cap / 2) base += _wagon_full_adder[img];
   466 	if (v->cargo.Count() >= v->cargo_cap / 2U) base += _wagon_full_adder[img];
   466 	return base;
   467 	return base;
   467 }
   468 }
   468 
   469 
   469 void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal)
   470 void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal)
   470 {
   471 {
   500 		}
   501 		}
   501 	}
   502 	}
   502 	DrawSprite(image, pal, x, y);
   503 	DrawSprite(image, pal, x, y);
   503 }
   504 }
   504 
   505 
   505 static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags)
   506 static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags)
   506 {
   507 {
   507 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   508 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   508 
   509 
   509 	const RailVehicleInfo *rvi = RailVehInfo(engine);
   510 	const RailVehicleInfo *rvi = RailVehInfo(engine);
   510 	int32 value = (GetEngineProperty(engine, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8;
   511 	CommandCost value((GetEngineProperty(engine, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
   511 
   512 
   512 	uint num_vehicles = 1 + CountArticulatedParts(engine);
   513 	uint num_vehicles = 1 + CountArticulatedParts(engine);
   513 
   514 
   514 	if (!(flags & DC_QUERY_COST)) {
   515 	if (!(flags & DC_QUERY_COST)) {
   515 		Vehicle *vl[11]; // Allow for wagon and upto 10 artic parts.
   516 		Vehicle *vl[11]; // Allow for wagon and upto 10 artic parts.
   563 			}
   564 			}
   564 
   565 
   565 			v->cargo_type = rvi->cargo_type;
   566 			v->cargo_type = rvi->cargo_type;
   566 			v->cargo_subtype = 0;
   567 			v->cargo_subtype = 0;
   567 			v->cargo_cap = rvi->capacity;
   568 			v->cargo_cap = rvi->capacity;
   568 			v->value = value;
   569 			v->value = value.GetCost();
   569 //			v->day_counter = 0;
   570 //			v->day_counter = 0;
   570 
   571 
   571 			v->u.rail.railtype = rvi->railtype;
   572 			v->u.rail.railtype = rvi->railtype;
   572 
   573 
   573 			v->build_year = _cur_year;
   574 			v->build_year = _cur_year;
   590 			}
   591 			}
   591 			GetPlayer(_current_player)->num_engines[engine]++;
   592 			GetPlayer(_current_player)->num_engines[engine]++;
   592 		}
   593 		}
   593 	}
   594 	}
   594 
   595 
   595 	return value;
   596 	return CommandCost(value);
   596 }
   597 }
   597 
   598 
   598 /** Move all free vehicles in the depot to the train */
   599 /** Move all free vehicles in the depot to the train */
   599 static void NormalizeTrainVehInDepot(const Vehicle* u)
   600 static void NormalizeTrainVehInDepot(const Vehicle* u)
   600 {
   601 {
   609 				break;
   610 				break;
   610 		}
   611 		}
   611 	}
   612 	}
   612 }
   613 }
   613 
   614 
   614 static int32 EstimateTrainCost(EngineID engine, const RailVehicleInfo* rvi)
   615 static CommandCost EstimateTrainCost(EngineID engine, const RailVehicleInfo* rvi)
   615 {
   616 {
   616 	return GetEngineProperty(engine, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5;
   617 	return CommandCost(GetEngineProperty(engine, 0x17, rvi->base_cost) * (_price.build_railvehicle >> 3) >> 5);
   617 }
   618 }
   618 
   619 
   619 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building)
   620 static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool building)
   620 {
   621 {
   621 	u->direction = v->direction;
   622 	u->direction = v->direction;
   649  * @param flags type of operation
   650  * @param flags type of operation
   650  * @param p1 engine type id
   651  * @param p1 engine type id
   651  * @param p2 bit 0 when set, the train will get number 0, otherwise it will get a free number
   652  * @param p2 bit 0 when set, the train will get number 0, otherwise it will get a free number
   652  *           bit 1 prevents any free cars from being added to the train
   653  *           bit 1 prevents any free cars from being added to the train
   653  */
   654  */
   654 int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   655 CommandCost CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   655 {
   656 {
   656 	/* Check if the engine-type is valid (for the player) */
   657 	/* Check if the engine-type is valid (for the player) */
   657 	if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_RAIL_VEHICLE_NOT_AVAILABLE);
   658 	if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_RAIL_VEHICLE_NOT_AVAILABLE);
   658 
   659 
   659 	/* Check if the train is actually being built in a depot belonging
   660 	/* Check if the train is actually being built in a depot belonging
   671 	/* We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */
   672 	/* We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */
   672 	if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
   673 	if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
   673 
   674 
   674 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags);
   675 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags);
   675 
   676 
   676 	int32 value = EstimateTrainCost(p1, rvi);
   677 	CommandCost value = EstimateTrainCost(p1, rvi);
   677 
   678 
   678 	uint num_vehicles =
   679 	uint num_vehicles =
   679 		(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
   680 		(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
   680 		CountArticulatedParts(p1);
   681 		CountArticulatedParts(p1);
   681 
   682 
   710 			v->spritenum = rvi->image_index;
   711 			v->spritenum = rvi->image_index;
   711 			v->cargo_type = rvi->cargo_type;
   712 			v->cargo_type = rvi->cargo_type;
   712 			v->cargo_subtype = 0;
   713 			v->cargo_subtype = 0;
   713 			v->cargo_cap = rvi->capacity;
   714 			v->cargo_cap = rvi->capacity;
   714 			v->max_speed = rvi->max_speed;
   715 			v->max_speed = rvi->max_speed;
   715 			v->value = value;
   716 			v->value = value.GetCost();
   716 			v->last_station_visited = INVALID_STATION;
   717 			v->last_station_visited = INVALID_STATION;
   717 			v->dest_tile = 0;
   718 			v->dest_tile = 0;
   718 
   719 
   719 			v->engine_type = p1;
   720 			v->engine_type = p1;
   720 
   721 
   907  * @param p1 various bitstuffed elements
   908  * @param p1 various bitstuffed elements
   908  * - p1 (bit  0 - 15) source vehicle index
   909  * - p1 (bit  0 - 15) source vehicle index
   909  * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line
   910  * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line
   910  * @param p2 (bit 0) move all vehicles following the source vehicle
   911  * @param p2 (bit 0) move all vehicles following the source vehicle
   911  */
   912  */
   912 int32 CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   913 CommandCost CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   913 {
   914 {
   914 	VehicleID s = GB(p1, 0, 16);
   915 	VehicleID s = GB(p1, 0, 16);
   915 	VehicleID d = GB(p1, 16, 16);
   916 	VehicleID d = GB(p1, 16, 16);
   916 
   917 
   917 	if (!IsValidVehicleID(s)) return CMD_ERROR;
   918 	if (!IsValidVehicleID(s)) return CMD_ERROR;
   935 	if (dst != NULL) {
   936 	if (dst != NULL) {
   936 		while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst);
   937 		while (IsArticulatedPart(dst)) dst = GetPrevVehicleInChain(dst);
   937 	}
   938 	}
   938 
   939 
   939 	/* don't move the same vehicle.. */
   940 	/* don't move the same vehicle.. */
   940 	if (src == dst) return 0;
   941 	if (src == dst) return CommandCost();
   941 
   942 
   942 	/* locate the head of the two chains */
   943 	/* locate the head of the two chains */
   943 	Vehicle *src_head = GetFirstVehicleInChain(src);
   944 	Vehicle *src_head = GetFirstVehicleInChain(src);
   944 	Vehicle *dst_head;
   945 	Vehicle *dst_head;
   945 	if (dst != NULL) {
   946 	if (dst != NULL) {
   952 	}
   953 	}
   953 
   954 
   954 	if (IsMultiheaded(src) && !IsTrainEngine(src)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
   955 	if (IsMultiheaded(src) && !IsTrainEngine(src)) return_cmd_error(STR_REAR_ENGINE_FOLLOW_FRONT_ERROR);
   955 
   956 
   956 	/* when moving all wagons, we can't have the same src_head and dst_head */
   957 	/* when moving all wagons, we can't have the same src_head and dst_head */
   957 	if (HASBIT(p2, 0) && src_head == dst_head) return 0;
   958 	if (HASBIT(p2, 0) && src_head == dst_head) return CommandCost();
   958 
   959 
   959 	{
   960 	{
   960 		int max_len = _patches.mammoth_trains ? 100 : 9;
   961 		int max_len = _patches.mammoth_trains ? 100 : 9;
   961 
   962 
   962 		/* check if all vehicles in the source train are stopped inside a depot. */
   963 		/* check if all vehicles in the source train are stopped inside a depot. */
  1151 		}
  1152 		}
  1152 
  1153 
  1153 		RebuildVehicleLists();
  1154 		RebuildVehicleLists();
  1154 	}
  1155 	}
  1155 
  1156 
  1156 	return 0;
  1157 	return CommandCost();
  1157 }
  1158 }
  1158 
  1159 
  1159 /** Start/Stop a train.
  1160 /** Start/Stop a train.
  1160  * @param tile unused
  1161  * @param tile unused
  1161  * @param flags type of operation
  1162  * @param flags type of operation
  1162  * @param p1 train to start/stop
  1163  * @param p1 train to start/stop
  1163  * @param p2 unused
  1164  * @param p2 unused
  1164  */
  1165  */
  1165 int32 CmdStartStopTrain(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1166 CommandCost CmdStartStopTrain(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1166 {
  1167 {
  1167 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1168 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1168 
  1169 
  1169 	Vehicle *v = GetVehicle(p1);
  1170 	Vehicle *v = GetVehicle(p1);
  1170 
  1171 
  1187 
  1188 
  1188 		v->vehstatus ^= VS_STOPPED;
  1189 		v->vehstatus ^= VS_STOPPED;
  1189 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1190 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1190 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1191 		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1191 	}
  1192 	}
  1192 	return 0;
  1193 	return CommandCost();
  1193 }
  1194 }
  1194 
  1195 
  1195 /** Sell a (single) train wagon/engine.
  1196 /** Sell a (single) train wagon/engine.
  1196  * @param tile unused
  1197  * @param tile unused
  1197  * @param flags type of operation
  1198  * @param flags type of operation
  1201  * - p2 = 1: sell the vehicle and all vehicles following it in the chain
  1202  * - p2 = 1: sell the vehicle and all vehicles following it in the chain
  1202              if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
  1203              if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
  1203  * - p2 = 2: when selling attached locos, rearrange all vehicles after it to separate lines;
  1204  * - p2 = 2: when selling attached locos, rearrange all vehicles after it to separate lines;
  1204  *           all wagons of the same type will go on the same line. Used by the AI currently
  1205  *           all wagons of the same type will go on the same line. Used by the AI currently
  1205  */
  1206  */
  1206 int32 CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1207 CommandCost CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1207 {
  1208 {
  1208 	/* Check if we deleted a vehicle window */
  1209 	/* Check if we deleted a vehicle window */
  1209 	Window *w = NULL;
  1210 	Window *w = NULL;
  1210 
  1211 
  1211 	if (!IsValidVehicleID(p1) || p2 > 2) return CMD_ERROR;
  1212 	if (!IsValidVehicleID(p1) || p2 > 2) return CMD_ERROR;
  1233 		}
  1234 		}
  1234 		InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
  1235 		InvalidateWindow(WC_VEHICLE_DEPOT, first->tile);
  1235 		RebuildVehicleLists();
  1236 		RebuildVehicleLists();
  1236 	}
  1237 	}
  1237 
  1238 
  1238 	int32 cost = 0;
  1239 	CommandCost cost;
  1239 	switch (p2) {
  1240 	switch (p2) {
  1240 		case 0: case 2: { /* Delete given wagon */
  1241 		case 0: case 2: { /* Delete given wagon */
  1241 			bool switch_engine = false;    // update second wagon to engine?
  1242 			bool switch_engine = false;    // update second wagon to engine?
  1242 			byte ori_subtype = v->subtype; // backup subtype of deleted wagon in case DeleteVehicle() changes
  1243 			byte ori_subtype = v->subtype; // backup subtype of deleted wagon in case DeleteVehicle() changes
  1243 
  1244 
  1245 			 * rear engine of the loco (from the point of deletion onwards) */
  1246 			 * rear engine of the loco (from the point of deletion onwards) */
  1246 			Vehicle *rear = (IsMultiheaded(v) &&
  1247 			Vehicle *rear = (IsMultiheaded(v) &&
  1247 				IsTrainEngine(v)) ? v->u.rail.other_multiheaded_part : NULL;
  1248 				IsTrainEngine(v)) ? v->u.rail.other_multiheaded_part : NULL;
  1248 
  1249 
  1249 			if (rear != NULL) {
  1250 			if (rear != NULL) {
  1250 				cost -= rear->value;
  1251 				cost.AddCost(-rear->value);
  1251 				if (flags & DC_EXEC) {
  1252 				if (flags & DC_EXEC) {
  1252 					UnlinkWagon(rear, first);
  1253 					UnlinkWagon(rear, first);
  1253 					DeleteDepotHighlightOfVehicle(rear);
  1254 					DeleteDepotHighlightOfVehicle(rear);
  1254 					DeleteVehicle(rear);
  1255 					DeleteVehicle(rear);
  1255 				}
  1256 				}
  1300 					if (IsLocalPlayer() && w != NULL) ShowTrainViewWindow(new_f);
  1301 					if (IsLocalPlayer() && w != NULL) ShowTrainViewWindow(new_f);
  1301 				}
  1302 				}
  1302 			}
  1303 			}
  1303 
  1304 
  1304 			/* 3. Delete the requested wagon */
  1305 			/* 3. Delete the requested wagon */
  1305 			cost -= v->value;
  1306 			cost.AddCost(-v->value);
  1306 			if (flags & DC_EXEC) {
  1307 			if (flags & DC_EXEC) {
  1307 				first = UnlinkWagon(v, first);
  1308 				first = UnlinkWagon(v, first);
  1308 				DeleteDepotHighlightOfVehicle(v);
  1309 				DeleteDepotHighlightOfVehicle(v);
  1309 				DeleteVehicle(v);
  1310 				DeleteVehicle(v);
  1310 
  1311 
  1350 					if (IsTrainEngine(v)) {
  1351 					if (IsTrainEngine(v)) {
  1351 						/* We got a front engine of a multiheaded set. Now we will sell the rear end too */
  1352 						/* We got a front engine of a multiheaded set. Now we will sell the rear end too */
  1352 						Vehicle *rear = v->u.rail.other_multiheaded_part;
  1353 						Vehicle *rear = v->u.rail.other_multiheaded_part;
  1353 
  1354 
  1354 						if (rear != NULL) {
  1355 						if (rear != NULL) {
  1355 							cost -= rear->value;
  1356 							cost.AddCost(-rear->value);
  1356 
  1357 
  1357 							/* If this is a multiheaded vehicle with nothing
  1358 							/* If this is a multiheaded vehicle with nothing
  1358 							 * between the parts, tmp will be pointing to the
  1359 							 * between the parts, tmp will be pointing to the
  1359 							 * rear part, which is unlinked from the train and
  1360 							 * rear part, which is unlinked from the train and
  1360 							 * deleted here. However, because tmp has already
  1361 							 * deleted here. However, because tmp has already
  1372 						/* The front to this engine is earlier in this train. Do nothing */
  1373 						/* The front to this engine is earlier in this train. Do nothing */
  1373 						continue;
  1374 						continue;
  1374 					}
  1375 					}
  1375 				}
  1376 				}
  1376 
  1377 
  1377 				cost -= v->value;
  1378 				cost.AddCost(-v->value);
  1378 				if (flags & DC_EXEC) {
  1379 				if (flags & DC_EXEC) {
  1379 					first = UnlinkWagon(v, first);
  1380 					first = UnlinkWagon(v, first);
  1380 					DeleteDepotHighlightOfVehicle(v);
  1381 					DeleteDepotHighlightOfVehicle(v);
  1381 					DeleteVehicle(v);
  1382 					DeleteVehicle(v);
  1382 					RemoveVehicleFromGroup(v);
  1383 					RemoveVehicleFromGroup(v);
  1614  * @param tile unused
  1615  * @param tile unused
  1615  * @param flags type of operation
  1616  * @param flags type of operation
  1616  * @param p1 train to reverse
  1617  * @param p1 train to reverse
  1617  * @param p2 if true, reverse a unit in a train (needs to be in a depot)
  1618  * @param p2 if true, reverse a unit in a train (needs to be in a depot)
  1618  */
  1619  */
  1619 int32 CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1620 CommandCost CmdReverseTrainDirection(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1620 {
  1621 {
  1621 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1622 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1622 
  1623 
  1623 	Vehicle *v = GetVehicle(p1);
  1624 	Vehicle *v = GetVehicle(p1);
  1624 
  1625 
  1654 				SetLastSpeed(v, 0);
  1655 				SetLastSpeed(v, 0);
  1655 				ReverseTrainDirection(v);
  1656 				ReverseTrainDirection(v);
  1656 			}
  1657 			}
  1657 		}
  1658 		}
  1658 	}
  1659 	}
  1659 	return 0;
  1660 	return CommandCost();
  1660 }
  1661 }
  1661 
  1662 
  1662 /** Force a train through a red signal
  1663 /** Force a train through a red signal
  1663  * @param tile unused
  1664  * @param tile unused
  1664  * @param flags type of operation
  1665  * @param flags type of operation
  1665  * @param p1 train to ignore the red signal
  1666  * @param p1 train to ignore the red signal
  1666  * @param p2 unused
  1667  * @param p2 unused
  1667  */
  1668  */
  1668 int32 CmdForceTrainProceed(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1669 CommandCost CmdForceTrainProceed(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1669 {
  1670 {
  1670 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1671 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1671 
  1672 
  1672 	Vehicle *v = GetVehicle(p1);
  1673 	Vehicle *v = GetVehicle(p1);
  1673 
  1674 
  1674 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1675 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1675 
  1676 
  1676 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1677 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1677 
  1678 
  1678 	return 0;
  1679 	return CommandCost();
  1679 }
  1680 }
  1680 
  1681 
  1681 /** Refits a train to the specified cargo type.
  1682 /** Refits a train to the specified cargo type.
  1682  * @param tile unused
  1683  * @param tile unused
  1683  * @param flags type of operation
  1684  * @param flags type of operation
  1686  * - p2 = (bit 0-7) - the new cargo type to refit to
  1687  * - p2 = (bit 0-7) - the new cargo type to refit to
  1687  * - p2 = (bit 8-15) - the new cargo subtype to refit to
  1688  * - p2 = (bit 8-15) - the new cargo subtype to refit to
  1688  * - p2 = (bit 16) - refit only this vehicle
  1689  * - p2 = (bit 16) - refit only this vehicle
  1689  * @return cost of refit or error
  1690  * @return cost of refit or error
  1690  */
  1691  */
  1691 int32 CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1692 CommandCost CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1692 {
  1693 {
  1693 	CargoID new_cid = GB(p2, 0, 8);
  1694 	CargoID new_cid = GB(p2, 0, 8);
  1694 	byte new_subtype = GB(p2, 8, 8);
  1695 	byte new_subtype = GB(p2, 8, 8);
  1695 	bool only_this = HASBIT(p2, 16);
  1696 	bool only_this = HASBIT(p2, 16);
  1696 
  1697 
  1704 	/* Check cargo */
  1705 	/* Check cargo */
  1705 	if (new_cid >= NUM_CARGO) return CMD_ERROR;
  1706 	if (new_cid >= NUM_CARGO) return CMD_ERROR;
  1706 
  1707 
  1707 	SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  1708 	SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  1708 
  1709 
  1709 	int32 cost = 0;
  1710 	CommandCost cost;
  1710 	uint num = 0;
  1711 	uint num = 0;
  1711 
  1712 
  1712 	do {
  1713 	do {
  1713 		/* XXX: We also refit all the attached wagons en-masse if they
  1714 		/* XXX: We also refit all the attached wagons en-masse if they
  1714 		 * can be refitted. This is how TTDPatch does it.  TODO: Have
  1715 		 * can be refitted. This is how TTDPatch does it.  TODO: Have
  1753 				}
  1754 				}
  1754 			}
  1755 			}
  1755 
  1756 
  1756 			if (amount != 0) {
  1757 			if (amount != 0) {
  1757 				if (new_cid != v->cargo_type) {
  1758 				if (new_cid != v->cargo_type) {
  1758 					cost += GetRefitCost(v->engine_type);
  1759 					cost.AddCost(GetRefitCost(v->engine_type));
  1759 				}
  1760 				}
  1760 
  1761 
  1761 				num += amount;
  1762 				num += amount;
  1762 				if (flags & DC_EXEC) {
  1763 				if (flags & DC_EXEC) {
  1763 					v->cargo_count = (v->cargo_type == new_cid) ? min(amount, v->cargo_count) : 0;
  1764 					v->cargo.Truncate((v->cargo_type == new_cid) ? amount : 0);
  1764 					v->cargo_type = new_cid;
  1765 					v->cargo_type = new_cid;
  1765 					v->cargo_cap = amount;
  1766 					v->cargo_cap = amount;
  1766 					v->cargo_subtype = new_subtype;
  1767 					v->cargo_subtype = new_subtype;
  1767 					InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1768 					InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  1768 					InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1769 					InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
  1870  * @param p1 train to send to the depot
  1871  * @param p1 train to send to the depot
  1871  * @param p2 various bitmasked elements
  1872  * @param p2 various bitmasked elements
  1872  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
  1873  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
  1873  * - p2 bit 8-10 - VLW flag (for mass goto depot)
  1874  * - p2 bit 8-10 - VLW flag (for mass goto depot)
  1874  */
  1875  */
  1875 int32 CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1876 CommandCost CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1876 {
  1877 {
  1877 	if (p2 & DEPOT_MASS_SEND) {
  1878 	if (p2 & DEPOT_MASS_SEND) {
  1878 		/* Mass goto depot requested */
  1879 		/* Mass goto depot requested */
  1879 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1880 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1880 		return SendAllVehiclesToDepot(VEH_TRAIN, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1881 		return SendAllVehiclesToDepot(VEH_TRAIN, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1895 			 * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
  1896 			 * Note: the if is (true for requesting service == true for ordered to stop in depot)          */
  1896 			if (flags & DC_EXEC) {
  1897 			if (flags & DC_EXEC) {
  1897 				TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
  1898 				TOGGLEBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
  1898 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1899 				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1899 			}
  1900 			}
  1900 			return 0;
  1901 			return CommandCost();
  1901 		}
  1902 		}
  1902 
  1903 
  1903 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
  1904 		if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders
  1904 		if (flags & DC_EXEC) {
  1905 		if (flags & DC_EXEC) {
  1905 			if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) {
  1906 			if (HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) {
  1908 
  1909 
  1909 			v->current_order.type = OT_DUMMY;
  1910 			v->current_order.type = OT_DUMMY;
  1910 			v->current_order.flags = 0;
  1911 			v->current_order.flags = 0;
  1911 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1912 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1912 		}
  1913 		}
  1913 		return 0;
  1914 		return CommandCost();
  1914 	}
  1915 	}
  1915 
  1916 
  1916 	/* check if at a standstill (not stopped only) in a depot
  1917 	/* check if at a standstill (not stopped only) in a depot
  1917 	 * the check is down here to make it possible to alter stop/service for trains entering the depot */
  1918 	 * the check is down here to make it possible to alter stop/service for trains entering the depot */
  1918 	if (IsTileDepotType(v->tile, TRANSPORT_RAIL) && v->cur_speed == 0) return CMD_ERROR;
  1919 	if (IsTileDepotType(v->tile, TRANSPORT_RAIL) && v->cur_speed == 0) return CMD_ERROR;
  1932 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1933 		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  1933 		/* If there is no depot in front, reverse automatically */
  1934 		/* If there is no depot in front, reverse automatically */
  1934 		if (tfdd.reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
  1935 		if (tfdd.reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
  1935 	}
  1936 	}
  1936 
  1937 
  1937 	return 0;
  1938 	return CommandCost();
  1938 }
  1939 }
  1939 
  1940 
  1940 
  1941 
  1941 void OnTick_Train()
  1942 void OnTick_Train()
  1942 {
  1943 {
  2377 	switch (v->current_order.type) {
  2378 	switch (v->current_order.type) {
  2378 		case OT_GOTO_DEPOT:
  2379 		case OT_GOTO_DEPOT:
  2379 			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return false;
  2380 			if (!(v->current_order.flags & OF_PART_OF_ORDERS)) return false;
  2380 			if ((v->current_order.flags & OF_SERVICE_IF_NEEDED) &&
  2381 			if ((v->current_order.flags & OF_SERVICE_IF_NEEDED) &&
  2381 					!VehicleNeedsService(v)) {
  2382 					!VehicleNeedsService(v)) {
       
  2383 				UpdateVehicleTimetable(v, true);
  2382 				v->cur_order_index++;
  2384 				v->cur_order_index++;
  2383 			}
  2385 			}
  2384 			break;
  2386 			break;
  2385 
  2387 
  2386 		case OT_LOADING:
  2388 		case OT_LOADING:
  2391 	}
  2393 	}
  2392 
  2394 
  2393 	/* check if we've reached the waypoint? */
  2395 	/* check if we've reached the waypoint? */
  2394 	bool at_waypoint = false;
  2396 	bool at_waypoint = false;
  2395 	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
  2397 	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
       
  2398 		UpdateVehicleTimetable(v, true);
  2396 		v->cur_order_index++;
  2399 		v->cur_order_index++;
  2397 		at_waypoint = true;
  2400 		at_waypoint = true;
  2398 	}
  2401 	}
  2399 
  2402 
  2400 	/* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
  2403 	/* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
  2401 	if (_patches.new_nonstop &&
  2404 	if (_patches.new_nonstop &&
  2402 			v->current_order.flags & OF_NON_STOP &&
  2405 			v->current_order.flags & OF_NON_STOP &&
  2403 			IsTileType(v->tile, MP_STATION) &&
  2406 			IsTileType(v->tile, MP_STATION) &&
  2404 			v->current_order.dest == GetStationIndex(v->tile)) {
  2407 			v->current_order.dest == GetStationIndex(v->tile)) {
       
  2408 		UpdateVehicleTimetable(v, true);
  2405 		v->cur_order_index++;
  2409 		v->cur_order_index++;
  2406 	}
  2410 	}
  2407 
  2411 
  2408 	/* Get the current order */
  2412 	/* Get the current order */
  2409 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
  2413 	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
  2523 	v->current_order.dest = 0;
  2527 	v->current_order.dest = 0;
  2524 }
  2528 }
  2525 
  2529 
  2526 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2530 static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
  2527 {
  2531 {
  2528 	/* need this hint so it returns the right z coordinate on bridges. */
       
  2529 	byte new_z = GetSlopeZ(v->x_pos, v->y_pos);
       
  2530 
       
  2531 	byte old_z = v->z_pos;
  2532 	byte old_z = v->z_pos;
  2532 	v->z_pos = new_z;
  2533 	v->z_pos = GetSlopeZ(v->x_pos, v->y_pos);
  2533 
  2534 
  2534 	if (new_tile) {
  2535 	if (new_tile) {
  2535 		CLRBIT(v->u.rail.flags, VRF_GOINGUP);
  2536 		CLRBIT(v->u.rail.flags, VRF_GOINGUP);
  2536 		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
  2537 		CLRBIT(v->u.rail.flags, VRF_GOINGDOWN);
  2537 
  2538 
  2538 		if (new_z != old_z) {
  2539 		if (v->u.rail.track == TRACK_BIT_X || v->u.rail.track == TRACK_BIT_Y) {
  2539 			TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
  2540 			/* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped.
  2540 
  2541 			 * To check whether the current tile is sloped, and in which
  2541 			/* XXX workaround, whole UP/DOWN detection needs overhaul */
  2542 			 * direction it is sloped, we get the 'z' at the center of
  2542 			if (!IsTunnelTile(tile)) {
  2543 			 * the tile (middle_z) and the edge of the tile (old_z),
  2543 				SETBIT(v->u.rail.flags, (new_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
  2544 			 * which we then can compare. */
       
  2545 			static const int HALF_TILE_SIZE = TILE_SIZE / 2;
       
  2546 			static const int INV_TILE_SIZE_MASK = ~(TILE_SIZE - 1);
       
  2547 
       
  2548 			byte middle_z = GetSlopeZ((v->x_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE, (v->y_pos & INV_TILE_SIZE_MASK) | HALF_TILE_SIZE);
       
  2549 
       
  2550 			/* For some reason tunnel tiles are always given as sloped :(
       
  2551 			 * But they are not sloped... */
       
  2552 			if (middle_z != v->z_pos && !IsTunnelTile(TileVirtXY(v->x_pos, v->y_pos))) {
       
  2553 				SETBIT(v->u.rail.flags, (middle_z > old_z) ? VRF_GOINGUP : VRF_GOINGDOWN);
  2544 			}
  2554 			}
  2545 		}
  2555 		}
  2546 	}
  2556 	}
  2547 
  2557 
  2548 	VehiclePositionChanged(v);
  2558 	VehiclePositionChanged(v);
  2657 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2667 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2658 	}
  2668 	}
  2659 }
  2669 }
  2660 
  2670 
  2661 
  2671 
       
  2672 static void SetVehicleCrashed(Vehicle *v)
       
  2673 {
       
  2674 	if (v->u.rail.crash_anim_pos != 0) return;
       
  2675 
       
  2676 	v->u.rail.crash_anim_pos++;
       
  2677 
       
  2678 	Vehicle *u = v;
       
  2679 	BEGIN_ENUM_WAGONS(v)
       
  2680 		v->vehstatus |= VS_CRASHED;
       
  2681 	END_ENUM_WAGONS(v)
       
  2682 
       
  2683 	InvalidateWindowWidget(WC_VEHICLE_VIEW, u->index, STATUS_BAR);
       
  2684 }
       
  2685 
       
  2686 static uint CountPassengersInTrain(const Vehicle* v)
       
  2687 {
       
  2688 	uint num = 0;
       
  2689 	BEGIN_ENUM_WAGONS(v)
       
  2690 		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count();
       
  2691 	END_ENUM_WAGONS(v)
       
  2692 	return num;
       
  2693 }
       
  2694 
  2662 struct TrainCollideChecker {
  2695 struct TrainCollideChecker {
  2663 	const Vehicle *v;
  2696 	Vehicle *v;
  2664 	const Vehicle *v_skip;
  2697 	const Vehicle *v_skip;
       
  2698 	uint num;
  2665 };
  2699 };
  2666 
  2700 
  2667 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2701 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2668 {
  2702 {
  2669 	const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2703 	TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2670 
  2704 
  2671 	if (v != tcc->v &&
  2705 	if (v != tcc->v &&
  2672 			v != tcc->v_skip &&
  2706 			v != tcc->v_skip &&
  2673 			v->type == VEH_TRAIN &&
  2707 			v->type == VEH_TRAIN &&
  2674 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2708 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2675 			myabs(v->z_pos - tcc->v->z_pos) < 6 &&
  2709 			myabs(v->z_pos - tcc->v->z_pos) < 6 &&
  2676 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2710 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2677 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
  2711 			myabs(v->y_pos - tcc->v->y_pos) < 6 ) {
  2678 		return v;
  2712 
  2679 	} else {
  2713 		Vehicle *coll = GetFirstVehicleInChain(v);
  2680 		return NULL;
  2714 
  2681 	}
  2715 		/* it can't collide with its own wagons */
  2682 }
  2716 		if (tcc->v == coll ||
  2683 
  2717 			(tcc->v->u.rail.track == TRACK_BIT_WORMHOLE && (tcc->v->direction & 2) != (v->direction & 2)))
  2684 static void SetVehicleCrashed(Vehicle *v)
  2718 			return NULL;
  2685 {
  2719 
  2686 	if (v->u.rail.crash_anim_pos != 0) return;
  2720 		/* two drivers + passengers killed in train tcc->v (if it was not crashed already) */
  2687 
  2721 		if (!(tcc->v->vehstatus & VS_CRASHED)) {
  2688 	v->u.rail.crash_anim_pos++;
  2722 			tcc->num += 2 + CountPassengersInTrain(tcc->v);
  2689 
  2723 			SetVehicleCrashed(tcc->v);
  2690 	Vehicle *u = v;
  2724 		}
  2691 	BEGIN_ENUM_WAGONS(v)
  2725 
  2692 		v->vehstatus |= VS_CRASHED;
  2726 		if (!(coll->vehstatus & VS_CRASHED)) {
  2693 	END_ENUM_WAGONS(v)
  2727 			/* two drivers + passengers killed in train coll (if it was not crashed already) */
  2694 
  2728 			tcc->num += 2 + CountPassengersInTrain(coll);
  2695 	InvalidateWindowWidget(WC_VEHICLE_VIEW, u->index, STATUS_BAR);
  2729 			SetVehicleCrashed(coll);
  2696 }
  2730 		}
  2697 
  2731 	}
  2698 static uint CountPassengersInTrain(const Vehicle* v)
  2732 
  2699 {
  2733 	return NULL;
  2700 	uint num = 0;
       
  2701 	BEGIN_ENUM_WAGONS(v)
       
  2702 		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo_count;
       
  2703 	END_ENUM_WAGONS(v)
       
  2704 	return num;
       
  2705 }
  2734 }
  2706 
  2735 
  2707 /**
  2736 /**
  2708  * Checks whether the specified train has a collision with another vehicle. If
  2737  * Checks whether the specified train has a collision with another vehicle. If
  2709  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2738  * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
  2718 	assert(v->u.rail.track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
  2747 	assert(v->u.rail.track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
  2719 
  2748 
  2720 	TrainCollideChecker tcc;
  2749 	TrainCollideChecker tcc;
  2721 	tcc.v = v;
  2750 	tcc.v = v;
  2722 	tcc.v_skip = v->next;
  2751 	tcc.v_skip = v->next;
  2723 
  2752 	tcc.num = 0;
  2724 	/* find colliding vehicle */
  2753 
  2725 	Vehicle *realcoll = (Vehicle*)VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
  2754 	/* find colliding vehicles */
  2726 	if (realcoll == NULL) return;
  2755 	VehicleFromPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
  2727 
  2756 
  2728 	Vehicle *coll = GetFirstVehicleInChain(realcoll);
  2757 	/* any dead -> no crash */
  2729 
  2758 	if (tcc.num == 0) return;
  2730 	/* it can't collide with its own wagons */
  2759 
  2731 	if (v == coll ||
  2760 	SetDParam(0, tcc.num);
  2732 			(v->u.rail.track == TRACK_BIT_WORMHOLE && (v->direction & 2) != (realcoll->direction & 2)))
       
  2733 		return;
       
  2734 
       
  2735 	/* two drivers + passengers killed in train v */
       
  2736 	uint num = 2 + CountPassengersInTrain(v);
       
  2737 	if (!(coll->vehstatus & VS_CRASHED))
       
  2738 		/* two drivers + passengers killed in train coll (if it was not crashed already) */
       
  2739 		num += 2 + CountPassengersInTrain(coll);
       
  2740 
       
  2741 	SetVehicleCrashed(v);
       
  2742 	if (IsFrontEngine(coll)) SetVehicleCrashed(coll);
       
  2743 
       
  2744 	SetDParam(0, num);
       
  2745 	AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
  2761 	AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL,
  2746 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
  2762 		NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0),
  2747 		v->index,
  2763 		v->index,
  2748 		0
  2764 		0
  2749 	);
  2765 	);
  3282 }
  3298 }
  3283 
  3299 
  3284 
  3300 
  3285 void Train_Tick(Vehicle *v)
  3301 void Train_Tick(Vehicle *v)
  3286 {
  3302 {
  3287 	if (_age_cargo_skip_counter == 0 && v->cargo_days != 0xff)
  3303 	if (_age_cargo_skip_counter == 0) v->cargo.AgeCargo();
  3288 		v->cargo_days++;
       
  3289 
  3304 
  3290 	v->tick_counter++;
  3305 	v->tick_counter++;
  3291 
  3306 
  3292 	if (IsFrontEngine(v)) {
  3307 	if (IsFrontEngine(v)) {
       
  3308 		v->current_order_time++;
       
  3309 
  3293 		TrainLocoHandler(v, false);
  3310 		TrainLocoHandler(v, false);
  3294 
  3311 
  3295 		/* make sure vehicle wasn't deleted. */
  3312 		/* make sure vehicle wasn't deleted. */
  3296 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3313 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3297 			TrainLocoHandler(v, true);
  3314 			TrainLocoHandler(v, true);
  3351 	v->current_order.dest = depot->index;
  3368 	v->current_order.dest = depot->index;
  3352 	v->dest_tile = tfdd.tile;
  3369 	v->dest_tile = tfdd.tile;
  3353 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  3370 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  3354 }
  3371 }
  3355 
  3372 
  3356 int32 GetTrainRunningCost(const Vehicle *v)
  3373 Money GetTrainRunningCost(const Vehicle *v)
  3357 {
  3374 {
  3358 	int32 cost = 0;
  3375 	Money cost = 0;
  3359 
  3376 
  3360 	do {
  3377 	do {
  3361 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  3378 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
  3362 
  3379 
  3363 		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
  3380 		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost_base);
  3387 			if (tile != 0) v->dest_tile = tile;
  3404 			if (tile != 0) v->dest_tile = tile;
  3388 		}
  3405 		}
  3389 
  3406 
  3390 		if ((v->vehstatus & VS_STOPPED) == 0) {
  3407 		if ((v->vehstatus & VS_STOPPED) == 0) {
  3391 			/* running costs */
  3408 			/* running costs */
  3392 			int32 cost = GetTrainRunningCost(v) / 364;
  3409 			CommandCost cost(GetTrainRunningCost(v) / 364);
  3393 
  3410 
  3394 			v->profit_this_year -= cost >> 8;
  3411 			v->profit_this_year -= cost.GetCost() >> 8;
  3395 
  3412 
  3396 			SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  3413 			SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  3397 			SubtractMoneyFromPlayerFract(v->owner, cost);
  3414 			SubtractMoneyFromPlayerFract(v->owner, cost);
  3398 
  3415 
  3399 			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  3416 			InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
  3400 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3417 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3401 		}
  3418 		}
       
  3419 	} else if (IsTrainEngine(v)) {
       
  3420 		/* Also age engines that aren't front engines */
       
  3421 		AgeVehicle(v);
  3402 	}
  3422 	}
  3403 }
  3423 }
  3404 
  3424 
  3405 void TrainsYearlyLoop()
  3425 void TrainsYearlyLoop()
  3406 {
  3426 {