src/vehicle.cpp
branchNewGRF_ports
changeset 10731 67db0d431d5e
parent 10724 68a692eacf22
child 10991 d8811e327d12
--- a/src/vehicle.cpp	Mon May 26 20:45:25 2008 +0000
+++ b/src/vehicle.cpp	Tue May 27 00:50:55 2008 +0000
@@ -50,6 +50,7 @@
 #include "depot_map.h"
 #include "animated_tile_func.h"
 #include "effectvehicle_base.h"
+#include "core/alloc_func.hpp"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -58,7 +59,7 @@
 #define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
 
 VehicleID _vehicle_id_ctr_day;
-Vehicle *_place_clicked_vehicle;
+const Vehicle *_place_clicked_vehicle;
 VehicleID _new_vehicle_id;
 uint16 _returned_refit_capacity;
 
@@ -126,20 +127,20 @@
 {
 	if (this->vehstatus & (VS_STOPPED | VS_CRASHED)) return false;
 
-	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
+	if (_settings.order.no_servicing_if_no_breakdowns && _settings.difficulty.vehicle_breakdowns == 0) {
 		/* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off.
 		 * Note: If servicing is enabled, we postpone replacement till next service. */
 		return EngineHasReplacementForPlayer(GetPlayer(this->owner), this->engine_type, this->group_id);
 	}
 
-	return _patches.servint_ispercent ?
+	return _settings.vehicle.servint_ispercent ?
 		(this->reliability < GetEngine(this->engine_type)->reliability * (100 - this->service_interval) / 100) :
 		(this->date_of_last_service + this->service_interval < _date);
 }
 
 bool Vehicle::NeedsAutomaticServicing() const
 {
-	if (_patches.gotodepot && VehicleHasDepotOrders(this)) return false;
+	if (_settings.order.gotodepot && VehicleHasDepotOrders(this)) return false;
 	if (this->current_order.IsType(OT_LOADING))            return false;
 	if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
 	return NeedsServicing();
@@ -531,6 +532,12 @@
 	return v;
 }
 
+const Vehicle *GetLastVehicleInChain(const Vehicle *v)
+{
+	while (v->Next() != NULL) v = v->Next();
+	return v;
+}
+
 uint CountVehiclesInChain(const Vehicle* v)
 {
 	uint count = 0;
@@ -906,7 +913,7 @@
 	if ((rel_old >> 8) != (rel >> 8)) InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
 	if (v->breakdown_ctr != 0 || v->vehstatus & VS_STOPPED ||
-			_opt.diff.vehicle_breakdowns < 1 ||
+			_settings.difficulty.vehicle_breakdowns < 1 ||
 			v->cur_speed < 5 || _game_mode == GM_MENU) {
 		return;
 	}
@@ -923,7 +930,7 @@
 	if (v->type == VEH_SHIP) rel += 0x6666;
 
 	/* reduced breakdowns? */
-	if (_opt.diff.vehicle_breakdowns == 1) rel += 0x6666;
+	if (_settings.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
 
 	/* check if to break down */
 	if (_breakdown_chance[(uint)min(rel, 0xffff) >> 10] <= v->breakdown_chance) {
@@ -982,9 +989,7 @@
  */
 CommandCost CmdMassStartStopVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **vl = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
+	VehicleList list;
 	CommandCost return_value = CMD_ERROR;
 	uint stop_command;
 	VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5);
@@ -1003,14 +1008,14 @@
 		uint32 id = p1;
 		uint16 window_type = p2 & VLW_MASK;
 
-		engine_count = GenerateVehicleSortList((const Vehicle***)&vl, &engine_list_length, vehicle_type, _current_player, id, window_type);
+		GenerateVehicleSortList(&list, vehicle_type, _current_player, id, window_type);
 	} else {
 		/* Get the list of vehicles in the depot */
-		BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, NULL, NULL, NULL);
+		BuildDepotVehicleList(vehicle_type, tile, &list, NULL);
 	}
 
-	for (uint i = 0; i < engine_count; i++) {
-		const Vehicle *v = vl[i];
+	for (uint i = 0; i < list.Length(); i++) {
+		const Vehicle *v = list[i];
 
 		if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue;
 
@@ -1032,7 +1037,6 @@
 		}
 	}
 
-	free(vl);
 	return return_value;
 }
 
