(svn r10770) -Codechange: use the pool item class as super class for the vehicle struct.
authorrubidium
Fri, 03 Aug 2007 19:36:00 +0000
changeset 7398 b933416cf32b
parent 7397 d39548123fbd
child 7399 60dd9641cb34
(svn r10770) -Codechange: use the pool item class as super class for the vehicle struct.
-Codechange: do not force "special" vehicles to be allocated in the low 1024 vehicle slots and non "special" vehicles in the rest of the slots.
src/aircraft_cmd.cpp
src/articulated_vehicles.cpp
src/disaster_cmd.cpp
src/economy.cpp
src/roadveh_cmd.cpp
src/ship_cmd.cpp
src/train_cmd.cpp
src/vehicle.cpp
src/vehicle.h
--- a/src/aircraft_cmd.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/aircraft_cmd.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -287,7 +287,7 @@
 	/* Allocate 2 or 3 vehicle structs, depending on type
 	 * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */
 	Vehicle *vl[3];
-	if (!AllocateVehicles(vl, avi->subtype & AIR_CTOL ? 2 : 3)) {
+	if (!Vehicle::AllocateList(vl, avi->subtype & AIR_CTOL ? 2 : 3)) {
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 	}
 
--- a/src/articulated_vehicles.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/articulated_vehicles.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -42,7 +42,7 @@
 		/* Attempt to use pre-allocated vehicles until they run out. This can happen
 		 * if the callback returns different values depending on the cargo type. */
 		u->next = vl[i];
-		if (u->next == NULL) u->next = AllocateVehicle();
+		if (u->next == NULL) u->next = new InvalidVehicle();
 		if (u->next == NULL) return;
 
 		u = u->next;
--- a/src/disaster_cmd.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/disaster_cmd.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -121,7 +121,6 @@
  * and owned by nobody */
 static void InitializeDisasterVehicle(Vehicle *v, int x, int y, byte z, Direction direction, byte subtype)
 {
-	v = new (v) DisasterVehicle();
 	v->x_pos = x;
 	v->y_pos = y;
 	v->z_pos = z;
@@ -600,7 +599,7 @@
 			v->tile,
 			0);
 
-		u = ForceAllocateSpecialVehicle();
+		u = new DisasterVehicle();
 		if (u == NULL) {
 			DeleteDisasterVeh(v);
 			return;
@@ -609,7 +608,7 @@
 		InitializeDisasterVehicle(u, -6 * TILE_SIZE, v->y_pos, 135, DIR_SW, ST_Big_Ufo_Destroyer);
 		u->u.disaster.big_ufo_destroyer_target = v->index;
 
-		w = ForceAllocateSpecialVehicle();
+		w = new DisasterVehicle();
 		if (w == NULL) return;
 
 		u->next = w;
@@ -706,7 +705,7 @@
 		VehiclePositionChanged(v);
 		BeginVehicleMove(v);
 		EndVehicleMove(v);
-		DeleteVehicle(v);
+		delete v;
 		return;
 	}
 
@@ -760,7 +759,7 @@
  * otherwise crashes on a random tile */
 static void Disaster_Zeppeliner_Init()
 {
-	Vehicle *v = ForceAllocateSpecialVehicle(), *u;
+	Vehicle *v = new DisasterVehicle(), *u;
 	Station *st;
 	int x;
 
@@ -781,7 +780,7 @@
 	InitializeDisasterVehicle(v, x, 0, 135, DIR_SE, ST_Zeppeliner);
 
 	/* Allocate shadow too? */
-	u = ForceAllocateSpecialVehicle();
+	u = new DisasterVehicle();
 	if (u != NULL) {
 		v->next = u;
 		InitializeDisasterVehicle(u, x, 0, 0, DIR_SE, ST_Zeppeliner_Shadow);
@@ -794,7 +793,7 @@
  * until it locates a road vehicle which it targets and then destroys */
 static void Disaster_Small_Ufo_Init()
 {
-	Vehicle *v = ForceAllocateSpecialVehicle(), *u;
+	Vehicle *v = new DisasterVehicle(), *u;
 	int x;
 
 	if (v == NULL) return;
@@ -806,7 +805,7 @@
 	v->age = 0;
 
 	/* Allocate shadow too? */
-	u = ForceAllocateSpecialVehicle();
+	u = new DisasterVehicle();
 	if (u != NULL) {
 		v->next = u;
 		InitializeDisasterVehicle(u, x, 0, 0, DIR_SE, ST_Small_Ufo_Shadow);
@@ -833,7 +832,7 @@
 
 	if (found == NULL) return;
 
-	v = ForceAllocateSpecialVehicle();
+	v = new DisasterVehicle();
 	if (v == NULL) return;
 
 	/* Start from the bottom (south side) of the map */
@@ -842,7 +841,7 @@
 
 	InitializeDisasterVehicle(v, x, y, 135, DIR_NE, ST_Airplane);
 
-	u = ForceAllocateSpecialVehicle();
+	u = new DisasterVehicle();
 	if (u != NULL) {
 		v->next = u;
 		InitializeDisasterVehicle(u, x, y, 0, DIR_SE, ST_Airplane_Shadow);
@@ -869,7 +868,7 @@
 
 	if (found == NULL) return;
 
-	v = ForceAllocateSpecialVehicle();
+	v = new DisasterVehicle();
 	if (v == NULL) return;
 
 	x = -16 * TILE_SIZE;
@@ -877,13 +876,13 @@
 
 	InitializeDisasterVehicle(v, x, y, 135, DIR_SW, ST_Helicopter);
 
-	u = ForceAllocateSpecialVehicle();
+	u = new DisasterVehicle();
 	if (u != NULL) {
 		v->next = u;
 		InitializeDisasterVehicle(u, x, y, 0, DIR_SW, ST_Helicopter_Shadow);
 		u->vehstatus |= VS_SHADOW;
 
-		w = ForceAllocateSpecialVehicle();
+		w = new DisasterVehicle();
 		if (w != NULL) {
 			u->next = w;
 			InitializeDisasterVehicle(w, x, y, 140, DIR_SW, ST_Helicopter_Rotors);
@@ -896,7 +895,7 @@
  * down by a combat airplane, destroying the surroundings */
 static void Disaster_Big_Ufo_Init()
 {
-	Vehicle *v = ForceAllocateSpecialVehicle(), *u;
+	Vehicle *v = new DisasterVehicle(), *u;
 	int x, y;
 
 	if (v == NULL) return;
@@ -909,7 +908,7 @@
 	v->age = 0;
 
 	/* Allocate shadow too? */
-	u = ForceAllocateSpecialVehicle();
+	u = new DisasterVehicle();
 	if (u != NULL) {
 		v->next = u;
 		InitializeDisasterVehicle(u, x, y, 0, DIR_NW, ST_Big_Ufo_Shadow);
@@ -921,7 +920,7 @@
 /* Curious submarine #1, just floats around */
 static void Disaster_Small_Submarine_Init()
 {
-	Vehicle *v = ForceAllocateSpecialVehicle();
+	Vehicle *v = new DisasterVehicle();
 	int x, y;
 	Direction dir;
 	uint32 r;
@@ -946,7 +945,7 @@
 /* Curious submarine #2, just floats around */
 static void Disaster_Big_Submarine_Init()
 {
-	Vehicle *v = ForceAllocateSpecialVehicle();
+	Vehicle *v = new DisasterVehicle();
 	int x, y;
 	Direction dir;
 	uint32 r;
--- a/src/economy.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/economy.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -355,14 +355,14 @@
 								Vehicle *u = v;
 								do {
 									Vehicle *next = GetNextVehicle(u);
-									DeleteVehicle(u);
+									delete u;
 									u = next;
 								} while (u != NULL);
 							} break;
 
 							case VEH_ROAD:
 							case VEH_SHIP:
-								DeleteVehicle(v);
+								delete v;
 								break;
 
 							case VEH_AIRCRAFT:
--- a/src/roadveh_cmd.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/roadveh_cmd.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -185,7 +185,7 @@
 	Vehicle *vl[11];
 	memset(&vl, 0, sizeof(vl));
 
-	if (!AllocateVehicles(vl, num_vehicles)) {
+	if (!Vehicle::AllocateList(vl, num_vehicles)) {
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 	}
 
@@ -372,7 +372,7 @@
 		InvalidateWindow(WC_COMPANY, v->owner);
 		DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 		DeleteDepotHighlightOfVehicle(v);
-		DeleteVehicle(v);
+		delete v;
 	}
 
 	return CommandCost(-v->value);
@@ -610,7 +610,7 @@
 	BeginVehicleMove(v);
 	EndVehicleMove(v);
 
-	DeleteVehicle(v);
+	delete v;
 }
 
 static byte SetRoadVehPosition(Vehicle *v, int x, int y)
--- a/src/ship_cmd.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/ship_cmd.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -33,6 +33,7 @@
 #include "newgrf_sound.h"
 #include "date.h"
 #include "spritecache.h"
+#include "misc/autoptr.hpp"
 
 static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
 
@@ -833,8 +834,9 @@
 	if (!IsTileDepotType(tile, TRANSPORT_WATER)) return CMD_ERROR;
 	if (!IsTileOwner(tile, _current_player)) return CMD_ERROR;
 
-	v = AllocateVehicle();
+	v = new Ship();
 	unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_SHIP);
+	AutoPtrT<Vehicle> v_auto_delete = v;
 
 	if (v == NULL || unit_num > _patches.max_ships)
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
@@ -898,6 +900,8 @@
 			InvalidateAutoreplaceWindow(VEH_SHIP, v->group_id); // updates the replace Ship window
 
 		GetPlayer(_current_player)->num_engines[p1]++;
+
+		v_auto_delete.Detach();
 	}
 
 	return value;
@@ -931,7 +935,7 @@
 		InvalidateWindow(WC_COMPANY, v->owner);
 		DeleteWindowById(WC_VEHICLE_VIEW, v->index);
 		DeleteDepotHighlightOfVehicle(v);
-		DeleteVehicle(v);
+		delete v;
 	}
 
 	return CommandCost(-v->value);
--- a/src/train_cmd.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/train_cmd.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -518,7 +518,7 @@
 
 		memset(&vl, 0, sizeof(vl));
 
-		if (!AllocateVehicles(vl, num_vehicles))
+		if (!Vehicle::AllocateList(vl, num_vehicles))
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 		if (flags & DC_EXEC) {
@@ -686,7 +686,7 @@
 
 		memset(&vl, 0, sizeof(vl));
 
-		if (!AllocateVehicles(vl, num_vehicles))
+		if (!Vehicle::AllocateList(vl, num_vehicles))
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 		Vehicle *v = vl[0];
@@ -1253,7 +1253,7 @@
 				if (flags & DC_EXEC) {
 					UnlinkWagon(rear, first);
 					DeleteDepotHighlightOfVehicle(rear);
-					DeleteVehicle(rear);
+					delete rear;
 				}
 			}
 
@@ -1308,7 +1308,7 @@
 			if (flags & DC_EXEC) {
 				first = UnlinkWagon(v, first);
 				DeleteDepotHighlightOfVehicle(v);
-				DeleteVehicle(v);
+				delete v;
 
 				/* 4 If the second wagon was an engine, update it to front_engine
 					* which UnlinkWagon() has changed to TS_Free_Car */
@@ -1367,7 +1367,7 @@
 							if (flags & DC_EXEC) {
 								first = UnlinkWagon(rear, first);
 								DeleteDepotHighlightOfVehicle(rear);
-								DeleteVehicle(rear);
+								delete rear;
 							}
 						}
 					} else if (v->u.rail.other_multiheaded_part != NULL) {
@@ -1380,7 +1380,7 @@
 				if (flags & DC_EXEC) {
 					first = UnlinkWagon(v, first);
 					DeleteDepotHighlightOfVehicle(v);
-					DeleteVehicle(v);
+					delete v;
 					RemoveVehicleFromGroup(v);
 				}
 			}
@@ -3039,7 +3039,7 @@
 	BeginVehicleMove(v);
 	EndVehicleMove(v);
 
-	DeleteVehicle(v);
+	delete v;
 
 	if (v->u.rail.track != TRACK_BIT_DEPOT && v->u.rail.track != TRACK_BIT_WORMHOLE)
 		SetSignalsOnBothDir(v->tile, FIND_FIRST_BIT(v->u.rail.track));
@@ -3329,8 +3329,7 @@
 			TrainLocoHandler(this, true);
 	} else if (IsFreeWagon(this) && HASBITS(this->vehstatus, VS_CRASHED)) {
 		/* Delete flooded standalone wagon */
-		if (++this->u.rail.crash_anim_pos >= 4400)
-			DeleteVehicle(this);
+		if (++this->u.rail.crash_anim_pos >= 4400) delete this;
 	}
 }
 
--- a/src/vehicle.cpp	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/vehicle.cpp	Fri Aug 03 19:36:00 2007 +0000
@@ -282,28 +282,12 @@
 	}
 }
 
-static Vehicle *InitializeVehicle(Vehicle *v)
+Vehicle::Vehicle()
 {
-	VehicleID index = v->index;
-	memset(v, 0, sizeof(Vehicle));
-	v->index = index;
-
-	assert(v->orders == NULL);
-
-	v = new (v) InvalidVehicle();
-	v->left_coord = INVALID_COORD;
-	v->first = NULL;
-	v->next = NULL;
-	v->next_hash = NULL;
-	v->string_id = 0;
-	v->next_shared = NULL;
-	v->prev_shared = NULL;
-	v->depot_list  = NULL;
-	v->random_bits = 0;
-	v->group_id = DEFAULT_GROUP;
-	v->fill_percent_te_id = INVALID_TE_ID;
-
-	return v;
+	this->type               = VEH_INVALID;
+	this->left_coord         = INVALID_COORD;
+	this->group_id           = DEFAULT_GROUP;
+	this->fill_percent_te_id = INVALID_TE_ID;
 }
 
 /**
@@ -315,87 +299,21 @@
 	return GB(Random(), 0, 8);
 }
 
-Vehicle *ForceAllocateSpecialVehicle()
-{
-	/* This stays a strange story.. there should always be room for special
-	 * vehicles (special effects all over the map), but with 65k of vehicles
-	 * is this realistic to double-check for that? For now we just reserve
-	 * BLOCKS_FOR_SPECIAL_VEHICLES times block_size vehicles that may only
-	 * be used for special vehicles.. should work nicely :) */
-
-	Vehicle *v;
-
-	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
-	 * TODO - This is just a temporary stage, this will be removed. */
-	for (v = GetVehicle(0); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
-		/* No more room for the special vehicles, return NULL */
-		if (v->index >= (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES)
-			return NULL;
-
-		if (!v->IsValid()) return InitializeVehicle(v);
-	}
-
-	return NULL;
-}
-
-/**
- * finds a free vehicle in the memory or allocates a new one
- * returns a pointer to the first free vehicle or NULL if all vehicles are in use
- * *skip_vehicles is an offset to where in the array we should begin looking
- * this is to avoid looping though the same vehicles more than once after we learned that they are not free
- * this feature is used by AllocateVehicles() since it need to allocate more than one and when
- * another block is added to _Vehicle_pool, since we only do that when we know it's already full
- */
-static Vehicle *AllocateSingleVehicle(VehicleID *skip_vehicles)
+
+/* static */ bool Vehicle::AllocateList(Vehicle **vl, int num)
 {
-	/* See note by ForceAllocateSpecialVehicle() why we skip the
-	 * first blocks */
-	Vehicle *v;
-	const int offset = (1 << Vehicle_POOL_BLOCK_SIZE_BITS) * BLOCKS_FOR_SPECIAL_VEHICLES;
-
-	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
-	 * @todo - This is just a temporary stage, this will be removed. */
-	if (*skip_vehicles < (_Vehicle_pool.GetSize() - offset)) { // make sure the offset in the array is not larger than the array itself
-		for (v = GetVehicle(offset + *skip_vehicles); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
-			(*skip_vehicles)++;
-			if (!v->IsValid()) return InitializeVehicle(v);
-		}
-	}
-
-	/* Check if we can add a block to the pool */
-	if (AddBlockToPool(&_Vehicle_pool))
-		return AllocateSingleVehicle(skip_vehicles);
-
-	return NULL;
-}
-
-
-Vehicle *AllocateVehicle()
-{
-	VehicleID counter = 0;
-	return AllocateSingleVehicle(&counter);
-}
-
-
-/** Allocates a lot of vehicles and frees them again
- * @param vl pointer to an array of vehicles to get allocated. Can be NULL if the vehicles aren't needed (makes it test only)
- * @param num number of vehicles to allocate room for
- * @return true if there is room to allocate all the vehicles
- */
-bool AllocateVehicles(Vehicle **vl, int num)
-{
-	int i;
-	Vehicle *v;
-	VehicleID counter = 0;
-
-	for (i = 0; i != num; i++) {
-		v = AllocateSingleVehicle(&counter);
-		if (v == NULL) {
-			return false;
-		}
+	uint counter = _Vehicle_pool.first_free_index;
+
+	for (int i = 0; i != num; i++) {
+		Vehicle *v = AllocateRaw(counter);
+
+		if (v == NULL) return false;
+		v = new (v) InvalidVehicle();
+
 		if (vl != NULL) {
 			vl[i] = v;
 		}
+		counter++;
 	}
 
 	return true;
@@ -671,44 +589,51 @@
 	}
 }
 
-void DestroyVehicle(Vehicle *v)
+Vehicle::~Vehicle()
 {
-	if (IsValidStationID(v->last_station_visited)) {
-		GetStation(v->last_station_visited)->loading_vehicles.remove(v);
-
-		HideFillingPercent(v->fill_percent_te_id);
-		v->fill_percent_te_id = INVALID_TE_ID;
+	if (IsValidStationID(this->last_station_visited)) {
+		GetStation(this->last_station_visited)->loading_vehicles.remove(this);
+
+		HideFillingPercent(this->fill_percent_te_id);
+		this->fill_percent_te_id = INVALID_TE_ID;
 	}
 
-	if (IsEngineCountable(v)) {
-		GetPlayer(v->owner)->num_engines[v->engine_type]--;
-		if (v->owner == _local_player) InvalidateAutoreplaceWindow(v->engine_type, v->group_id);
-
-		if (IsValidGroupID(v->group_id)) GetGroup(v->group_id)->num_engines[v->engine_type]--;
-		if (v->IsPrimaryVehicle()) DecreaseGroupNumVehicle(v->group_id);
+	if (IsEngineCountable(this)) {
+		GetPlayer(this->owner)->num_engines[this->engine_type]--;
+		if (this->owner == _local_player) InvalidateAutoreplaceWindow(this->engine_type, this->group_id);
+
+		if (IsValidGroupID(this->group_id)) GetGroup(this->group_id)->num_engines[this->engine_type]--;
+		if (this->IsPrimaryVehicle()) DecreaseGroupNumVehicle(this->group_id);
 	}
 
-	DeleteVehicleNews(v->index, INVALID_STRING_ID);
-
-	DeleteName(v->string_id);
-	if (v->type == VEH_ROAD) ClearSlot(v);
-
-	if (v->type != VEH_TRAIN || (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v)))) {
-		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
+	DeleteVehicleNews(this->index, INVALID_STRING_ID);
+
+	this->QuickFree();
+	if (this->type == VEH_ROAD) ClearSlot(this);
+
+	if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (IsFrontEngine(this) || IsFreeWagon(this)))) {
+		InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
 	}
 
-	v->cargo.Truncate(0);
-	UpdateVehiclePosHash(v, INVALID_COORD, 0);
-	v->next_hash = NULL;
-	v->next_new_hash = NULL;
-	if (IsPlayerBuildableVehicleType(v)) DeleteVehicleOrders(v);
+	this->cargo.Truncate(0);
+	UpdateVehiclePosHash(this, INVALID_COORD, 0);
+	this->next_hash = NULL;
+	this->next_new_hash = NULL;
+	if (IsPlayerBuildableVehicleType(this)) DeleteVehicleOrders(this);
 
 	/* Now remove any artic part. This will trigger an other
 	 *  destroy vehicle, which on his turn can remove any
 	 *  other artic parts. */
-	if ((v->type == VEH_TRAIN && EngineHasArticPart(v)) || (v->type == VEH_ROAD && RoadVehHasArticPart(v))) {
-		DeleteVehicle(v->next);
+	if ((this->type == VEH_TRAIN && EngineHasArticPart(this)) || (this->type == VEH_ROAD && RoadVehHasArticPart(this))) {
+		delete this->next;
 	}
+
+	new (this) InvalidVehicle();
+}
+
+void Vehicle::QuickFree()
+{
+	DeleteName(this->string_id);
 }
 
 /**
@@ -725,7 +650,7 @@
 	do {
 		Vehicle *u = v;
 		v = v->next;
-		DeleteVehicle(u);
+		delete u;
 	} while (v != NULL);
 }
 
@@ -932,7 +857,7 @@
 		tile = TileVirtXY(v->x_pos, v->y_pos);
 		if (!IsTileType(tile, MP_INDUSTRY)) {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 			return;
 		}
 
@@ -971,7 +896,7 @@
 			v->cur_image++;
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 			return;
 		}
 		moved = true;
@@ -1006,7 +931,7 @@
 			EndVehicleMove(v);
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 		}
 	}
 }
@@ -1030,7 +955,7 @@
 			EndVehicleMove(v);
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 		}
 	}
 }
@@ -1059,7 +984,7 @@
 			v->cur_image++;
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 			return;
 		}
 		moved = true;
@@ -1088,7 +1013,7 @@
 			EndVehicleMove(v);
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 		}
 	}
 }
@@ -1117,7 +1042,7 @@
 	if (v->u.special.animation_state == 0) {
 		BeginVehicleMove(v);
 		EndVehicleMove(v);
-		DeleteVehicle(v);
+		delete v;
 	}
 }
 
@@ -1138,7 +1063,7 @@
 			EndVehicleMove(v);
 		} else {
 			EndVehicleMove(v);
-			DeleteVehicle(v);
+			delete v;
 		}
 	}
 }
@@ -1209,7 +1134,7 @@
 			v->u.special.animation_state++;
 			if (v->u.special.animation_state == lengthof(_bulldozer_movement)) {
 				EndVehicleMove(v);
-				DeleteVehicle(v);
+				delete v;
 				return;
 			}
 		}
@@ -1413,7 +1338,7 @@
 
 	if (b->y == 4 && b->x == 0) {
 		EndVehicleMove(v);
-		DeleteVehicle(v);
+		delete v;
 		return;
 	}
 
@@ -1482,9 +1407,8 @@
 {
 	Vehicle *v;
 
-	v = ForceAllocateSpecialVehicle();
+	v = new SpecialVehicle();
 	if (v != NULL) {
-		v = new (v) SpecialVehicle();
 		v->subtype = type;
 		v->x_pos = x;
 		v->y_pos = y;
@@ -1878,7 +1802,7 @@
 			veh_counter++;
 		} while ((v = v->next) != NULL);
 
-		if (!AllocateVehicles(NULL, veh_counter)) {
+		if (!Vehicle::AllocateList(NULL, veh_counter)) {
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 		}
 	}
@@ -3091,7 +3015,7 @@
 };
 
 
-static const void *_veh_descs[] = {
+static const SaveLoad *_veh_descs[] = {
 	_train_desc,
 	_roadveh_desc,
 	_ship_desc,
@@ -3107,7 +3031,7 @@
 	/* Write the vehicles */
 	FOR_ALL_VEHICLES(v) {
 		SlSetArrayIndex(v->index);
-		SlObject(v, (SaveLoad*)_veh_descs[v->type]);
+		SlObject(v, _veh_descs[v->type]);
 	}
 }
 
@@ -3121,25 +3045,20 @@
 
 	while ((index = SlIterateArray()) != -1) {
 		Vehicle *v;
-
-		if (!AddBlockIfNeeded(&_Vehicle_pool, index))
-			error("Vehicles: failed loading savegame: too many vehicles");
-
-		v = GetVehicle(index);
 		VehicleType vtype = (VehicleType)SlReadByte();
 
 		switch (vtype) {
-			case VEH_TRAIN:    v = new (v) Train();           break;
-			case VEH_ROAD:     v = new (v) RoadVehicle();     break;
-			case VEH_SHIP:     v = new (v) Ship();            break;
-			case VEH_AIRCRAFT: v = new (v) Aircraft();        break;
-			case VEH_SPECIAL:  v = new (v) SpecialVehicle();  break;
-			case VEH_DISASTER: v = new (v) DisasterVehicle(); break;
-			case VEH_INVALID:  v = new (v) InvalidVehicle();  break;
+			case VEH_TRAIN:    v = new (index) Train();           break;
+			case VEH_ROAD:     v = new (index) RoadVehicle();     break;
+			case VEH_SHIP:     v = new (index) Ship();            break;
+			case VEH_AIRCRAFT: v = new (index) Aircraft();        break;
+			case VEH_SPECIAL:  v = new (index) SpecialVehicle();  break;
+			case VEH_DISASTER: v = new (index) DisasterVehicle(); break;
+			case VEH_INVALID:  v = new (index) InvalidVehicle();  break;
 			default: NOT_REACHED();
 		}
 
-		SlObject(v, (SaveLoad*)_veh_descs[vtype]);
+		SlObject(v, _veh_descs[vtype]);
 
 		if (_cargo_count != 0 && IsPlayerBuildableVehicleType(v)) {
 			/* Don't construct the packet with station here, because that'll fail with old savegames */
--- a/src/vehicle.h	Fri Aug 03 18:34:47 2007 +0000
+++ b/src/vehicle.h	Fri Aug 03 19:36:00 2007 +0000
@@ -215,13 +215,13 @@
 	TrackBitsByte state;
 };
 
+struct Vehicle;
+DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125)
 
-struct Vehicle {
+struct Vehicle : PoolItem<Vehicle, VehicleID, &_Vehicle_pool> {
 	VehicleTypeByte type;    ///< Type of vehicle
 	byte subtype;            // subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes)
 
-	VehicleID index;         // NOSAVE: Index in vehicle array
-
 	Vehicle *next;           // next
 	Vehicle *first;          // NOSAVE: pointer to the first vehicle in the chain
 	Vehicle *depot_list;     //NOSAVE: linked list to tell what vehicles entered a depot during the last tick. Used by autoreplace
@@ -335,6 +335,23 @@
 		VehicleShip ship;
 	} u;
 
+
+	/**
+	 * Allocates a lot of vehicles.
+	 * @param vl pointer to an array of vehicles to get allocated. Can be NULL if the vehicles aren't needed (makes it test only)
+	 * @param num number of vehicles to allocate room for
+	 * @return true if there is room to allocate all the vehicles
+	 */
+	static bool AllocateList(Vehicle **vl, int num);
+
+	/** Create a new vehicle */
+	Vehicle();
+
+	/** We want to 'destruct' the right class. */
+	virtual ~Vehicle();
+
+	void QuickFree();
+
 	void BeginLoading();
 	void LeaveStation();
 
@@ -346,37 +363,6 @@
 	void HandleLoading(bool mode = false);
 
 	/**
-	 * An overriden version of new, so you can use the vehicle instance
-	 * instead of a newly allocated piece of memory.
-	 * @param size the size of the variable (unused)
-	 * @param v    the vehicle to use as 'storage' backend
-	 * @return the memory that is 'allocated'
-	 */
-	void *operator new(size_t size, Vehicle *v) { return v; }
-
-	/**
-	 * 'Free' the memory allocated by the overriden new.
-	 * @param p the memory to 'free'
-	 * @param v the vehicle that was given to 'new' on creation.
-	 * @note This function isn't used (at the moment) and only added
-	 *       to please some compiler.
-	 */
-	void operator delete(void *p, Vehicle *v) {}
-
-	/**
-	 * 'Free' the memory allocated by the overriden new.
-	 * @param p the memory to 'free'
-	 * @note This function isn't used (at the moment) and only added
-	 *       as the above function was needed to please some compiler
-	 *       which made it necessary to add this to please yet
-	 *       another compiler...
-	 */
-	void operator delete(void *p) {}
-
-	/** We want to 'destruct' the right class. */
-	virtual ~Vehicle() {}
-
-	/**
 	 * Get a string 'representation' of the vehicle type.
 	 * @return the string representation.
 	 */
@@ -509,10 +495,6 @@
 typedef void *VehicleFromPosProc(Vehicle *v, void *data);
 
 void VehicleServiceInDepot(Vehicle *v);
-Vehicle *AllocateVehicle();
-bool AllocateVehicles(Vehicle **vl, int num);
-Vehicle *ForceAllocateVehicle();
-Vehicle *ForceAllocateSpecialVehicle();
 void VehiclePositionChanged(Vehicle *v);
 void AfterLoadVehicles();
 Vehicle *GetLastVehicleInChain(Vehicle *v);
@@ -619,8 +601,6 @@
 #define BEGIN_ENUM_WAGONS(v) do {
 #define END_ENUM_WAGONS(v) } while ((v = v->next) != NULL);
 
-DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 125)
-
 static inline VehicleID GetMaxVehicleIndex()
 {
 	/* TODO - This isn't the real content of the function, but
@@ -636,14 +616,6 @@
 	return GetVehiclePoolSize();
 }
 
-void DestroyVehicle(Vehicle *v);
-
-static inline void DeleteVehicle(Vehicle *v)
-{
-	DestroyVehicle(v);
-	v = new (v) InvalidVehicle();
-}
-
 static inline bool IsPlayerBuildableVehicleType(VehicleType type)
 {
 	switch (type) {