src/vehicle.cpp
branchgamebalance
changeset 9908 0fa543611bbe
parent 9906 6f41b8713b65
child 9909 dce9a6923bb7
equal deleted inserted replaced
9907:3b068c3a1c74 9908:0fa543611bbe
     1 /* $Id$ */
     1 /* $Id$ */
       
     2 
       
     3 /** @file vehicle.cpp */
     2 
     4 
     3 #include "stdafx.h"
     5 #include "stdafx.h"
     4 #include "openttd.h"
     6 #include "openttd.h"
     5 #include "road_map.h"
     7 #include "road_map.h"
     6 #include "roadveh.h"
     8 #include "roadveh.h"
     7 #include "ship.h"
     9 #include "ship.h"
     8 #include "spritecache.h"
    10 #include "spritecache.h"
     9 #include "table/sprites.h"
    11 #include "table/sprites.h"
    10 #include "table/strings.h"
    12 #include "table/strings.h"
    11 #include "functions.h"
    13 #include "functions.h"
       
    14 #include "landscape.h"
    12 #include "map.h"
    15 #include "map.h"
    13 #include "tile.h"
    16 #include "tile.h"
    14 #include "vehicle.h"
    17 #include "vehicle.h"
    15 #include "gfx.h"
    18 #include "gfx.h"
    16 #include "viewport.h"
    19 #include "viewport.h"
   102 }
   105 }
   103 
   106 
   104 bool VehicleNeedsService(const Vehicle *v)
   107 bool VehicleNeedsService(const Vehicle *v)
   105 {
   108 {
   106 	if (v->vehstatus & VS_CRASHED)
   109 	if (v->vehstatus & VS_CRASHED)
   107 		return false; /* Crashed vehicles don't need service anymore */
   110 		return false; // Crashed vehicles don't need service anymore
   108 
   111 
   109 	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
   112 	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
   110 		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
   113 		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
   111 	}
   114 	}
   112 
   115 
   213 	v->top_coord = pt.y;
   216 	v->top_coord = pt.y;
   214 	v->right_coord = pt.x + spr->width + 2;
   217 	v->right_coord = pt.x + spr->width + 2;
   215 	v->bottom_coord = pt.y + spr->height + 2;
   218 	v->bottom_coord = pt.y + spr->height + 2;
   216 }
   219 }
   217 
   220 
   218 // Called after load to update coordinates
   221 /** Called after load to update coordinates */
   219 void AfterLoadVehicles()
   222 void AfterLoadVehicles()
   220 {
   223 {
   221 	Vehicle *v;
   224 	Vehicle *v;
   222 
   225 
   223 	FOR_ALL_VEHICLES(v) {
   226 	FOR_ALL_VEHICLES(v) {
   309 	}
   312 	}
   310 
   313 
   311 	return NULL;
   314 	return NULL;
   312 }
   315 }
   313 
   316 
   314 /*
   317 /**
   315  * finds a free vehicle in the memory or allocates a new one
   318  * finds a free vehicle in the memory or allocates a new one
   316  * returns a pointer to the first free vehicle or NULL if all vehicles are in use
   319  * returns a pointer to the first free vehicle or NULL if all vehicles are in use
   317  * *skip_vehicles is an offset to where in the array we should begin looking
   320  * *skip_vehicles is an offset to where in the array we should begin looking
   318  * this is to avoid looping though the same vehicles more than once after we learned that they are not free
   321  * this is to avoid looping though the same vehicles more than once after we learned that they are not free
   319  * this feature is used by AllocateVehicles() since it need to allocate more than one and when
   322  * this feature is used by AllocateVehicles() since it need to allocate more than one and when
   325 	 * first blocks */
   328 	 * first blocks */
   326 	Vehicle *v;
   329 	Vehicle *v;
   327 	const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
   330 	const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
   328 
   331 
   329 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   332 	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
   330 	 * TODO - This is just a temporary stage, this will be removed. */
   333 	 * @todo - This is just a temporary stage, this will be removed. */
   331 	if (*skip_vehicles < (_Vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself
   334 	if (*skip_vehicles < (_Vehicle_pool.total_items - offset)) { // make sure the offset in the array is not larger than the array itself
   332 		for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   335 		for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
   333 			(*skip_vehicles)++;
   336 			(*skip_vehicles)++;
   334 			if (!IsValidVehicle(v)) return InitializeVehicle(v);
   337 			if (!IsValidVehicle(v)) return InitializeVehicle(v);
   335 		}
   338 		}
   379 
   382 
   380 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
   383 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
   381 {
   384 {
   382 	Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, 0);
   385 	Point pt = RemapCoords(TileX(tile) * TILE_SIZE, TileY(tile) * TILE_SIZE, 0);
   383 
   386 
   384 	// The hash area to scan
   387 	/* The hash area to scan */
   385 	const int xl = GB(pt.x - 174, 7, 6);
   388 	const int xl = GB(pt.x - 174, 7, 6);
   386 	const int xu = GB(pt.x + 104, 7, 6);
   389 	const int xu = GB(pt.x + 104, 7, 6);
   387 	const int yl = GB(pt.y - 294, 6, 6) << 6;
   390 	const int yl = GB(pt.y - 294, 6, 6) << 6;
   388 	const int yu = GB(pt.y +  56, 6, 6) << 6;
   391 	const int yu = GB(pt.y +  56, 6, 6) << 6;
   389 
   392 
   496 	Vehicle *u;
   499 	Vehicle *u;
   497 	assert(v != NULL);
   500 	assert(v != NULL);
   498 
   501 
   499 	u = GetFirstVehicleInChain(v);
   502 	u = GetFirstVehicleInChain(v);
   500 
   503 
   501 	// Check to see if this is the first
   504 	/* Check to see if this is the first */
   502 	if (v == u) return NULL;
   505 	if (v == u) return NULL;
   503 
   506 
   504 	for (; u->next != v; u = u->next) assert(u->next != NULL);
   507 	for (; u->next != v; u = u->next) assert(u->next != NULL);
   505 
   508 
   506 	return u;
   509 	return u;
   604 void Ship_Tick(Vehicle *v);
   607 void Ship_Tick(Vehicle *v);
   605 void Train_Tick(Vehicle *v);
   608 void Train_Tick(Vehicle *v);
   606 static void EffectVehicle_Tick(Vehicle *v);
   609 static void EffectVehicle_Tick(Vehicle *v);
   607 void DisasterVehicle_Tick(Vehicle *v);
   610 void DisasterVehicle_Tick(Vehicle *v);
   608 
   611 
   609 // head of the linked list to tell what vehicles that visited a depot in a tick
   612 /** head of the linked list to tell what vehicles that visited a depot in a tick */
   610 static Vehicle* _first_veh_in_depot_list;
   613 static Vehicle* _first_veh_in_depot_list;
   611 
   614 
   612 /** Adds a vehicle to the list of vehicles, that visited a depot this tick
   615 /** Adds a vehicle to the list of vehicles, that visited a depot this tick
   613  * @param *v vehicle to add
   616  * @param *v vehicle to add
   614  */
   617  */
   615 void VehicleEnteredDepotThisTick(Vehicle *v)
   618 void VehicleEnteredDepotThisTick(Vehicle *v)
   616 {
   619 {
   617 	// we need to set v->leave_depot_instantly as we have no control of it's contents at this time
   620 	/* we need to set v->leave_depot_instantly as we have no control of it's contents at this time */
   618 	if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
   621 	if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS) && v->current_order.type == OT_GOTO_DEPOT) {
   619 		// we keep the vehicle in the depot since the user ordered it to stay
   622 		/* we keep the vehicle in the depot since the user ordered it to stay */
   620 		v->leave_depot_instantly = false;
   623 		v->leave_depot_instantly = false;
   621 	} else {
   624 	} else {
   622 		// the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   625 		/* the vehicle do not plan on stopping in the depot, so we stop it to ensure that it will not reserve the path
   623 		// out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path
   626 		 * out of the depot before we might autoreplace it to a different engine. The new engine would not own the reserved path
   624 		// we store that we stopped the vehicle, so autoreplace can start it again
   627 		 * we store that we stopped the vehicle, so autoreplace can start it again */
   625 		v->vehstatus |= VS_STOPPED;
   628 		v->vehstatus |= VS_STOPPED;
   626 		v->leave_depot_instantly = true;
   629 		v->leave_depot_instantly = true;
   627 	}
   630 	}
   628 
   631 
   629 	if (_first_veh_in_depot_list == NULL) {
   632 	if (_first_veh_in_depot_list == NULL) {
   648 void CallVehicleTicks()
   651 void CallVehicleTicks()
   649 {
   652 {
   650 	Vehicle *v;
   653 	Vehicle *v;
   651 
   654 
   652 #ifdef ENABLE_NETWORK
   655 #ifdef ENABLE_NETWORK
   653 	// hotfix for desync problem:
   656 	/* hotfix for desync problem:
   654 	//  for MP games invalidate the YAPF cache every tick to keep it exactly the same on the server and all clients
   657 	 *  for MP games invalidate the YAPF cache every tick to keep it exactly the same on the server and all clients */
   655 	if (_networking) {
   658 	if (_networking) {
   656 		YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
   659 		YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
   657 	}
   660 	}
   658 #endif //ENABLE_NETWORK
   661 #endif //ENABLE_NETWORK
   659 
   662 
   677 				/* Play an alterate running sound every 16 ticks */
   680 				/* Play an alterate running sound every 16 ticks */
   678 				if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16);
   681 				if (GB(v->tick_counter, 0, 4) == 0) PlayVehicleSound(v, v->cur_speed > 0 ? VSE_RUNNING_16 : VSE_STOPPED_16);
   679 		}
   682 		}
   680 	}
   683 	}
   681 
   684 
   682 	// now we handle all the vehicles that entered a depot this tick
   685 	/* now we handle all the vehicles that entered a depot this tick */
   683 	v = _first_veh_in_depot_list;
   686 	v = _first_veh_in_depot_list;
   684 	while (v != NULL) {
   687 	while (v != NULL) {
   685 		Vehicle *w = v->depot_list;
   688 		Vehicle *w = v->depot_list;
   686 		v->depot_list = NULL; // it should always be NULL at the end of each tick
   689 		v->depot_list = NULL; // it should always be NULL at the end of each tick
   687 		MaybeReplaceVehicle(v, false, true);
   690 		MaybeReplaceVehicle(v, false, true);
   693 {
   696 {
   694 	uint32 full = 0, not_full = 0;
   697 	uint32 full = 0, not_full = 0;
   695 	bool keep_loading = false;
   698 	bool keep_loading = false;
   696 	const GoodsEntry *ge = GetStation(v->last_station_visited)->goods;
   699 	const GoodsEntry *ge = GetStation(v->last_station_visited)->goods;
   697 
   700 
   698 	//special handling of aircraft
   701 	/* special handling of aircraft */
   699 
   702 
   700 	//if the aircraft carries passengers and is NOT full, then
   703 	/* if the aircraft carries passengers and is NOT full, then
   701 	//continue loading, no matter how much mail is in
   704 	 *continue loading, no matter how much mail is in */
   702 	if (v->type == VEH_AIRCRAFT &&
   705 	if (v->type == VEH_AIRCRAFT &&
   703 			IsCargoInClass(v->cargo_type, CC_PASSENGERS) &&
   706 			IsCargoInClass(v->cargo_type, CC_PASSENGERS) &&
   704 			v->cargo_cap != v->cargo_count) {
   707 			v->cargo_cap != v->cargo_count) {
   705 		return true;
   708 		return true;
   706 	}
   709 	}
   707 
   710 
   708 	// patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded.
   711 	/* patch should return "true" to continue loading, i.e. when there is no cargo type that is fully loaded. */
   709 	do {
   712 	do {
   710 		//Should never happen, but just in case future additions change this
   713 		/* Should never happen, but just in case future additions change this */
   711 		assert(v->cargo_type<32);
   714 		assert(v->cargo_type<32);
   712 
   715 
   713 		if (v->cargo_cap != 0) {
   716 		if (v->cargo_cap != 0) {
   714 			uint32 mask = 1 << v->cargo_type;
   717 			uint32 mask = 1 << v->cargo_type;
   715 
   718 
   724 				not_full |= mask;
   727 				not_full |= mask;
   725 			}
   728 			}
   726 		}
   729 		}
   727 	} while ((v = v->next) != NULL);
   730 	} while ((v = v->next) != NULL);
   728 
   731 
   729 	// continue loading if there is a non full cargo type and no cargo type that is full
   732 	/* continue loading if there is a non full cargo type and no cargo type that is full */
   730 	return keep_loading || (not_full && (full & ~not_full) == 0);
   733 	return keep_loading || (not_full && (full & ~not_full) == 0);
   731 }
   734 }
   732 
   735 
   733 bool CanFillVehicle(Vehicle *v)
   736 bool CanFillVehicle(Vehicle *v)
   734 {
   737 {
   741 				IsTileType(TILE_ADDXY(tile,  0,  1), MP_STATION) ||
   744 				IsTileType(TILE_ADDXY(tile,  0,  1), MP_STATION) ||
   742 				IsTileType(TILE_ADDXY(tile,  0, -1), MP_STATION) ||
   745 				IsTileType(TILE_ADDXY(tile,  0, -1), MP_STATION) ||
   743 				IsTileType(TILE_ADDXY(tile, -2,  0), MP_STATION)
   746 				IsTileType(TILE_ADDXY(tile, -2,  0), MP_STATION)
   744 			))) {
   747 			))) {
   745 
   748 
   746 		// If patch is active, use alternative CanFillVehicle-function
   749 		/* If patch is active, use alternative CanFillVehicle-function */
   747 		if (_patches.full_load_any && v->current_order.flags & OF_FULL_LOAD) return CanFillVehicle_FullLoadAny(v);
   750 		if (_patches.full_load_any && v->current_order.flags & OF_FULL_LOAD) return CanFillVehicle_FullLoadAny(v);
   748 
   751 
   749 		do {
   752 		do {
   750 			if (v->cargo_count != v->cargo_cap) return true;
   753 			if (v->cargo_count != v->cargo_cap) return true;
   751 		} while ((v = v->next) != NULL);
   754 		} while ((v = v->next) != NULL);
   819 		v->sprite_width, v->sprite_height, v->z_height, v->z_pos);
   822 		v->sprite_width, v->sprite_height, v->z_height, v->z_pos);
   820 }
   823 }
   821 
   824 
   822 void ViewportAddVehicles(DrawPixelInfo *dpi)
   825 void ViewportAddVehicles(DrawPixelInfo *dpi)
   823 {
   826 {
   824 	// The bounding rectangle
   827 	/* The bounding rectangle */
   825 	const int l = dpi->left;
   828 	const int l = dpi->left;
   826 	const int r = dpi->left + dpi->width;
   829 	const int r = dpi->left + dpi->width;
   827 	const int t = dpi->top;
   830 	const int t = dpi->top;
   828 	const int b = dpi->top + dpi->height;
   831 	const int b = dpi->top + dpi->height;
   829 
   832 
   830 	// The hash area to scan
   833 	/* The hash area to scan */
   831 	const int xl = GB(l - 70, 7, 6);
   834 	const int xl = GB(l - 70, 7, 6);
   832 	const int xu = GB(r,      7, 6);
   835 	const int xu = GB(r,      7, 6);
   833 	const int yl = GB(t - 70, 6, 6) << 6;
   836 	const int yl = GB(t - 70, 6, 6) << 6;
   834 	const int yu = GB(b,      6, 6) << 6;
   837 	const int yu = GB(b,      6, 6) << 6;
   835 
   838 
  1565 
  1568 
  1566 static void ShowVehicleGettingOld(Vehicle *v, StringID msg)
  1569 static void ShowVehicleGettingOld(Vehicle *v, StringID msg)
  1567 {
  1570 {
  1568 	if (v->owner != _local_player) return;
  1571 	if (v->owner != _local_player) return;
  1569 
  1572 
  1570 	// Do not show getting-old message if autorenew is active
  1573 	/* Do not show getting-old message if autorenew is active */
  1571 	if (GetPlayer(v->owner)->engine_renew) return;
  1574 	if (GetPlayer(v->owner)->engine_renew) return;
  1572 
  1575 
  1573 	SetDParam(0, _vehicle_type_names[v->type]);
  1576 	SetDParam(0, _vehicle_type_names[v->type]);
  1574 	SetDParam(1, v->unitnumber);
  1577 	SetDParam(1, v->unitnumber);
  1575 	AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
  1578 	AddNewsItem(msg, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
  1597 	}
  1600 	}
  1598 }
  1601 }
  1599 
  1602 
  1600 /** Starts or stops a lot of vehicles
  1603 /** Starts or stops a lot of vehicles
  1601  * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots)
  1604  * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots)
       
  1605  * @param flags type of operation
  1602  * @param p1 Station/Order/Depot ID (only used for vehicle list windows)
  1606  * @param p1 Station/Order/Depot ID (only used for vehicle list windows)
  1603  * @param p2 bitmask
  1607  * @param p2 bitmask
  1604  *   - bit 0-4 Vehicle type
  1608  *   - bit 0-4 Vehicle type
  1605  *   - bit 5 false = start vehicles, true = stop vehicles
  1609  *   - bit 5 false = start vehicles, true = stop vehicles
  1606  *   - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case
  1610  *   - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case
  1663 	free(vl);
  1667 	free(vl);
  1664 	return return_value;
  1668 	return return_value;
  1665 }
  1669 }
  1666 
  1670 
  1667 /** Sells all vehicles in a depot
  1671 /** Sells all vehicles in a depot
  1668 * @param tile Tile of the depot where the depot is
  1672  * @param tile Tile of the depot where the depot is
  1669 * @param p1 Vehicle type
  1673  * @param flags type of operation
  1670 * @param p2 unused
  1674  * @param p1 Vehicle type
  1671 */
  1675  * @param p2 unused
       
  1676  */
  1672 int32 CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1677 int32 CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1673 {
  1678 {
  1674 	Vehicle **engines = NULL;
  1679 	Vehicle **engines = NULL;
  1675 	Vehicle **wagons = NULL;
  1680 	Vehicle **wagons = NULL;
  1676 	uint16 engine_list_length = 0;
  1681 	uint16 engine_list_length = 0;
  1715 	if (cost == 0) return CMD_ERROR; // no vehicles to sell
  1720 	if (cost == 0) return CMD_ERROR; // no vehicles to sell
  1716 	return cost;
  1721 	return cost;
  1717 }
  1722 }
  1718 
  1723 
  1719 /** Autoreplace all vehicles in the depot
  1724 /** Autoreplace all vehicles in the depot
  1720 * @param tile Tile of the depot where the vehicles are
  1725  * @param tile Tile of the depot where the vehicles are
  1721 * @param p1 Type of vehicle
  1726  * @param flags type of operation
  1722 * @param p2 Unused
  1727  * @param p1 Type of vehicle
  1723 */
  1728  * @param p2 Unused
       
  1729  */
  1724 int32 CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1730 int32 CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1725 {
  1731 {
  1726 	Vehicle **vl = NULL;
  1732 	Vehicle **vl = NULL;
  1727 	uint16 engine_list_length = 0;
  1733 	uint16 engine_list_length = 0;
  1728 	uint16 engine_count = 0;
  1734 	uint16 engine_count = 0;
  1782 	return cost;
  1788 	return cost;
  1783 }
  1789 }
  1784 
  1790 
  1785 /** Clone a vehicle. If it is a train, it will clone all the cars too
  1791 /** Clone a vehicle. If it is a train, it will clone all the cars too
  1786  * @param tile tile of the depot where the cloned vehicle is build
  1792  * @param tile tile of the depot where the cloned vehicle is build
       
  1793  * @param flags type of operation
  1787  * @param p1 the original vehicle's index
  1794  * @param p1 the original vehicle's index
  1788  * @param p2 1 = shared orders, else copied orders
  1795  * @param p2 1 = shared orders, else copied orders
  1789  */
  1796  */
  1790 int32 CmdCloneVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1797 int32 CmdCloneVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1791 {
  1798 {
  1812 
  1819 
  1813 	if (!CheckOwnership(v->owner)) return CMD_ERROR;
  1820 	if (!CheckOwnership(v->owner)) return CMD_ERROR;
  1814 
  1821 
  1815 	if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR;
  1822 	if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || v->u.rail.crash_anim_pos >= 4400)) return CMD_ERROR;
  1816 
  1823 
  1817 	// check that we can allocate enough vehicles
  1824 	/* check that we can allocate enough vehicles */
  1818 	if (!(flags & DC_EXEC)) {
  1825 	if (!(flags & DC_EXEC)) {
  1819 		int veh_counter = 0;
  1826 		int veh_counter = 0;
  1820 		do {
  1827 		do {
  1821 			veh_counter++;
  1828 			veh_counter++;
  1822 		} while ((v = v->next) != NULL);
  1829 		} while ((v = v->next) != NULL);
  1860 			if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1867 			if (v->type == VEH_TRAIN && HASBIT(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
  1861 				SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION);
  1868 				SETBIT(w->u.rail.flags, VRF_REVERSE_DIRECTION);
  1862 			}
  1869 			}
  1863 
  1870 
  1864 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
  1871 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
  1865 				// this s a train car
  1872 				/* this s a train car
  1866 				// add this unit to the end of the train
  1873 				 * add this unit to the end of the train */
  1867 				DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
  1874 				DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
  1868 			} else {
  1875 			} else {
  1869 				// this is a front engine or not a train. It need orders
  1876 				/* this is a front engine or not a train. It need orders */
  1870 				w_front = w;
  1877 				w_front = w;
  1871 				w->service_interval = v->service_interval;
  1878 				w->service_interval = v->service_interval;
  1872 				DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
  1879 				DoCommand(0, (v->index << 16) | w->index, p2 & 1 ? CO_SHARE : CO_COPY, flags, CMD_CLONE_ORDER);
  1873 			}
  1880 			}
  1874 			w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
  1881 			w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
  1875 		}
  1882 		}
  1876 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
  1883 	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
  1877 
  1884 
  1878 	if (flags & DC_EXEC && v_front->type == VEH_TRAIN) {
  1885 	if (flags & DC_EXEC && v_front->type == VEH_TRAIN) {
  1879 		// for trains this needs to be the front engine due to the callback function
  1886 		/* for trains this needs to be the front engine due to the callback function */
  1880 		_new_vehicle_id = w_front->index;
  1887 		_new_vehicle_id = w_front->index;
  1881 	}
  1888 	}
  1882 
  1889 
  1883 	/* Set the expense type last as refitting will make the cost go towards
  1890 	/* Set the expense type last as refitting will make the cost go towards
  1884 	 * running costs... */
  1891 	 * running costs... */
  2218 	}
  2225 	}
  2219 }
  2226 }
  2220 
  2227 
  2221 /** Give a custom name to your vehicle
  2228 /** Give a custom name to your vehicle
  2222  * @param tile unused
  2229  * @param tile unused
       
  2230  * @param flags type of operation
  2223  * @param p1 vehicle ID to name
  2231  * @param p1 vehicle ID to name
  2224  * @param p2 unused
  2232  * @param p2 unused
  2225  */
  2233  */
  2226 int32 CmdNameVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  2234 int32 CmdNameVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  2227 {
  2235 {
  2251 }
  2259 }
  2252 
  2260 
  2253 
  2261 
  2254 /** Change the service interval of a vehicle
  2262 /** Change the service interval of a vehicle
  2255  * @param tile unused
  2263  * @param tile unused
       
  2264  * @param flags type of operation
  2256  * @param p1 vehicle ID that is being service-interval-changed
  2265  * @param p1 vehicle ID that is being service-interval-changed
  2257  * @param p2 new service interval
  2266  * @param p2 new service interval
  2258  */
  2267  */
  2259 int32 CmdChangeServiceInt(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  2268 int32 CmdChangeServiceInt(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  2260 {
  2269 {
  2347 {
  2356 {
  2348 	if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
  2357 	if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
  2349 
  2358 
  2350 	switch (v->type) {
  2359 	switch (v->type) {
  2351 		case VEH_TRAIN:
  2360 		case VEH_TRAIN:
  2352 			if (v->u.rail.track == TRACK_BIT_DEPOT) /* We'll assume the train is facing outwards */
  2361 			if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards
  2353 				return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); /* Train in depot */
  2362 				return DiagdirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot
  2354 
  2363 
  2355 			if (v->u.rail.track == TRACK_BIT_WORMHOLE) /* train in tunnel, so just use his direction and assume a diagonal track */
  2364 			if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel, so just use his direction and assume a diagonal track
  2356 				return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
  2365 				return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
  2357 
  2366 
  2358 			return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction);
  2367 			return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction);
  2359 
  2368 
  2360 		case VEH_SHIP:
  2369 		case VEH_SHIP:
  2361 			if (IsShipInDepot(v))
  2370 			if (IsShipInDepot(v))
  2362 				/* We'll assume the ship is facing outwards */
  2371 				// We'll assume the ship is facing outwards
  2363 				return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile));
  2372 				return DiagdirToDiagTrackdir(GetShipDepotDirection(v->tile));
  2364 
  2373 
  2365 			return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction);
  2374 			return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction);
  2366 
  2375 
  2367 		case VEH_ROAD:
  2376 		case VEH_ROAD:
  2368 			if (IsRoadVehInDepot(v)) /* We'll assume the road vehicle is facing outwards */
  2377 			if (IsRoadVehInDepot(v)) // We'll assume the road vehicle is facing outwards
  2369 				return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile));
  2378 				return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile));
  2370 
  2379 
  2371 			if (IsStandardRoadStopTile(v->tile)) /* We'll assume the road vehicle is facing outwards */
  2380 			if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards
  2372 				return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); /* Road vehicle in a station */
  2381 				return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station
  2373 
  2382 
  2374 			if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
  2383 			if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
  2375 
  2384 
  2376 			/* If vehicle's state is a valid track direction (vehicle is not turning around) return it */
  2385 			/* If vehicle's state is a valid track direction (vehicle is not turning around) return it */
  2377 			if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state;
  2386 			if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state;
  2420 		gmax = max;
  2429 		gmax = max;
  2421 		free(cache);
  2430 		free(cache);
  2422 		cache = MallocT<bool>(max + 1);
  2431 		cache = MallocT<bool>(max + 1);
  2423 	}
  2432 	}
  2424 
  2433 
  2425 	// Clear the cache
  2434 	/* Clear the cache */
  2426 	memset(cache, 0, (max + 1) * sizeof(*cache));
  2435 	memset(cache, 0, (max + 1) * sizeof(*cache));
  2427 
  2436 
  2428 	// Fill the cache
  2437 	/* Fill the cache */
  2429 	FOR_ALL_VEHICLES(u) {
  2438 	FOR_ALL_VEHICLES(u) {
  2430 		if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max)
  2439 		if (u->type == type && u->owner == _current_player && u->unitnumber != 0 && u->unitnumber <= max)
  2431 			cache[u->unitnumber] = true;
  2440 			cache[u->unitnumber] = true;
  2432 	}
  2441 	}
  2433 
  2442 
  2434 	// Find the first unused unit number
  2443 	/* Find the first unused unit number */
  2435 	for (unit = 1; unit <= max; unit++) {
  2444 	for (unit = 1; unit <= max; unit++) {
  2436 		if (!cache[unit]) break;
  2445 		if (!cache[unit]) break;
  2437 	}
  2446 	}
  2438 
  2447 
  2439 	return unit;
  2448 	return unit;
  2560 	}
  2569 	}
  2561 
  2570 
  2562 	return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
  2571 	return GetEngineColourMap(v->engine_type, v->owner, INVALID_ENGINE, v);
  2563 }
  2572 }
  2564 
  2573 
  2565 // Save and load of vehicles
  2574 /** Save and load of vehicles */
  2566 extern const SaveLoad _common_veh_desc[] = {
  2575 extern const SaveLoad _common_veh_desc[] = {
  2567 	    SLE_VAR(Vehicle, subtype,              SLE_UINT8),
  2576 	    SLE_VAR(Vehicle, subtype,              SLE_UINT8),
  2568 
  2577 
  2569 	    SLE_REF(Vehicle, next,                 REF_VEHICLE_OLD),
  2578 	    SLE_REF(Vehicle, next,                 REF_VEHICLE_OLD),
  2570 	    SLE_VAR(Vehicle, string_id,            SLE_STRINGID),
  2579 	    SLE_VAR(Vehicle, string_id,            SLE_STRINGID),
  2665 	    SLE_VAR(Vehicle, waiting_triggers,     SLE_UINT8),
  2674 	    SLE_VAR(Vehicle, waiting_triggers,     SLE_UINT8),
  2666 
  2675 
  2667 	    SLE_REF(Vehicle, next_shared,          REF_VEHICLE),
  2676 	    SLE_REF(Vehicle, next_shared,          REF_VEHICLE),
  2668 	    SLE_REF(Vehicle, prev_shared,          REF_VEHICLE),
  2677 	    SLE_REF(Vehicle, prev_shared,          REF_VEHICLE),
  2669 
  2678 
  2670 	// reserve extra space in savegame here. (currently 10 bytes)
  2679 	/* reserve extra space in savegame here. (currently 10 bytes) */
  2671 	SLE_CONDNULL(10,                                                       2, SL_MAX_VERSION),
  2680 	SLE_CONDNULL(10,                                                       2, SL_MAX_VERSION),
  2672 
  2681 
  2673 	SLE_END()
  2682 	SLE_END()
  2674 };
  2683 };
  2675 
  2684 
  2684 
  2693 
  2685 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, flags),                  SLE_UINT8,  2, SL_MAX_VERSION),
  2694 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, flags),                  SLE_UINT8,  2, SL_MAX_VERSION),
  2686 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION),
  2695 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION),
  2687 
  2696 
  2688 	SLE_CONDNULL(2, 2, 19),
  2697 	SLE_CONDNULL(2, 2, 19),
  2689 	// reserve extra space in savegame here. (currently 11 bytes)
  2698 	/* reserve extra space in savegame here. (currently 11 bytes) */
  2690 	SLE_CONDNULL(11, 2, SL_MAX_VERSION),
  2699 	SLE_CONDNULL(11, 2, SL_MAX_VERSION),
  2691 
  2700 
  2692 	SLE_END()
  2701 	SLE_END()
  2693 };
  2702 };
  2694 
  2703 
  2704 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, reverse_ctr),    SLE_UINT8),
  2713 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, reverse_ctr),    SLE_UINT8),
  2705 
  2714 
  2706 	SLE_CONDREFX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot),     REF_ROADSTOPS, 6, SL_MAX_VERSION),
  2715 	SLE_CONDREFX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot),     REF_ROADSTOPS, 6, SL_MAX_VERSION),
  2707 	SLE_CONDNULL(1,                                                                     6, SL_MAX_VERSION),
  2716 	SLE_CONDNULL(1,                                                                     6, SL_MAX_VERSION),
  2708 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot_age), SLE_UINT8,     6, SL_MAX_VERSION),
  2717 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot_age), SLE_UINT8,     6, SL_MAX_VERSION),
  2709 	// reserve extra space in savegame here. (currently 16 bytes)
  2718 	/* reserve extra space in savegame here. (currently 16 bytes) */
  2710 	SLE_CONDNULL(16,                                                                    2, SL_MAX_VERSION),
  2719 	SLE_CONDNULL(16,                                                                    2, SL_MAX_VERSION),
  2711 
  2720 
  2712 	SLE_END()
  2721 	SLE_END()
  2713 };
  2722 };
  2714 
  2723 
  2715 static const SaveLoad _ship_desc[] = {
  2724 static const SaveLoad _ship_desc[] = {
  2716 	SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file.
  2725 	SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file.
  2717 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
  2726 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
  2718 	SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8),
  2727 	SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8),
  2719 
  2728 
  2720 	// reserve extra space in savegame here. (currently 16 bytes)
  2729 	/* reserve extra space in savegame here. (currently 16 bytes) */
  2721 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
  2730 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
  2722 
  2731 
  2723 	SLE_END()
  2732 	SLE_END()
  2724 };
  2733 };
  2725 
  2734 
  2734 
  2743 
  2735 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, state),           SLE_UINT8),
  2744 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, state),           SLE_UINT8),
  2736 
  2745 
  2737 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos),    SLE_UINT8,                 2, SL_MAX_VERSION),
  2746 	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos),    SLE_UINT8,                 2, SL_MAX_VERSION),
  2738 
  2747 
  2739 	// reserve extra space in savegame here. (currently 15 bytes)
  2748 	/* reserve extra space in savegame here. (currently 15 bytes) */
  2740 	SLE_CONDNULL(15,                                                                                      2, SL_MAX_VERSION),
  2749 	SLE_CONDNULL(15,                                                                                      2, SL_MAX_VERSION),
  2741 
  2750 
  2742 	SLE_END()
  2751 	SLE_END()
  2743 };
  2752 };
  2744 
  2753 
  2766 	    SLE_VAR(Vehicle, vehstatus,     SLE_UINT8),
  2775 	    SLE_VAR(Vehicle, vehstatus,     SLE_UINT8),
  2767 
  2776 
  2768 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk0), SLE_UINT16),
  2777 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk0), SLE_UINT16),
  2769 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk2), SLE_UINT8),
  2778 	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk2), SLE_UINT8),
  2770 
  2779 
  2771 	// reserve extra space in savegame here. (currently 16 bytes)
  2780 	/* reserve extra space in savegame here. (currently 16 bytes) */
  2772 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
  2781 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
  2773 
  2782 
  2774 	SLE_END()
  2783 	SLE_END()
  2775 };
  2784 };
  2776 
  2785 
  2808 	    SLE_VAR(Vehicle, tick_counter,  SLE_UINT8),
  2817 	    SLE_VAR(Vehicle, tick_counter,  SLE_UINT8),
  2809 
  2818 
  2810 	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, image_override), SLE_UINT16),
  2819 	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, image_override), SLE_UINT16),
  2811 	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, unk2),           SLE_UINT16),
  2820 	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, unk2),           SLE_UINT16),
  2812 
  2821 
  2813 	// reserve extra space in savegame here. (currently 16 bytes)
  2822 	/* reserve extra space in savegame here. (currently 16 bytes) */
  2814 	SLE_CONDNULL(16,                                                 2, SL_MAX_VERSION),
  2823 	SLE_CONDNULL(16,                                                 2, SL_MAX_VERSION),
  2815 
  2824 
  2816 	SLE_END()
  2825 	SLE_END()
  2817 };
  2826 };
  2818 
  2827 
  2824 	_aircraft_desc,
  2833 	_aircraft_desc,
  2825 	_special_desc,
  2834 	_special_desc,
  2826 	_disaster_desc,
  2835 	_disaster_desc,
  2827 };
  2836 };
  2828 
  2837 
  2829 // Will be called when the vehicles need to be saved.
  2838 /** Will be called when the vehicles need to be saved. */
  2830 static void Save_VEHS()
  2839 static void Save_VEHS()
  2831 {
  2840 {
  2832 	Vehicle *v;
  2841 	Vehicle *v;
  2833 	// Write the vehicles
  2842 	/* Write the vehicles */
  2834 	FOR_ALL_VEHICLES(v) {
  2843 	FOR_ALL_VEHICLES(v) {
  2835 		SlSetArrayIndex(v->index);
  2844 		SlSetArrayIndex(v->index);
  2836 		SlObject(v, (SaveLoad*)_veh_descs[v->type]);
  2845 		SlObject(v, (SaveLoad*)_veh_descs[v->type]);
  2837 	}
  2846 	}
  2838 }
  2847 }
  2839 
  2848 
  2840 // Will be called when vehicles need to be loaded.
  2849 /** Will be called when vehicles need to be loaded. */
  2841 static void Load_VEHS()
  2850 static void Load_VEHS()
  2842 {
  2851 {
  2843 	int index;
  2852 	int index;
  2844 	Vehicle *v;
  2853 	Vehicle *v;
  2845 
  2854