@@ -1044,15 +1048,10 @@
  */
 CommandCost CmdDepotSellAllVehicles(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **engines = NULL;
-	Vehicle **wagons = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
-	uint16 wagon_list_length = 0;
-	uint16 wagon_count = 0;
+	VehicleList list;
 
 	CommandCost cost(EXPENSES_NEW_VEHICLES);
-	uint  sell_command, total_number_vehicles;
+	uint sell_command;
 	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 
 	switch (vehicle_type) {
@@ -1064,26 +1063,13 @@
 	}
 
 	/* Get the list of vehicles in the depot */
-	BuildDepotVehicleList(vehicle_type, tile, &engines, &engine_list_length, &engine_count,
-						                      &wagons,  &wagon_list_length,  &wagon_count);
-
-	total_number_vehicles = engine_count + wagon_count;
-	for (uint i = 0; i < total_number_vehicles; i++) {
-		const Vehicle *v;
-
-		if (i < engine_count) {
-			v = engines[i];
-		} else {
-			v = wagons[i - engine_count];
-		}
-
-		CommandCost ret = DoCommand(tile, v->index, 1, flags, sell_command);
-
+	BuildDepotVehicleList(vehicle_type, tile, &list, &list);
+
+	for (uint i = 0; i < list.Length(); i++) {
+		CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command);
 		if (CmdSucceeded(ret)) cost.AddCost(ret);
 	}
 
-	free(engines);
-	free(wagons);
 	if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell
 	return cost;
 }
@@ -1099,9 +1085,7 @@
  */
 CommandCost CmdDepotMassAutoReplace(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	Vehicle **vl = NULL;
-	uint16 engine_list_length = 0;
-	uint16 engine_count = 0;
+	VehicleList list;
 	CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES);
 	VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8);
 	bool all_or_nothing = HasBit(p2, 0);
@@ -1109,10 +1093,10 @@
 	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
-	BuildDepotVehicleList(vehicle_type, tile, &vl, &engine_list_length, &engine_count, &vl, &engine_list_length, &engine_count);
-
-	for (uint i = 0; i < engine_count; i++) {
-		Vehicle *v = vl[i];
+	BuildDepotVehicleList(vehicle_type, tile, &list, &list);
+
+	for (uint i = 0; i < list.Length(); i++) {
+		Vehicle *v = (Vehicle*)list[i];
 
 		/* Ensure that the vehicle completely in the depot */
 		if (!v->IsInDepot()) continue;
@@ -1127,22 +1111,18 @@
 				 * We should never reach this if DC_EXEC is set since then it should
 				 * have failed the estimation guess. */
 				assert(!(flags & DC_EXEC));
-				/* Now we will have to return an error.
-				 * This goto will leave the loop and it's ok to do so because
-				 * there is no point in the rest of the loop. */
-				goto error;
+				/* Now we will have to return an error. */
+				return CMD_ERROR;
 			}
 		}
 	}
 
 	if (cost.GetCost() == 0) {
-error:
 		/* Either we didn't replace anything or something went wrong.
 		 * Either way we want to return an error and not execute this command. */
 		cost = CMD_ERROR;
 	}
 
-	free(vl);
 	return cost;
 }
 
@@ -1311,100 +1291,55 @@
 	return total_cost;
 }
 
-
-/* Extend the list size for BuildDepotVehicleList() */
-static inline void ExtendVehicleListSize(const Vehicle ***engine_list, uint16 *engine_list_length, uint16 step_size)
-{
-	*engine_list_length = min(*engine_list_length + step_size, GetMaxVehicleIndex() + 1);
-	*engine_list = ReallocT(*engine_list, *engine_list_length);
-}
-
-/** Generates a list of vehicles inside a depot
- * Will enlarge allocated space for the list if they are too small, so it's ok to call with (pointer to NULL array, pointer to uninitised uint16, pointer to 0)
- * If one of the lists is not needed (say wagons when finding ships), all the pointers regarding that list should be set to NULL
- * @param type Type of vehicle
- * @param tile The tile the depot is located in
- * @param ***engine_list Pointer to a pointer to an array of vehicles in the depot (old list is freed and a new one is malloced)
- * @param *engine_list_length Allocated size of engine_list. Needs to be set to 0 when engine_list points to a NULL array
- * @param *engine_count The number of engines stored in the list
- * @param ***wagon_list Pointer to a pointer to an array of free wagons in the depot (old list is freed and a new one is malloced)
- * @param *wagon_list_length Allocated size of wagon_list. Needs to be set to 0 when wagon_list points to a NULL array
- * @param *wagon_count The number of engines stored in the list
+/**
+ * Generate a list of vehicles inside a depot.
+ * @param type    Type of vehicle
+ * @param tile    The tile the depot is located on
+ * @param engines Pointer to list to add vehicles to
+ * @param wagons  Pointer to list to add wagons to (can be NULL)
  */
