src/train_cmd.cpp
branchgamebalance
changeset 9895 7bd07f43b0e3
parent 6502 7ca154aca2b7
child 9896 2473804114de
equal deleted inserted replaced
9894:70d78ac95d6c 9895:7bd07f43b0e3
   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);
  1332 
  1332 
  1333 				/* 2.1 If the first wagon is sold, update the first-> pointers to NULL */
  1333 				/* 2.1 If the first wagon is sold, update the first-> pointers to NULL */
  1334 				for (Vehicle *tmp = first; tmp != NULL; tmp = tmp->next) tmp->first = NULL;
  1334 				for (Vehicle *tmp = first; tmp != NULL; tmp = tmp->next) tmp->first = NULL;
  1335 
  1335 
  1336 				/* 2.2 If there are wagons present after the deleted front engine, check
  1336 				/* 2.2 If there are wagons present after the deleted front engine, check
  1337          * if the second wagon (which will be first) is an engine. If it is one,
  1337 				 * if the second wagon (which will be first) is an engine. If it is one,
  1338          * promote it as a new train, retaining the unitnumber, orders */
  1338 				 * promote it as a new train, retaining the unitnumber, orders */
  1339 				if (new_f != NULL) {
  1339 				if (new_f != NULL && IsTrainEngine(new_f)) {
  1340 					if (IsTrainEngine(new_f)) {
  1340 					switch_engine = true;
  1341 						switch_engine = true;
  1341 					/* Copy important data from the front engine */
  1342 						/* Copy important data from the front engine */
  1342 					new_f->unitnumber      = first->unitnumber;
  1343 						new_f->unitnumber = first->unitnumber;
  1343 					new_f->current_order   = first->current_order;
  1344 						new_f->current_order = first->current_order;
  1344 					new_f->cur_order_index = first->cur_order_index;
  1345 						new_f->cur_order_index = first->cur_order_index;
  1345 					new_f->orders          = first->orders;
  1346 						new_f->orders = first->orders;
  1346 					new_f->num_orders      = first->num_orders;
  1347 						if (first->prev_shared != NULL) {
  1347 
  1348 							first->prev_shared->next_shared = new_f;
  1348 					if (first->prev_shared != NULL) {
  1349 							new_f->prev_shared = first->prev_shared;
  1349 						first->prev_shared->next_shared = new_f;
  1350 						}
  1350 						new_f->prev_shared = first->prev_shared;
  1351 
       
  1352 						if (first->next_shared != NULL) {
       
  1353 							first->next_shared->prev_shared = new_f;
       
  1354 							new_f->next_shared = first->next_shared;
       
  1355 						}
       
  1356 
       
  1357 						new_f->num_orders = first->num_orders;
       
  1358 						first->orders = NULL; // XXX - to not to delete the orders */
       
  1359 						if (IsLocalPlayer()) ShowTrainViewWindow(new_f);
       
  1360 					}
  1351 					}
       
  1352 
       
  1353 					if (first->next_shared != NULL) {
       
  1354 						first->next_shared->prev_shared = new_f;
       
  1355 						new_f->next_shared = first->next_shared;
       
  1356 					}
       
  1357 
       
  1358 					/*
       
  1359 					 * Remove all order information from the front train, to
       
  1360 					 * prevent the order and the shared order list to be
       
  1361 					 * destroyed by Destroy/DeleteVehicle.
       
  1362 					 */
       
  1363 					first->orders      = NULL;
       
  1364 					first->prev_shared = NULL;
       
  1365 					first->next_shared = NULL;
       
  1366 
       
  1367 					if (IsLocalPlayer()) ShowTrainViewWindow(new_f);
  1361 				}
  1368 				}
  1362 			}
  1369 			}
  1363 
  1370 
  1364 			/* 3. Delete the requested wagon */
  1371 			/* 3. Delete the requested wagon */
  1365 			cost -= v->value;
  1372 			cost -= v->value;
  1560 }
  1567 }
  1561 
  1568 
  1562 /* Check if the vehicle is a train and is on the tile we are testing */
  1569 /* Check if the vehicle is a train and is on the tile we are testing */
  1563 static void *TestTrainOnCrossing(Vehicle *v, void *data)
  1570 static void *TestTrainOnCrossing(Vehicle *v, void *data)
  1564 {
  1571 {
  1565 	if (v->tile != *(const TileIndex*)data || v->type != VEH_Train) return NULL;
  1572 	if (v->tile != *(const TileIndex*)data || v->type != VEH_TRAIN) return NULL;
  1566 	return v;
  1573 	return v;
  1567 }
  1574 }
  1568 
  1575 
  1569 static void DisableTrainCrossing(TileIndex tile)
  1576 static void DisableTrainCrossing(TileIndex tile)
  1570 {
  1577 {
  1667 {
  1674 {
  1668 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1675 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1669 
  1676 
  1670 	Vehicle *v = GetVehicle(p1);
  1677 	Vehicle *v = GetVehicle(p1);
  1671 
  1678 
  1672 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1679 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1673 
  1680 
  1674 	if (p2) {
  1681 	if (p2) {
  1675 		// turn a single unit around
  1682 		// turn a single unit around
  1676 
  1683 
  1677 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1684 		if (IsMultiheaded(v) || HASBIT(EngInfo(v->engine_type)->callbackmask, CBM_ARTIC_ENGINE)) {
  1715 {
  1722 {
  1716 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1723 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1717 
  1724 
  1718 	Vehicle *v = GetVehicle(p1);
  1725 	Vehicle *v = GetVehicle(p1);
  1719 
  1726 
  1720 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1727 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1721 
  1728 
  1722 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1729 	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
  1723 
  1730 
  1724 	return 0;
  1731 	return 0;
  1725 }
  1732 }
  1738 
  1745 
  1739 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1746 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1740 
  1747 
  1741 	Vehicle *v = GetVehicle(p1);
  1748 	Vehicle *v = GetVehicle(p1);
  1742 
  1749 
  1743 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1750 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1744 	if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
  1751 	if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
  1745 
  1752 
  1746 	/* Check cargo */
  1753 	/* Check cargo */
  1747 	if (new_cid > NUM_CARGO) return CMD_ERROR;
  1754 	if (new_cid >= NUM_CARGO) return CMD_ERROR;
  1748 
  1755 
  1749 	SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  1756 	SET_EXPENSES_TYPE(EXPENSES_TRAIN_RUN);
  1750 
  1757 
  1751 	int32 cost = 0;
  1758 	int32 cost = 0;
  1752 	uint num = 0;
  1759 	uint num = 0;
  1820 	if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1)));
  1827 	if (flags & DC_EXEC) TrainConsistChanged(GetFirstVehicleInChain(GetVehicle(p1)));
  1821 
  1828 
  1822 	return cost;
  1829 	return cost;
  1823 }
  1830 }
  1824 
  1831 
  1825 typedef struct TrainFindDepotData {
  1832 struct TrainFindDepotData {
  1826 	uint best_length;
  1833 	uint best_length;
  1827 	TileIndex tile;
  1834 	TileIndex tile;
  1828 	PlayerID owner;
  1835 	PlayerID owner;
  1829 	/**
  1836 	/**
  1830 	 * true if reversing is necessary for the train to get to this depot
  1837 	 * 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
  1838 	 * This value is unused when new depot finding and NPF are both disabled
  1832 	 */
  1839 	 */
  1833 	bool reverse;
  1840 	bool reverse;
  1834 } TrainFindDepotData;
  1841 };
  1835 
  1842 
  1836 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
  1843 static bool NtpCallbFindDepot(TileIndex tile, TrainFindDepotData *tfdd, int track, uint length)
  1837 {
  1844 {
  1838 	if (IsTileType(tile, MP_RAILWAY) &&
  1845 	if (IsTileType(tile, MP_RAILWAY) &&
  1839 			IsTileOwner(tile, tfdd->owner) &&
  1846 			IsTileOwner(tile, tfdd->owner) &&
  1916 int32 CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1923 int32 CmdSendTrainToDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1917 {
  1924 {
  1918 	if (p2 & DEPOT_MASS_SEND) {
  1925 	if (p2 & DEPOT_MASS_SEND) {
  1919 		/* Mass goto depot requested */
  1926 		/* Mass goto depot requested */
  1920 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1927 		if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
  1921 		return SendAllVehiclesToDepot(VEH_Train, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1928 		return SendAllVehiclesToDepot(VEH_TRAIN, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
  1922 	}
  1929 	}
  1923 
  1930 
  1924 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1931 	if (!IsValidVehicleID(p1)) return CMD_ERROR;
  1925 
  1932 
  1926 	Vehicle *v = GetVehicle(p1);
  1933 	Vehicle *v = GetVehicle(p1);
  1927 
  1934 
  1928 	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
  1935 	if (v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
  1929 
  1936 
  1930 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
  1937 	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
  1931 
  1938 
  1932 	if (v->current_order.type == OT_GOTO_DEPOT) {
  1939 	if (v->current_order.type == OT_GOTO_DEPOT) {
  1933 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
  1940 		if (!!(p2 & DEPOT_SERVICE) == HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT)) {
  1977 
  1984 
  1978 	return 0;
  1985 	return 0;
  1979 }
  1986 }
  1980 
  1987 
  1981 
  1988 
  1982 void OnTick_Train(void)
  1989 void OnTick_Train()
  1983 {
  1990 {
  1984 	_age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1);
  1991 	_age_cargo_skip_counter = (_age_cargo_skip_counter == 0) ? 184 : (_age_cargo_skip_counter - 1);
  1985 }
  1992 }
  1986 
  1993 
  1987 static const int8 _vehicle_smoke_pos[8] = {
  1994 static const int8 _vehicle_smoke_pos[8] = {
  2132 
  2139 
  2133 	return false;
  2140 	return false;
  2134 }
  2141 }
  2135 
  2142 
  2136 /* Check for station tiles */
  2143 /* Check for station tiles */
  2137 typedef struct TrainTrackFollowerData {
  2144 struct TrainTrackFollowerData {
  2138 	TileIndex dest_coords;
  2145 	TileIndex dest_coords;
  2139 	StationID station_index; // station index we're heading for
  2146 	StationID station_index; // station index we're heading for
  2140 	uint best_bird_dist;
  2147 	uint best_bird_dist;
  2141 	uint best_track_dist;
  2148 	uint best_track_dist;
  2142 	TrackdirByte best_track;
  2149 	TrackdirByte best_track;
  2143 } TrainTrackFollowerData;
  2150 };
  2144 
  2151 
  2145 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2152 static bool NtpCallbFindStation(TileIndex tile, TrainTrackFollowerData *ttfd, Trackdir track, uint length)
  2146 {
  2153 {
  2147 	// heading for nowhere?
  2154 	// heading for nowhere?
  2148 	if (ttfd->dest_coords == 0) return false;
  2155 	if (ttfd->dest_coords == 0) return false;
  2156 		/* We do not check for dest_coords if we have a station_index,
  2163 		/* We do not check for dest_coords if we have a station_index,
  2157 		 * because in that case the dest_coords are just an
  2164 		 * because in that case the dest_coords are just an
  2158 		 * approximation of where the station is */
  2165 		 * approximation of where the station is */
  2159 		// found station
  2166 		// found station
  2160 		ttfd->best_track = track;
  2167 		ttfd->best_track = track;
       
  2168 		ttfd->best_bird_dist = 0;
  2161 		return true;
  2169 		return true;
  2162 	} else {
  2170 	} else {
  2163 		// didn't find station, keep track of the best path so far.
  2171 		// didn't find station, keep track of the best path so far.
  2164 		uint dist = DistanceManhattan(tile, ttfd->dest_coords);
  2172 		uint dist = DistanceManhattan(tile, ttfd->dest_coords);
  2165 		if (dist < ttfd->best_bird_dist) {
  2173 		if (dist < ttfd->best_bird_dist) {
  2452 
  2460 
  2453 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2461 	const Order *order = GetVehicleOrder(v, v->cur_order_index);
  2454 
  2462 
  2455 	// If no order, do nothing.
  2463 	// If no order, do nothing.
  2456 	if (order == NULL) {
  2464 	if (order == NULL) {
  2457 		v->current_order.type = OT_NOTHING;
  2465 		v->current_order.Free();
  2458 		v->current_order.flags = 0;
       
  2459 		v->dest_tile = 0;
  2466 		v->dest_tile = 0;
  2460 		return false;
  2467 		return false;
  2461 	}
  2468 	}
  2462 
  2469 
  2463 	// If it is unchanged, keep it.
  2470 	// If it is unchanged, keep it.
  2710 			!IsFrontEngine(v) ||
  2717 			!IsFrontEngine(v) ||
  2711 			HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
  2718 			HASBIT(v->u.rail.compatible_railtypes, GetRailType(tile))
  2712 		);
  2719 		);
  2713 }
  2720 }
  2714 
  2721 
  2715 typedef struct {
  2722 struct RailtypeSlowdownParams {
  2716 	byte small_turn, large_turn;
  2723 	byte small_turn, large_turn;
  2717 	byte z_up; // fraction to remove when moving up
  2724 	byte z_up; // fraction to remove when moving up
  2718 	byte z_down; // fraction to remove when moving down
  2725 	byte z_down; // fraction to remove when moving down
  2719 } RailtypeSlowdownParams;
  2726 };
  2720 
  2727 
  2721 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2728 static const RailtypeSlowdownParams _railtype_slowdown[] = {
  2722 	// normal accel
  2729 	// normal accel
  2723 	{256 / 4, 256 / 2, 256 / 4, 2}, // normal
  2730 	{256 / 4, 256 / 2, 256 / 4, 2}, // normal
  2724 	{256 / 4, 256 / 2, 256 / 4, 2}, // electrified
  2731 	{256 / 4, 256 / 2, 256 / 4, 2}, // electrified
  2766 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2773 		UpdateSignalsOnSegment(tile, _otherside_signal_directions[i]);
  2767 	}
  2774 	}
  2768 }
  2775 }
  2769 
  2776 
  2770 
  2777 
  2771 typedef struct TrainCollideChecker {
  2778 struct TrainCollideChecker {
  2772 	const Vehicle *v;
  2779 	const Vehicle *v;
  2773 	const Vehicle *v_skip;
  2780 	const Vehicle *v_skip;
  2774 } TrainCollideChecker;
  2781 };
  2775 
  2782 
  2776 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2783 static void *FindTrainCollideEnum(Vehicle *v, void *data)
  2777 {
  2784 {
  2778 	const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2785 	const TrainCollideChecker* tcc = (TrainCollideChecker*)data;
  2779 
  2786 
  2780 	if (v != tcc->v &&
  2787 	if (v != tcc->v &&
  2781 			v != tcc->v_skip &&
  2788 			v != tcc->v_skip &&
  2782 			v->type == VEH_Train &&
  2789 			v->type == VEH_TRAIN &&
  2783 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2790 			v->u.rail.track != TRACK_BIT_DEPOT &&
  2784 			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
  2791 			myabs(v->z_pos - tcc->v->z_pos) <= 6 &&
  2785 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2792 			myabs(v->x_pos - tcc->v->x_pos) < 6 &&
  2786 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
  2793 			myabs(v->y_pos - tcc->v->y_pos) < 6) {
  2787 		return v;
  2794 		return v;
  2859 
  2866 
  2860 	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
  2867 	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
  2861 	SndPlayVehicleFx(SND_13_BIG_CRASH, v);
  2868 	SndPlayVehicleFx(SND_13_BIG_CRASH, v);
  2862 }
  2869 }
  2863 
  2870 
  2864 typedef struct VehicleAtSignalData {
  2871 struct VehicleAtSignalData {
  2865 	TileIndex tile;
  2872 	TileIndex tile;
  2866 	Direction direction;
  2873 	Direction direction;
  2867 } VehicleAtSignalData;
  2874 };
  2868 
  2875 
  2869 static void *CheckVehicleAtSignal(Vehicle *v, void *data)
  2876 static void *CheckVehicleAtSignal(Vehicle *v, void *data)
  2870 {
  2877 {
  2871 	const VehicleAtSignalData* vasd = (VehicleAtSignalData*)data;
  2878 	const VehicleAtSignalData* vasd = (VehicleAtSignalData*)data;
  2872 
  2879 
  2873 	if (v->type == VEH_Train && IsFrontEngine(v) && v->tile == vasd->tile) {
  2880 	if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == vasd->tile) {
  2874 		DirDiff diff = ChangeDirDiff(DirDifference(v->direction, vasd->direction), DIRDIFF_90RIGHT);
  2881 		DirDiff diff = ChangeDirDiff(DirDifference(v->direction, vasd->direction), DIRDIFF_90RIGHT);
  2875 
  2882 
  2876 		if (diff == DIRDIFF_90RIGHT || (v->cur_speed <= 5 && diff <= DIRDIFF_REVERSE)) return v;
  2883 		if (diff == DIRDIFF_90RIGHT || (v->cur_speed <= 5 && diff <= DIRDIFF_REVERSE)) return v;
  2877 	}
  2884 	}
  2878 	return NULL;
  2885 	return NULL;
  2908 						TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
  2915 						TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
  2909 						return;
  2916 						return;
  2910 					}
  2917 					}
  2911 
  2918 
  2912 					if (v->current_order.type == OT_LEAVESTATION) {
  2919 					if (v->current_order.type == OT_LEAVESTATION) {
  2913 						v->current_order.type = OT_NOTHING;
  2920 						v->current_order.Free();
  2914 						v->current_order.flags = 0;
       
  2915 						InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2921 						InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
  2916 					}
  2922 					}
  2917 				}
  2923 				}
  2918 			} else {
  2924 			} else {
  2919 				/* A new tile is about to be entered. */
  2925 				/* A new tile is about to be entered. */
  3389 
  3395 
  3390 	if (IsFrontEngine(v)) {
  3396 	if (IsFrontEngine(v)) {
  3391 		TrainLocoHandler(v, false);
  3397 		TrainLocoHandler(v, false);
  3392 
  3398 
  3393 		// make sure vehicle wasn't deleted.
  3399 		// make sure vehicle wasn't deleted.
  3394 		if (v->type == VEH_Train && IsFrontEngine(v))
  3400 		if (v->type == VEH_TRAIN && IsFrontEngine(v))
  3395 			TrainLocoHandler(v, true);
  3401 			TrainLocoHandler(v, true);
  3396 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3402 	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
  3397 		// Delete flooded standalone wagon
  3403 		// Delete flooded standalone wagon
  3398 		if (++v->u.rail.crash_anim_pos >= 4400)
  3404 		if (++v->u.rail.crash_anim_pos >= 4400)
  3399 			DeleteVehicle(v);
  3405 			DeleteVehicle(v);
  3493 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3499 			InvalidateWindowClasses(WC_TRAINS_LIST);
  3494 		}
  3500 		}
  3495 	}
  3501 	}
  3496 }
  3502 }
  3497 
  3503 
  3498 void TrainsYearlyLoop(void)
  3504 void TrainsYearlyLoop()
  3499 {
  3505 {
  3500 	Vehicle *v;
  3506 	Vehicle *v;
  3501 
  3507 
  3502 	FOR_ALL_VEHICLES(v) {
  3508 	FOR_ALL_VEHICLES(v) {
  3503 		if (v->type == VEH_Train && IsFrontEngine(v)) {
  3509 		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)
  3510 			// 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) {
  3511 			if (_patches.train_income_warn && v->owner == _local_player && v->age >= 730 && v->profit_this_year < 0) {
  3506 				SetDParam(1, v->profit_this_year);
  3512 				SetDParam(1, v->profit_this_year);
  3507 				SetDParam(0, v->unitnumber);
  3513 				SetDParam(0, v->unitnumber);
  3508 				AddNewsItem(
  3514 				AddNewsItem(
  3518 		}
  3524 		}
  3519 	}
  3525 	}
  3520 }
  3526 }
  3521 
  3527 
  3522 
  3528 
  3523 void InitializeTrains(void)
  3529 void InitializeTrains()
  3524 {
  3530 {
  3525 	_age_cargo_skip_counter = 1;
  3531 	_age_cargo_skip_counter = 1;
  3526 }
  3532 }
  3527 
  3533 
  3528 /*
  3534 /*
  3529  * Link front and rear multiheaded engines to each other
  3535  * Link front and rear multiheaded engines to each other
  3530  * This is done when loading a savegame
  3536  * This is done when loading a savegame
  3531  */
  3537  */
  3532 void ConnectMultiheadedTrains(void)
  3538 void ConnectMultiheadedTrains()
  3533 {
  3539 {
  3534 	Vehicle *v;
  3540 	Vehicle *v;
  3535 
  3541 
  3536 	FOR_ALL_VEHICLES(v) {
  3542 	FOR_ALL_VEHICLES(v) {
  3537 		if (v->type == VEH_Train) {
  3543 		if (v->type == VEH_TRAIN) {
  3538 			v->u.rail.other_multiheaded_part = NULL;
  3544 			v->u.rail.other_multiheaded_part = NULL;
  3539 		}
  3545 		}
  3540 	}
  3546 	}
  3541 
  3547 
  3542 	FOR_ALL_VEHICLES(v) {
  3548 	FOR_ALL_VEHICLES(v) {
  3543 		if (v->type == VEH_Train && IsFrontEngine(v)) {
  3549 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
  3544 			Vehicle *u = v;
  3550 			Vehicle *u = v;
  3545 
  3551 
  3546 			BEGIN_ENUM_WAGONS(u) {
  3552 			BEGIN_ENUM_WAGONS(u) {
  3547 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
  3553 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
  3548 
  3554 
  3575 
  3581 
  3576 /*
  3582 /*
  3577  *  Converts all trains to the new subtype format introduced in savegame 16.2
  3583  *  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
  3584  *  It also links multiheaded engines or make them forget they are multiheaded if no suitable partner is found
  3579  */
  3585  */
  3580 void ConvertOldMultiheadToNew(void)
  3586 void ConvertOldMultiheadToNew()
  3581 {
  3587 {
  3582 	Vehicle *v;
  3588 	Vehicle *v;
  3583 	FOR_ALL_VEHICLES(v) {
  3589 	FOR_ALL_VEHICLES(v) {
  3584 		if (v->type == VEH_Train) {
  3590 		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
  3591 			SETBIT(v->subtype, 7); // indicates that it's the old format and needs to be converted in the next loop
  3586 		}
  3592 		}
  3587 	}
  3593 	}
  3588 
  3594 
  3589 	FOR_ALL_VEHICLES(v) {
  3595 	FOR_ALL_VEHICLES(v) {
  3590 		if (v->type == VEH_Train) {
  3596 		if (v->type == VEH_TRAIN) {
  3591 			if (HASBIT(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
  3597 			if (HASBIT(v->subtype, 7) && ((v->subtype & ~0x80) == 0 || (v->subtype & ~0x80) == 4)) {
  3592 				Vehicle *u = v;
  3598 				Vehicle *u = v;
  3593 
  3599 
  3594 				BEGIN_ENUM_WAGONS(u) {
  3600 				BEGIN_ENUM_WAGONS(u) {
  3595 					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);
  3601 					const RailVehicleInfo *rvi = RailVehInfo(u->engine_type);