src/train_cmd.cpp
branchcpp_gui
changeset 6298 c30fe89622df
parent 6285 187e3ef04cc9
child 6303 84c215fc8eb8
equal deleted inserted replaced
6297:4bf29d14edba 6298:c30fe89622df
   138  */
   138  */
   139 void TrainConsistChanged(Vehicle* v)
   139 void TrainConsistChanged(Vehicle* v)
   140 {
   140 {
   141 	uint16 max_speed = 0xFFFF;
   141 	uint16 max_speed = 0xFFFF;
   142 
   142 
   143 	assert(v->type == VEH_Train);
   143 	assert(v->type == VEH_TRAIN);
   144 	assert(IsFrontEngine(v) || IsFreeWagon(v));
   144 	assert(IsFrontEngine(v) || IsFreeWagon(v));
   145 
   145 
   146 	const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
   146 	const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
   147 	EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE;
   147 	EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE;
   148 	v->u.rail.cached_total_length = 0;
   148 	v->u.rail.cached_total_length = 0;
   260 static bool TrainShouldStop(const Vehicle* v, TileIndex tile)
   260 static bool TrainShouldStop(const Vehicle* v, TileIndex tile)
   261 {
   261 {
   262 	const Order* o = &v->current_order;
   262 	const Order* o = &v->current_order;
   263 	StationID sid = GetStationIndex(tile);
   263 	StationID sid = GetStationIndex(tile);
   264 
   264 
   265 	assert(v->type == VEH_Train);
   265 	assert(v->type == VEH_TRAIN);
   266 	//When does a train drive through a station
   266 	//When does a train drive through a station
   267 	//first we deal with the "new nonstop handling"
   267 	//first we deal with the "new nonstop handling"
   268 	if (_patches.new_nonstop && o->flags & OF_NON_STOP && sid == o->dest) {
   268 	if (_patches.new_nonstop && o->flags & OF_NON_STOP && sid == o->dest) {
   269 		return false;
   269 		return false;
   270 	}
   270 	}
   543 		u->cargo_cap = rvi_artic->capacity;
   543 		u->cargo_cap = rvi_artic->capacity;
   544 		u->max_speed = 0;
   544 		u->max_speed = 0;
   545 		u->max_age = 0;
   545 		u->max_age = 0;
   546 		u->engine_type = engine_type;
   546 		u->engine_type = engine_type;
   547 		u->value = 0;
   547 		u->value = 0;
   548 		u->type = VEH_Train;
   548 		u->type = VEH_TRAIN;
   549 		u->subtype = 0;
   549 		u->subtype = 0;
   550 		SetArticulatedPart(u);
   550 		SetArticulatedPart(u);
   551 		u->cur_image = 0xAC2;
   551 		u->cur_image = 0xAC2;
   552 		u->random_bits = VehicleRandomBits();
   552 		u->random_bits = VehicleRandomBits();
   553 
   553 
   578 
   578 
   579 			Vehicle *u = NULL;
   579 			Vehicle *u = NULL;
   580 
   580 
   581 			Vehicle *w;
   581 			Vehicle *w;
   582 			FOR_ALL_VEHICLES(w) {
   582 			FOR_ALL_VEHICLES(w) {
   583 				if (w->type == VEH_Train && w->tile == tile &&
   583 				if (w->type == VEH_TRAIN && w->tile == tile &&
   584 				    IsFreeWagon(w) && w->engine_type == engine) {
   584 				    IsFreeWagon(w) && w->engine_type == engine) {
   585 					u = GetLastVehicleInChain(w);
   585 					u = GetLastVehicleInChain(w);
   586 					break;
   586 					break;
   587 				}
   587 				}
   588 			}
   588 			}
   621 //			v->day_counter = 0;
   621 //			v->day_counter = 0;
   622 
   622 
   623 			v->u.rail.railtype = rvi->railtype;
   623 			v->u.rail.railtype = rvi->railtype;
   624 
   624 
   625 			v->build_year = _cur_year;
   625 			v->build_year = _cur_year;
   626 			v->type = VEH_Train;
   626 			v->type = VEH_TRAIN;
   627 			v->cur_image = 0xAC2;
   627 			v->cur_image = 0xAC2;
   628 			v->random_bits = VehicleRandomBits();
   628 			v->random_bits = VehicleRandomBits();
   629 
   629 
   630 			AddArticulatedParts(vl);
   630 			AddArticulatedParts(vl);
   631 
   631 
   634 			VehiclePositionChanged(v);
   634 			VehiclePositionChanged(v);
   635 			TrainConsistChanged(GetFirstVehicleInChain(v));
   635 			TrainConsistChanged(GetFirstVehicleInChain(v));
   636 
   636 
   637 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   637 			InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   638 			if (IsLocalPlayer()) {
   638 			if (IsLocalPlayer()) {
   639 				InvalidateAutoreplaceWindow(VEH_Train); // updates the replace Train window
   639 				InvalidateAutoreplaceWindow(VEH_TRAIN); // updates the replace Train window
   640 			}
   640 			}
   641 			GetPlayer(_current_player)->num_engines[engine]++;
   641 			GetPlayer(_current_player)->num_engines[engine]++;
   642 		}
   642 		}
   643 	}
   643 	}
   644 
   644 
   649 static void NormalizeTrainVehInDepot(const Vehicle* u)
   649 static void NormalizeTrainVehInDepot(const Vehicle* u)
   650 {
   650 {
   651 	const Vehicle* v;
   651 	const Vehicle* v;
   652 
   652 
   653 	FOR_ALL_VEHICLES(v) {
   653 	FOR_ALL_VEHICLES(v) {
   654 		if (v->type == VEH_Train && IsFreeWagon(v) &&
   654 		if (v->type == VEH_TRAIN && IsFreeWagon(v) &&
   655 				v->tile == u->tile &&
   655 				v->tile == u->tile &&
   656 				v->u.rail.track == TRACK_BIT_DEPOT) {
   656 				v->u.rail.track == TRACK_BIT_DEPOT) {
   657 			if (CmdFailed(DoCommand(0, v->index | (u->index << 16), 1, DC_EXEC,
   657 			if (CmdFailed(DoCommand(0, v->index | (u->index << 16), 1, DC_EXEC,
   658 					CMD_MOVE_RAIL_VEHICLE)))
   658 					CMD_MOVE_RAIL_VEHICLE)))
   659 				break;
   659 				break;
   687 	if (building) v->next = u;
   687 	if (building) v->next = u;
   688 	u->engine_type = v->engine_type;
   688 	u->engine_type = v->engine_type;
   689 	u->build_year = v->build_year;
   689 	u->build_year = v->build_year;
   690 	if (building) v->value >>= 1;
   690 	if (building) v->value >>= 1;
   691 	u->value = v->value;
   691 	u->value = v->value;
   692 	u->type = VEH_Train;
   692 	u->type = VEH_TRAIN;
   693 	u->cur_image = 0xAC2;
   693 	u->cur_image = 0xAC2;
   694 	u->random_bits = VehicleRandomBits();
   694 	u->random_bits = VehicleRandomBits();
   695 	VehiclePositionChanged(u);
   695 	VehiclePositionChanged(u);
   696 }
   696 }
   697 
   697 
   702  *           bit 1 prevents any free cars from being added to the train
   702  *           bit 1 prevents any free cars from being added to the train
   703  */
   703  */
   704 int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   704 int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   705 {
   705 {
   706 	/* Check if the engine-type is valid (for the player) */
   706 	/* 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);
   707 	if (!IsEngineBuildable(p1, VEH_TRAIN, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   708 
   708 
   709 	/* Check if the train is actually being built in a depot belonging
   709 	/* 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 */
   710 	 * to the player. Doesn't matter if only the cost is queried */
   711 	if (!(flags & DC_QUERY_COST)) {
   711 	if (!(flags & DC_QUERY_COST)) {
   712 		if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
   712 		if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
   737 		if (!AllocateVehicles(vl, num_vehicles))
   737 		if (!AllocateVehicles(vl, num_vehicles))
   738 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   738 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   739 
   739 
   740 		Vehicle *v = vl[0];
   740 		Vehicle *v = vl[0];
   741 
   741 
   742 		UnitID unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_Train);
   742 		UnitID unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_TRAIN);
   743 		if (unit_num > _patches.max_trains)
   743 		if (unit_num > _patches.max_trains)
   744 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   744 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
   745 
   745 
   746 		if (flags & DC_EXEC) {
   746 		if (flags & DC_EXEC) {
   747 			DiagDirection dir = GetRailDepotDirection(tile);
   747 			DiagDirection dir = GetRailDepotDirection(tile);
   779 			_new_vehicle_id = v->index;
   779 			_new_vehicle_id = v->index;
   780 
   780 
   781 			v->service_interval = _patches.servint_trains;
   781 			v->service_interval = _patches.servint_trains;
   782 			v->date_of_last_service = _date;
   782 			v->date_of_last_service = _date;
   783 			v->build_year = _cur_year;
   783 			v->build_year = _cur_year;
   784 			v->type = VEH_Train;
   784 			v->type = VEH_TRAIN;
   785 			v->cur_image = 0xAC2;
   785 			v->cur_image = 0xAC2;
   786 			v->random_bits = VehicleRandomBits();
   786 			v->random_bits = VehicleRandomBits();
   787 
   787 
   788 			v->vehicle_flags = 0;
   788 			v->vehicle_flags = 0;
   789 			if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   789 			if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   816 
   816 
   817 			InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   817 			InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   818 			RebuildVehicleLists();
   818 			RebuildVehicleLists();
   819 			InvalidateWindow(WC_COMPANY, v->owner);
   819 			InvalidateWindow(WC_COMPANY, v->owner);
   820 			if (IsLocalPlayer())
   820 			if (IsLocalPlayer())
   821 				InvalidateAutoreplaceWindow(VEH_Train); // updates the replace Train window
   821 				InvalidateAutoreplaceWindow(VEH_TRAIN); // updates the replace Train window
   822 
   822 
   823 			GetPlayer(_current_player)->num_engines[p1]++;
   823 			GetPlayer(_current_player)->num_engines[p1]++;
   824 		}
   824 		}
   825 	}
   825 	}
   826 
   826 
   895 	Vehicle *dst;
   895 	Vehicle *dst;
   896 	EngineID eng = src->engine_type;
   896 	EngineID eng = src->engine_type;
   897 	TileIndex tile = src->tile;
   897 	TileIndex tile = src->tile;
   898 
   898 
   899 	FOR_ALL_VEHICLES(dst) {
   899 	FOR_ALL_VEHICLES(dst) {
   900 		if (dst->type == VEH_Train && IsFreeWagon(dst) && dst->tile == tile) {
   900 		if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile) {
   901 			// check so all vehicles in the line have the same engine.
   901 			// check so all vehicles in the line have the same engine.
   902 			Vehicle *v = dst;
   902 			Vehicle *v = dst;
   903 
   903 
   904 			while (v->engine_type == eng) {
   904 			while (v->engine_type == eng) {
   905 				v = v->next;
   905 				v = v->next;
   962 
   962 
   963 	if (!IsValidVehicleID(s)) return CMD_ERROR;
   963 	if (!IsValidVehicleID(s)) return CMD_ERROR;
   964 
   964 
   965 	Vehicle *src = GetVehicle(s);
   965 	Vehicle *src = GetVehicle(s);
   966 
   966 
   967 	if (src->type != VEH_Train || !CheckOwnership(src->owner)) return CMD_ERROR;
   967 	if (src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR;
   968 
   968 
   969 	// if nothing is selected as destination, try and find a matching vehicle to drag to.
   969 	// if nothing is selected as destination, try and find a matching vehicle to drag to.
   970 	Vehicle *dst;
   970 	Vehicle *dst;
   971 	if (d == INVALID_VEHICLE) {
   971 	if (d == INVALID_VEHICLE) {
   972 		dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
   972 		dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
   973 	} else {
   973 	} else {
   974 		if (!IsValidVehicleID(d)) return CMD_ERROR;
   974 		if (!IsValidVehicleID(d)) return CMD_ERROR;
   975 		dst = GetVehicle(d);
   975 		dst = GetVehicle(d);
   976 		if (dst->type != VEH_Train || !CheckOwnership(dst->owner)) return CMD_ERROR;
   976 		if (dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR;
   977 	}
   977 	}
   978 
   978 
   979 	// if an articulated part is being handled, deal with its parent vehicle
   979 	// if an articulated part is being handled, deal with its parent vehicle
   980 	while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src);
   980 	while (IsArticulatedPart(src)) src = GetPrevVehicleInChain(src);
   981 	if (dst != NULL) {
   981 	if (dst != NULL) {
  1076 		}
  1076 		}
  1077 	}
  1077 	}
  1078 
  1078 
  1079 	// moving a loco to a new line?, then we need to assign a unitnumber.
  1079 	// moving a loco to a new line?, then we need to assign a unitnumber.
  1080 	if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
  1080 	if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) {
  1081 		UnitID unit_num = GetFreeUnitNumber(VEH_Train);
  1081 		UnitID unit_num = GetFreeUnitNumber(VEH_TRAIN);
  1082 		if (unit_num > _patches.max_trains)
  1082 		if (unit_num > _patches.max_trains)
  1083 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
  1083 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
  1084 
  1084 
  1085 		if (flags & DC_EXEC) src->unitnumber = unit_num;
  1085 		if (flags & DC_EXEC) src->unitnumber = unit_num;
  1086 	}
  1086 	}
  1240 {
  1240 {
  1241 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1241 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1242 
  1242 
  1243 	Vehicle *v = GetVehicle(p1);
  1243 	Vehicle *v = GetVehicle(p1);
  1244 
  1244 
  1245 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1245 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1246 
  1246 
  1247 	/* Check if this train can be started/stopped. The callback will fail or
  1247 	/* Check if this train can be started/stopped. The callback will fail or
  1248 	 * return 0xFF if it can. */
  1248 	 * return 0xFF if it can. */
  1249 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
  1249 	uint16 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
  1250 	if (callback != CALLBACK_FAILED && callback != 0xFF) {
  1250 	if (callback != CALLBACK_FAILED && callback != 0xFF) {
  1281 {
  1281 {
  1282 	if (!IsValidVehicleID(p1) || p2 > 2) return CMD_ERROR;
  1282 	if (!IsValidVehicleID(p1) || p2 > 2) return CMD_ERROR;
  1283 
  1283 
  1284 	Vehicle *v = GetVehicle(p1);
  1284 	Vehicle *v = GetVehicle(p1);
  1285 
  1285 
  1286 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1286 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1287 
  1287 
  1288 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
  1288 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
  1289 
  1289 
  1290 	while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v);
  1290 	while (IsArticulatedPart(v)) v = GetPrevVehicleInChain(v);
  1291 	Vehicle *first = GetFirstVehicleInChain(v);
  1291 	Vehicle *first = GetFirstVehicleInChain(v);
  1560 }
  1560 }
  1561 
  1561 
  1562 /* Check if the vehicle is a train and is on the tile we are testing */
  1562 /* Check if the vehicle is a train and is on the tile we are testing */
  1563 static void *TestTrainOnCrossing(Vehicle *v, void *data)
  1563 static void *TestTrainOnCrossing(Vehicle *v, void *data)
  1564 {
  1564 {
  1565 	if (v->tile != *(const TileIndex*)data || v->type != VEH_Train) return NULL;
  1565 	if (v->tile != *(const TileIndex*)data || v->type != VEH_TRAIN) return NULL;
  1566 	return v;
  1566 	return v;
  1567 }
  1567 }
  1568 
  1568 
  1569 static void DisableTrainCrossing(TileIndex tile)
  1569 static void DisableTrainCrossing(TileIndex tile)
  1570 {
  1570 {
  1667 {
  1667 {
  1668 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1668 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1669 
  1669 
  1670 	Vehicle *v = GetVehicle(p1);
  1670 	Vehicle *v = GetVehicle(p1);
  1671 
  1671 
  1672 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1672 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1673 
  1673 
  1674 	if (p2) {
  1674 	if (p2) {
  1675 		// turn a single unit around
  1675 		// turn a single unit around
  1676 
  1676 
  1677 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1677 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1715 {
  1715 {
  1716 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1716 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1717 
  1717 
  1718 	Vehicle *v = GetVehicle(p1);
  1718 	Vehicle *v = GetVehicle(p1);
  1719 
  1719 
  1720 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1720 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1721 
  1721 
  1722 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1722 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1723 
  1723 
  1724 	return 0;
  1724 	return 0;
  1725 }
  1725 }
  1738 
  1738 
  1739 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1739 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1740 
  1740 
  1741 	Vehicle *v = GetVehicle(p1);
  1741 	Vehicle *v = GetVehicle(p1);
  1742 
  1742 
  1743 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1743 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1744 	if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
  1744 	if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
  1745 
  1745 
  1746 	/* Check cargo */
  1746 	/* Check cargo */
  1747 	if (new_cid > NUM_CARGO) return CMD_ERROR;
  1747 	if (new_cid > NUM_CARGO) return CMD_ERROR;
  1748 
  1748 
  1820 	if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1)));
  1820 	if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1)));
  1821 
  1821 
  1822 	return cost;
  1822 	return cost;
  1823 }
  1823 }
  1824 
  1824 
  1825 typedef struct TrainFindDepotData {
  1825 struct TrainFindDepotData {
  1826 	uint best_length;
  1826 	uint best_length;
  1827 	TileIndex tile;
  1827 	TileIndex tile;
  1828 	PlayerID owner;
  1828 	PlayerID owner;
  1829 	/**
  1829 	/**
  1830 	 * true if reversing is necessary for the train to get to this depot
  1830 	 * true if reversing is necessary for the train to get to this depot
  1831 	 * This value is unused when new depot finding and NPF are both disabled
  1831 	 * This value is unused when new depot finding and NPF are both disabled
  1832 	 */
  1832 	 */
  1833 	bool reverse;
  1833 	bool reverse;
  1834 } TrainFindDepotData;
  1834 };
  1835 
  1835 
  1836 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
  1836 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
  1837 {
  1837 {
  1838 	if (IsTileType(tile, MP_RAILWAY) &&
  1838 	if (IsTileType(tile, MP_RAILWAY) &&
  1839 			IsTileOwner(tile, tfdd->owner) &&
  1839 			IsTileOwner(tile, tfdd->owner) &&
  1916 int32 CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1916 int32 CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1917 {
  1917 {
  1918 	if (p2 & DEPOT_MASS_SEND) {
  1918 	if (p2 & DEPOT_MASS_SEND) {
  1919 		/* Mass goto depot requested */
  1919 		/* Mass goto depot requested */
  1920 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1920 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1921 		return SendAllVehiclesToDepot(VEH_Train, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1921 		return SendAllVehiclesToDepot(VEH_TRAIN, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1922 	}
  1922 	}
  1923 
  1923 
  1924 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1924 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1925 
  1925 
  1926 	Vehicle *v = GetVehicle(p1);
  1926 	Vehicle *v = GetVehicle(p1);
  1927 
  1927 
  1928 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1928 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1929 
  1929 
  1930 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
  1930 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
  1931 
  1931 
  1932 	if (v->current_order.type == OT_GOTO_DEPOT) {
  1932 	if (v->current_order.type == OT_GOTO_DEPOT) {
  1933 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
  1933 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
  1977 
  1977 
  1978 	return 0;
  1978 	return 0;
  1979 }
  1979 }
  1980 
  1980 
  1981 
  1981 
  1982 void OnTick_Train(void)
  1982 void OnTick_Train()
  1983 {
  1983 {
  1984 	_age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1);
  1984 	_age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1);
  1985 }
  1985 }
  1986 
  1986 
  1987 static const int8 _vehicle_smoke_pos[8] = {
  1987 static const int8 _vehicle_smoke_pos[8] = {
  2132 
  2132 
  2133 	return false;
  2133 	return false;
  2134 }
  2134 }
  2135 
  2135 
  2136 /* Check for station tiles */
  2136 /* Check for station tiles */
  2137 typedef struct TrainTrackFollowerData {
  2137 struct TrainTrackFollowerData {
  2138 	TileIndex dest_coords;
  2138 	TileIndex dest_coords;
  2139 	StationID station_index; // station index we're heading for
  2139 	StationID station_index; // station index we're heading for
  2140 	uint best_bird_dist;
  2140 	uint best_bird_dist;
  2141 	uint best_track_dist;
  2141 	uint best_track_dist;
  2142 	TrackdirByte best_track;
  2142 	TrackdirByte best_track;
  2143 } TrainTrackFollowerData;
  2143 };
  2144 
  2144 
  2145 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2145 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2146 {
  2146 {
  2147 	// heading for nowhere?
  2147 	// heading for nowhere?
  2148 	if (ttfd->dest_coords == 0) return false;
  2148 	if (ttfd->dest_coords == 0) return false;
  2452 
  2452 
  2453 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2453 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2454 
  2454 
  2455 	// If no order, do nothing.
  2455 	// If no order, do nothing.
  2456 	if (order == NULL) {
  2456 	if (order == NULL) {
  2457 		v->current_order.type = OT_NOTHING;
  2457 		v->current_order.Free();
  2458 		v->current_order.flags = 0;
       
  2459 		v->dest_tile = 0;
  2458 		v->dest_tile = 0;
  2460 		return false;
  2459 		return false;
  2461 	}
  2460 	}
  2462 
  2461 
  2463 	// If it is unchanged, keep it.
  2462 	// If it is unchanged, keep it.
  2710 			!IsFrontEngine(v) ||
  2709 			!IsFrontEngine(v) ||
  2711 			HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
  2710 			HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
  2712 		);
  2711 		);
  2713 }
  2712 }
  2714 
  2713 
  2715 typedef struct {
  2714 struct RailtypeSlowdownParams {
  2716 	byte small_turn, large_turn;
  2715 	byte small_turn, large_turn;
  2717 	byte z_up; // fraction to remove when moving up
  2716 	byte z_up; // fraction to remove when moving up
  2718 	byte z_down; // fraction to remove when moving down
  2717 	byte z_down; // fraction to remove when moving down
  2719 } RailtypeSlowdownParams;
  2718 };
  2720 
  2719 
  2721 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2720 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2722 	// normal accel
  2721 	// normal accel
  2723 	{256 / 4, 256 / 2, 256 / 4, 2}, // normal
  2722 	{256 / 4, 256 / 2, 256 / 4, 2}, // normal
  2724 	{256 / 4, 256 / 2, 256 / 4, 2}, // electrified
  2723 	{256 / 4, 256 / 2, 256 / 4, 2}, // electrified
  2766 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2765 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2767 	}
  2766 	}
  2768 }
  2767 }
  2769 
  2768 
  2770 
  2769 
  2771 typedef struct TrainCollideChecker {
  2770 struct TrainCollideChecker {
  2772 	const Vehicle *v;
  2771 	const Vehicle *v;
  2773 	const Vehicle *v_skip;
  2772 	const Vehicle *v_skip;
  2774 } TrainCollideChecker;
  2773 };
  2775 
  2774 
  2776 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2775 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2777 {
  2776 {
  2778 	const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2777 	const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2779 
  2778 
  2780 	if (v != tcc->v &&
  2779 	if (v != tcc->v &&
  2781 			v != tcc->v_skip &&
  2780 			v != tcc->v_skip &&
  2782 			v->type == VEH_Train &&
  2781 			v->type == VEH_TRAIN &&
  2783 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2782 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2784 			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
  2783 			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
  2785 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2784 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2786 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
  2785 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
  2787 		return v;
  2786 		return v;
  2859 
  2858 
  2860 	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
  2859 	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
  2861 	SndPlayVehicleFx(SND_13_BIG_CRASH, v);
  2860 	SndPlayVehicleFx(SND_13_BIG_CRASH, v);
  2862 }
  2861 }
  2863 
  2862 
  2864 typedef struct VehicleAtSignalData {
  2863 struct VehicleAtSignalData {
  2865 	TileIndex tile;
  2864 	TileIndex tile;
  2866 	Direction direction;
  2865 	Direction direction;
  2867 } VehicleAtSignalData;
  2866 };
  2868 
  2867 
  2869 static void *CheckVehicleAtSignal(Vehicle *v, void *data)
  2868 static void *CheckVehicleAtSignal(Vehicle *v, void *data)
  2870 {
  2869 {
  2871 	const VehicleAtSignalData* vasd = (VehicleAtSignalData*)data;
  2870 	const VehicleAtSignalData* vasd = (VehicleAtSignalData*)data;
  2872 
  2871 
  2873 	if (v->type == VEH_Train && IsFrontEngine(v) && v->tile == vasd->tile) {
  2872 	if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == vasd->tile) {
  2874 		DirDiff diff = ChangeDirDiff(DirDifference(v->direction, vasd->direction), DIRDIFF_90RIGHT);
  2873 		DirDiff diff = ChangeDirDiff(DirDifference(v->direction, vasd->direction), DIRDIFF_90RIGHT);
  2875 
  2874 
  2876 		if (diff == DIRDIFF_90RIGHT || (v->cur_speed <= 5 && diff <= DIRDIFF_REVERSE)) return v;
  2875 		if (diff == DIRDIFF_90RIGHT || (v->cur_speed <= 5 && diff <= DIRDIFF_REVERSE)) return v;
  2877 	}
  2876 	}
  2878 	return NULL;
  2877 	return NULL;
  2908 						TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
  2907 						TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
  2909 						return;
  2908 						return;
  2910 					}
  2909 					}
  2911 
  2910 
  2912 					if (v->current_order.type == OT_LEAVESTATION) {
  2911 					if (v->current_order.type == OT_LEAVESTATION) {
  2913 						v->current_order.type = OT_NOTHING;
  2912 						v->current_order.Free();
  2914 						v->current_order.flags = 0;
       
  2915 						InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2913 						InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2916 					}
  2914 					}
  2917 				}
  2915 				}
  2918 			} else {
  2916 			} else {
  2919 				/* A new tile is about to be entered. */
  2917 				/* A new tile is about to be entered. */
  3389 
  3387 
  3390 	if (IsFrontEngine(v)) {
  3388 	if (IsFrontEngine(v)) {
  3391 		TrainLocoHandler(v, false);
  3389 		TrainLocoHandler(v, false);
  3392 
  3390 
  3393 		// make sure vehicle wasn't deleted.
  3391 		// make sure vehicle wasn't deleted.
  3394 		if (v->type == VEH_Train && IsFrontEngine(v))
  3392 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3395 			TrainLocoHandler(v, true);
  3393 			TrainLocoHandler(v, true);
  3396 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3394 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3397 		// Delete flooded standalone wagon
  3395 		// Delete flooded standalone wagon
  3398 		if (++v->u.rail.crash_anim_pos >= 4400)
  3396 		if (++v->u.rail.crash_anim_pos >= 4400)
  3399 			DeleteVehicle(v);
  3397 			DeleteVehicle(v);
  3493 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3491 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3494 		}
  3492 		}
  3495 	}
  3493 	}
  3496 }
  3494 }
  3497 
  3495 
  3498 void TrainsYearlyLoop(void)
  3496 void TrainsYearlyLoop()
  3499 {
  3497 {
  3500 	Vehicle *v;
  3498 	Vehicle *v;
  3501 
  3499 
  3502 	FOR_ALL_VEHICLES(v) {
  3500 	FOR_ALL_VEHICLES(v) {
  3503 		if (v->type == VEH_Train && IsFrontEngine(v)) {
  3501 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3504 			// show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list)
  3502 			// show warning if train is not generating enough income last 2 years (corresponds to a red icon in the vehicle list)
  3505 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3503 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3506 				SetDParam(1, v->profit_this_year);
  3504 				SetDParam(1, v->profit_this_year);
  3507 				SetDParam(0, v->unitnumber);
  3505 				SetDParam(0, v->unitnumber);
  3508 				AddNewsItem(
  3506 				AddNewsItem(
  3518 		}
  3516 		}
  3519 	}
  3517 	}
  3520 }
  3518 }
  3521 
  3519 
  3522 
  3520 
  3523 void InitializeTrains(void)
  3521 void InitializeTrains()
  3524 {
  3522 {
  3525 	_age_cargo_skip_counter = 1;
  3523 	_age_cargo_skip_counter = 1;
  3526 }
  3524 }
  3527 
  3525 
  3528 /*
  3526 /*
  3529  * Link front and rear multiheaded engines to each other
  3527  * Link front and rear multiheaded engines to each other
  3530  * This is done when loading a savegame
  3528  * This is done when loading a savegame
  3531  */
  3529  */
  3532 void ConnectMultiheadedTrains(void)
  3530 void ConnectMultiheadedTrains()
  3533 {
  3531 {
  3534 	Vehicle *v;
  3532 	Vehicle *v;
  3535 
  3533 
  3536 	FOR_ALL_VEHICLES(v) {
  3534 	FOR_ALL_VEHICLES(v) {
  3537 		if (v->type == VEH_Train) {
  3535 		if (v->type == VEH_TRAIN) {
  3538 			v->u.rail.other_multiheaded_part = NULL;
  3536 			v->u.rail.other_multiheaded_part = NULL;
  3539 		}
  3537 		}
  3540 	}
  3538 	}
  3541 
  3539 
  3542 	FOR_ALL_VEHICLES(v) {
  3540 	FOR_ALL_VEHICLES(v) {
  3543 		if (v->type == VEH_Train && IsFrontEngine(v)) {
  3541 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3544 			Vehicle *u = v;
  3542 			Vehicle *u = v;
  3545 
  3543 
  3546 			BEGIN_ENUM_WAGONS(u) {
  3544 			BEGIN_ENUM_WAGONS(u) {
  3547 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
  3545 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
  3548 
  3546 
  3575 
  3573 
  3576 /*
  3574 /*
  3577  *  Converts all trains to the new subtype format introduced in savegame 16.2
  3575  *  Converts all trains to the new subtype format introduced in savegame 16.2
  3578  *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
  3576  *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
  3579  */
  3577  */
  3580 void ConvertOldMultiheadToNew(void)
  3578 void ConvertOldMultiheadToNew()
  3581 {
  3579 {
  3582 	Vehicle *v;
  3580 	Vehicle *v;
  3583 	FOR_ALL_VEHICLES(v) {
  3581 	FOR_ALL_VEHICLES(v) {
  3584 		if (v->type == VEH_Train) {
  3582 		if (v->type == VEH_TRAIN) {
  3585 			SETBIT(v->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
  3583 			SETBIT(v->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
  3586 		}
  3584 		}
  3587 	}
  3585 	}
  3588 
  3586 
  3589 	FOR_ALL_VEHICLES(v) {
  3587 	FOR_ALL_VEHICLES(v) {
  3590 		if (v->type == VEH_Train) {
  3588 		if (v->type == VEH_TRAIN) {
  3591 			if (HASBIT(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
  3589 			if (HASBIT(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
  3592 				Vehicle *u = v;
  3590 				Vehicle *u = v;
  3593 
  3591 
  3594 				BEGIN_ENUM_WAGONS(u) {
  3592 				BEGIN_ENUM_WAGONS(u) {
  3595 					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
  3593 					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);