-void BuildDepotVehicleList(VehicleType type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count)
+void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons)
 {
-	Vehicle *v;
-
-	/* This function should never be called without an array to store results */
-	assert(!(engine_list == NULL && type != VEH_TRAIN));
-	assert(!(type == VEH_TRAIN && engine_list == NULL && wagon_list == NULL));
-
-	/* Both array and the length should either be NULL to disable the list or both should not be NULL */
-	assert((engine_list == NULL && engine_list_length == NULL) || (engine_list != NULL && engine_list_length != NULL));
-	assert((wagon_list == NULL && wagon_list_length == NULL) || (wagon_list != NULL && wagon_list_length != NULL));
-
-	assert(!(engine_list != NULL && engine_count == NULL));
-	assert(!(wagon_list != NULL && wagon_count == NULL));
-
-	if (engine_count != NULL) *engine_count = 0;
-	if (wagon_count != NULL) *wagon_count = 0;
-
-	switch (type) {
-		case VEH_TRAIN:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_TRAIN && v->u.rail.track == TRACK_BIT_DEPOT) {
-					if (IsFrontEngine(v)) {
-						if (engine_list == NULL) continue;
-						if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-						(*engine_list)[(*engine_count)++] = v;
-					} else if (IsFreeWagon(v)) {
-						if (wagon_list == NULL) continue;
-						if (*wagon_count == *wagon_list_length) ExtendVehicleListSize((const Vehicle***)wagon_list, wagon_list_length, 25);
-						(*wagon_list)[(*wagon_count)++] = v;
-					}
+	engines->Clear();
+	if (wagons != NULL && wagons != engines) wagons->Clear();
+
+	const Vehicle *v;
+	FOR_ALL_VEHICLES(v) {
+		/* General tests for all vehicle types */
+		if (v->type != type) continue;
+		if (v->tile != tile) continue;
+
+		switch (type) {
+			case VEH_TRAIN:
+				if (v->u.rail.track != TRACK_BIT_DEPOT) continue;
+				if (wagons != NULL && IsFreeWagon(v)) {
+					*wagons->Append() = v;
+					continue;
 				}
-			}
-			break;
-
-		case VEH_ROAD:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_ROAD && v->IsInDepot() && IsRoadVehFront(v)) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		case VEH_SHIP:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile && v->type == VEH_SHIP && v->IsInDepot()) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		case VEH_AIRCRAFT:
-			FOR_ALL_VEHICLES(v) {
-				if (v->tile == tile &&
-						v->type == VEH_AIRCRAFT && IsNormalAircraft(v) &&
-						v->IsInDepot()) {
-					if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25);
-					(*engine_list)[(*engine_count)++] = v;
-				}
-			}
-			break;
-
-		default: NOT_REACHED();
+				break;
+
+			default:
+				if (!v->IsInDepot()) continue;
+				break;
+		}
+
+		if (!v->IsPrimaryVehicle()) continue;
+
+		*engines->Append() = v;
 	}
+
+	/* Ensure the lists are not wasting too much space. If the lists are fresh
+	 * (i.e. built within a command) then this will actually do nothing. */
+	engines->Compact();
+	if (wagons != NULL && wagons != engines) wagons->Compact();
 }
 
 /**
- * @param sort_list list to store the list in. Either NULL or the length length_of_array tells
- * @param length_of_array informs the length allocated for sort_list. This is not the same as the number of vehicles in the list. Needs to be 0 when sort_list is NULL
- * @param type type of vehicle
- * @param owner PlayerID of owner to generate a list for
- * @param index This parameter has different meanings depending on window_type
+ * Generate a list of vehicles based on window type.
+ * @param list        Pointer to list to add vehicles to
+ * @param type        Type of vehicle
+ * @param owner       Player to generate list for
+ * @param index       This parameter has different meanings depending on window_type
  *    <ul>
  *      <li>VLW_STATION_LIST:  index of station to generate a list for</li>
  *      <li>VLW_SHARED_ORDERS: index of order to generate a list for<li>
@@ -1412,83 +1347,71 @@
  *      <li>VLW_DEPOT_LIST: TileIndex of the depot/hangar to make the list for</li>
  *      <li>VLW_GROUP_LIST: index of group to generate a list for</li>
  *    </ul>
- * @param window_type tells what kind of window the list is for. Use the VLW flags in vehicle_gui.h
- * @return the number of vehicles added to the list
+ * @param window_type The type of window the list is for, using the VLW_ flags in vehicle_gui.h
  */
-uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, VehicleType type, PlayerID owner, uint32 index, uint16 window_type)
+void GenerateVehicleSortList(VehicleList *list, VehicleType type, PlayerID owner, uint32 index, uint16 window_type)
 {
-	uint n = 0;
+	list->Clear();
+
 	const Vehicle *v;
 
 	switch (window_type) {
-		case VLW_STATION_LIST: {
+		case VLW_STATION_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle()) {
 					const Order *order;
 
 					FOR_VEHICLE_ORDERS(v, order) {
 						if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == index) {
-							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 50);
-							(*sort_list)[n++] = v;
+							*list->Append() = v;
 							break;
 						}
 					}
 				}
 			}
 			break;
-		}
-
-		case VLW_SHARED_ORDERS: {
+
+		case VLW_SHARED_ORDERS:
 			FOR_ALL_VEHICLES(v) {
 				/* Find a vehicle with the order in question */
-				if (v->orders != NULL && v->orders->index == index) break;
-			}
-
-			if (v != NULL && v->orders != NULL && v->orders->index == index) {
-				/* Only try to make the list if we found a vehicle using the order in question */
-				for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
-					(*sort_list)[n++] = v;
+				if (v->orders != NULL && v->orders->index == index) {
+					/* Add all vehicles from this vehicle's shared order list */
+					for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) {
+						*list->Append() = v;
+					}
+					break;
 				}
 			}
 			break;
-		}
-
-		case VLW_STANDARD: {
+
+		case VLW_STANDARD:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->owner == owner && v->IsPrimaryVehicle()) {
-					/* TODO find a better estimate on the total number of vehicles for current player */
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4);
-					(*sort_list)[n++] = v;
+					*list->Append() = v;
 				}
 			}
 			break;
-		}
-
-		case VLW_DEPOT_LIST: {
+
+		case VLW_DEPOT_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle()) {
 					const Order *order;
 
 					FOR_VEHICLE_ORDERS(v, order) {
 						if (order->IsType(OT_GOTO_DEPOT) && order->GetDestination() == index) {
-							if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, 25);
-							(*sort_list)[n++] = v;
+							*list->Append() = v;
 							break;
 						}
 					}
 				}
 			}
 			break;
-		}
 
 		case VLW_GROUP_LIST:
 			FOR_ALL_VEHICLES(v) {
 				if (v->type == type && v->IsPrimaryVehicle() &&
 						v->owner == owner && v->group_id == index) {
-					if (n == *length_of_array) ExtendVehicleListSize(sort_list, length_of_array, GetNumVehicles() / 4);
-
-					(*sort_list)[n++] = v;
+					*list->Append() = v;
 				}
 			}
 			break;
@@ -1496,16 +1419,7 @@
 		default: NOT_REACHED(); break;
 	}
 
-	if ((n + 100) < *length_of_array) {
-		/* We allocated way too much for sort_list.
-		 * Now we will reduce how much we allocated.
-		 * We will still make it have room for 50 extra vehicles to prevent having
-		 * to move the whole array if just one vehicle is added later */
-		*length_of_array = n + 50;
-		*sort_list = ReallocT(*sort_list, (*length_of_array) * sizeof((*sort_list)[0]));
-	}
-
-	return n;
+	list->Compact();
 }
 
 /**
@@ -1519,14 +1433,13 @@
  */
 CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id)
 {
-	const Vehicle **sort_list = NULL;
-	uint16 array_length = 0;
-
-	uint n = GenerateVehicleSortList(&sort_list, &array_length, type, owner, id, vlw_flag);
+	VehicleList list;
+
+	GenerateVehicleSortList(&list, type, owner, id, vlw_flag);
 
 	/* Send all the vehicles to a depot */
-	for (uint i = 0; i < n; i++) {
-		const Vehicle *v = sort_list[i];
+	for (uint i = 0; i < list.Length(); i++) {
+		const Vehicle *v = list[i];
 		CommandCost ret = DoCommand(v->tile, v->index, (service ? 1 : 0) | DEPOT_DONT_CANCEL, flags, GetCmdSendToDepot(type));
 
 		/* Return 0 if DC_EXEC is not set this is a valid goto depot command)
@@ -1534,12 +1447,10 @@
 			* and we will issue the command. We can now safely quit the loop, knowing
 			* it will succeed at least once. With DC_EXEC we really need to send them to the depot */
 		if (CmdSucceeded(ret) && !(flags & DC_EXEC)) {
-			free((void*)sort_list);
 			return CommandCost();
 		}
 	}
 
-	free((void*)sort_list);
 	return (flags & DC_EXEC) ? CommandCost() : CMD_ERROR;
 }
 
@@ -1733,7 +1644,7 @@
 	if (flags & DC_EXEC) {
 		free(v->name);
 		v->name = strdup(_cmd_text);
-		ResortVehicleLists();
+		InvalidateWindowClassesData(WC_TRAINS_LIST, 1);
 		MarkWholeScreenDirty();
 	}
 
@@ -1915,10 +1826,10 @@
 	static UnitID gmax = 0;
 
 	switch (type) {
-		case VEH_TRAIN:    max = _patches.max_trains; break;
-		case VEH_ROAD:     max = _patches.max_roadveh; break;
-		case VEH_SHIP:     max = _patches.max_ships; break;
-		case VEH_AIRCRAFT: max = _patches.max_aircraft; break;
+		case VEH_TRAIN:    max = _settings.vehicle.max_trains; break;
+		case VEH_ROAD:     max = _settings.vehicle.max_roadveh; break;
+		case VEH_SHIP:     max = _settings.vehicle.max_ships; break;
+		case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break;
 		default: NOT_REACHED();
 	}
 
@@ -1968,14 +1879,14 @@
 	assert(IsPlayerBuildableVehicleType(type));
 
 	if (!IsValidPlayer(_current_player)) return false;
-	if (_patches.always_build_infrastructure) return true;
+	if (_settings.gui.always_build_infrastructure) return true;
 
 	UnitID max;
 	switch (type) {
-		case VEH_TRAIN:    max = _patches.max_trains; break;
-		case VEH_ROAD:     max = _patches.max_roadveh; break;
-		case VEH_SHIP:     max = _patches.max_ships; break;
-		case VEH_AIRCRAFT: max = _patches.max_aircraft; break;
+		case VEH_TRAIN:    max = _settings.vehicle.max_trains; break;
+		case VEH_ROAD:     max = _settings.vehicle.max_roadveh; break;
+		case VEH_SHIP:     max = _settings.vehicle.max_ships; break;
+		case VEH_AIRCRAFT: max = _settings.vehicle.max_aircraft; break;
 		default: NOT_REACHED();
 	}
 
@@ -2007,7 +1918,7 @@
 
 	/* The default livery is always available for use, but its in_use flag determines
 	 * whether any _other_ liveries are in use. */
-	if (p->livery[LS_DEFAULT].in_use && (_patches.liveries == 2 || (_patches.liveries == 1 && player == _local_player))) {
+	if (p->livery[LS_DEFAULT].in_use && (_settings.gui.liveries == 2 || (_settings.gui.liveries == 1 && player == _local_player))) {
 		/* Determine the livery scheme to use */
 		switch (GetEngine(engine_type)->type) {
 			default: NOT_REACHED();
@@ -2576,7 +2487,7 @@
 
 			/* Not the first call for this tick, or still loading */
 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
-					(_patches.timetabling && this->current_order_time < wait_time)) return;
+					(_settings.order.timetabling && this->current_order_time < wait_time)) return;
 
 			this->PlayLeaveStationSound();
 
@@ -2807,11 +2718,11 @@
 {
 	if (!ContainsBackup()) return v;
 	if (v != NULL) {
-		ChangeVehicleViewWindow(v, INVALID_VEHICLE);
+		ChangeVehicleViewWindow(v->index, INVALID_VEHICLE);
 		DoCommand(0, v->index, 1, DC_EXEC, GetCmdSellVeh(v));
 	}
 	v = RestoreBackupVehicle(this->vehicles, p);
-	ChangeVehicleViewWindow(INVALID_VEHICLE, v);
+	ChangeVehicleViewWindow(INVALID_VEHICLE, v->index);
 	if (orders != NULL) RestoreVehicleOrdersBruteForce(v, orders);
 	if (economy != NULL) economy->Restore();
 	/* If we stored cargo as well then we should restore it. */