(svn r9754) -Codechange: make classes for all vehicle types, so we can make nicer/better maintainable code, i.e. virtual methods instead of switches.
authorrubidium
Sun, 29 Apr 2007 21:24:08 +0000
changeset 7048 06b931095b26
parent 7047 578d7e38b601
child 7049 01825af2ce90
(svn r9754) -Codechange: make classes for all vehicle types, so we can make nicer/better maintainable code, i.e. virtual methods instead of switches.
src/aircraft.h
src/aircraft_cmd.cpp
src/disaster_cmd.cpp
src/oldloader.cpp
src/roadveh.h
src/roadveh_cmd.cpp
src/ship.h
src/ship_cmd.cpp
src/train.h
src/train_cmd.cpp
src/vehicle.cpp
src/vehicle.h
--- a/src/aircraft.h	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/aircraft.h	Sun Apr 29 21:24:08 2007 +0000
@@ -115,4 +115,22 @@
  */
 void UpdateAircraftCache(Vehicle *v);
 
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Aircraft();
+ *
+ * As side-effect the vehicle type is set correctly.
+ */
+struct Aircraft : public Vehicle {
+	/** Initializes the Vehicle to an aircraft */
+	Aircraft() { this->type = VEH_AIRCRAFT; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~Aircraft() {}
+
+	const char *GetTypeString() { return "aircraft"; }
+};
+
 #endif /* AIRCRAFT_H */
--- a/src/aircraft_cmd.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/aircraft_cmd.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -269,7 +269,8 @@
 		Vehicle *u = vl[1]; // shadow
 
 		v->unitnumber = unit_num;
-		v->type = u->type = VEH_AIRCRAFT;
+		v = new (v) Aircraft();
+		u = new (u) Aircraft();
 		v->direction = DIR_SE;
 
 		v->owner = u->owner = _current_player;
@@ -404,7 +405,7 @@
 
 			u->next = w;
 
-			w->type = VEH_AIRCRAFT;
+			w = new (w) Aircraft();
 			w->direction = DIR_N;
 			w->owner = _current_player;
 			w->x_pos = v->x_pos;
--- a/src/disaster_cmd.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/disaster_cmd.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -121,7 +121,7 @@
  * and owned by nobody */
 static void InitializeDisasterVehicle(Vehicle *v, int x, int y, byte z, Direction direction, byte subtype)
 {
-	v->type = VEH_DISASTER;
+	v = new (v) DisasterVehicle();
 	v->x_pos = x;
 	v->y_pos = y;
 	v->z_pos = z;
--- a/src/oldloader.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/oldloader.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -15,6 +15,10 @@
 #include "player.h"
 #include "engine.h"
 #include "vehicle.h"
+#include "aircraft.h"
+#include "roadveh.h"
+#include "ship.h"
+#include "train.h"
 #include "signs.h"
 #include "debug.h"
 #include "depot.h"
@@ -1070,13 +1074,13 @@
 	 * Basically v->type -= 0x10; would suffice, but play safely */
 	switch (v->type) {
 		default: NOT_REACHED();
-		case 0x00 /*VEH_INVALID */: v->type = VEH_INVALID;  res = LoadChunk(ls, NULL,           vehicle_empty_chunk);    break;
-		case 0x10 /*VEH_TRAIN   */: v->type = VEH_TRAIN;    res = LoadChunk(ls, &v->u.rail,     vehicle_train_chunk);    break;
-		case 0x11 /*VEH_ROAD    */: v->type = VEH_ROAD;     res = LoadChunk(ls, &v->u.road,     vehicle_road_chunk);     break;
-		case 0x12 /*VEH_SHIP    */: v->type = VEH_SHIP;     res = LoadChunk(ls, &v->u.ship,     vehicle_ship_chunk);     break;
-		case 0x13 /*VEH_AIRCRAFT*/: v->type = VEH_AIRCRAFT; res = LoadChunk(ls, &v->u.air,      vehicle_air_chunk);      break;
-		case 0x14 /*VEH_SPECIAL */: v->type = VEH_SPECIAL;  res = LoadChunk(ls, &v->u.special,  vehicle_special_chunk);  break;
-		case 0x15 /*VEH_DISASTER*/: v->type = VEH_DISASTER; res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break;
+		case 0x00 /*VEH_INVALID */: v = new (v) InvalidVehicle();  res = LoadChunk(ls, NULL,           vehicle_empty_chunk);    break;
+		case 0x10 /*VEH_TRAIN   */: v = new (v) Train();           res = LoadChunk(ls, &v->u.rail,     vehicle_train_chunk);    break;
+		case 0x11 /*VEH_ROAD    */: v = new (v) RoadVehicle();     res = LoadChunk(ls, &v->u.road,     vehicle_road_chunk);     break;
+		case 0x12 /*VEH_SHIP    */: v = new (v) Ship();            res = LoadChunk(ls, &v->u.ship,     vehicle_ship_chunk);     break;
+		case 0x13 /*VEH_AIRCRAFT*/: v = new (v) Aircraft();        res = LoadChunk(ls, &v->u.air,      vehicle_air_chunk);      break;
+		case 0x14 /*VEH_SPECIAL */: v = new (v) SpecialVehicle();  res = LoadChunk(ls, &v->u.special,  vehicle_special_chunk);  break;
+		case 0x15 /*VEH_DISASTER*/: v = new (v) DisasterVehicle(); res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break;
 	}
 
 	/* This chunk size should always be 10 bytes */
--- a/src/roadveh.h	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/roadveh.h	Sun Apr 29 21:24:08 2007 +0000
@@ -22,4 +22,23 @@
 void CcBuildRoadVeh(bool success, TileIndex tile, uint32 p1, uint32 p2);
 void CcCloneRoadVeh(bool success, TileIndex tile, uint32 p1, uint32 p2);
 
+
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) RoadVehicle();
+ *
+ * As side-effect the vehicle type is set correctly.
+ */
+struct RoadVehicle : public Vehicle {
+	/** Initializes the Vehicle to a road vehicle */
+	RoadVehicle() { this->type = VEH_ROAD; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~RoadVehicle() {}
+
+	const char *GetTypeString() { return "road vehicle"; }
+};
+
 #endif /* ROADVEH_H */
--- a/src/roadveh_cmd.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/roadveh_cmd.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -205,7 +205,7 @@
 		v->date_of_last_service = _date;
 		v->build_year = _cur_year;
 
-		v->type = VEH_ROAD;
+		v = new (v) RoadVehicle();
 		v->cur_image = 0xC15;
 		v->random_bits = VehicleRandomBits();
 
--- a/src/ship.h	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/ship.h	Sun Apr 29 21:24:08 2007 +0000
@@ -23,4 +23,23 @@
 	return IsShipInDepot(v) && v->vehstatus & VS_STOPPED;
 }
 
+
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Ship();
+ *
+ * As side-effect the vehicle type is set correctly.
+ */
+struct Ship: public Vehicle {
+	/** Initializes the Vehicle to a ship */
+	Ship() { this->type = VEH_SHIP; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~Ship() {}
+
+	const char *GetTypeString() { return "ship"; }
+};
+
 #endif /* SHIP_H */
--- a/src/ship_cmd.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/ship_cmd.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -910,7 +910,7 @@
 		v->date_of_last_service = _date;
 		v->build_year = _cur_year;
 		v->cur_image = 0x0E5E;
-		v->type = VEH_SHIP;
+		v = new (v) Ship();
 		v->random_bits = VehicleRandomBits();
 
 		v->vehicle_flags = 0;
--- a/src/train.h	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/train.h	Sun Apr 29 21:24:08 2007 +0000
@@ -228,4 +228,22 @@
 
 byte FreightWagonMult(CargoID cargo);
 
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Train();
+ *
+ * As side-effect the vehicle type is set correctly.
+ */
+struct Train : public Vehicle {
+	/** Initializes the Vehicle to a train */
+	Train() { this->type = VEH_TRAIN; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~Train() {}
+
+	const char *GetTypeString() { return "train"; }
+};
+
 #endif /* TRAIN_H */
--- a/src/train_cmd.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/train_cmd.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -552,7 +552,7 @@
 		u->max_age = 0;
 		u->engine_type = engine_type;
 		u->value = 0;
-		u->type = VEH_TRAIN;
+		u = new (u) Train();
 		u->subtype = 0;
 		SetArticulatedPart(u);
 		u->cur_image = 0xAC2;
@@ -630,7 +630,7 @@
 			v->u.rail.railtype = rvi->railtype;
 
 			v->build_year = _cur_year;
-			v->type = VEH_TRAIN;
+			v = new (v) Train();
 			v->cur_image = 0xAC2;
 			v->random_bits = VehicleRandomBits();
 
@@ -696,7 +696,7 @@
 	u->build_year = v->build_year;
 	if (building) v->value >>= 1;
 	u->value = v->value;
-	u->type = VEH_TRAIN;
+	u = new (u) Train();
 	u->cur_image = 0xAC2;
 	u->random_bits = VehicleRandomBits();
 	VehiclePositionChanged(u);
@@ -789,7 +789,7 @@
 			v->service_interval = _patches.servint_trains;
 			v->date_of_last_service = _date;
 			v->build_year = _cur_year;
-			v->type = VEH_TRAIN;
+			v = new (v) Train();
 			v->cur_image = 0xAC2;
 			v->random_bits = VehicleRandomBits();
 
--- a/src/vehicle.cpp	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/vehicle.cpp	Sun Apr 29 21:24:08 2007 +0000
@@ -89,7 +89,7 @@
 	 * TODO - This is just a temporary stage, this will be removed. */
 	for (v = GetVehicle(start_item); v != NULL; v = (v->index + 1U < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) {
 		v->index = start_item++;
-		v->type  = VEH_INVALID;
+		v = new (v) InvalidVehicle();
 	}
 }
 
@@ -271,7 +271,7 @@
 
 	assert(v->orders == NULL);
 
-	v->type = VEH_INVALID;
+	v = new (v) InvalidVehicle();
 	v->left_coord = INVALID_COORD;
 	v->first = NULL;
 	v->next = NULL;
@@ -1438,7 +1438,7 @@
 
 	v = ForceAllocateSpecialVehicle();
 	if (v != NULL) {
-		v->type = VEH_SPECIAL;
+		v = new (v) SpecialVehicle();
 		v->subtype = type;
 		v->x_pos = x;
 		v->y_pos = y;
@@ -2681,17 +2681,17 @@
 	/* This next line is for version 4 and prior compatibility.. it temporarily reads
 	    type and flags (which were both 4 bits) into type. Later on this is
 	    converted correctly */
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, type), SLE_UINT8,                 0, 4),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, dest), SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, type), SLE_UINT8,                 0, 4),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, dest), SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
 
 	/* Orders for version 5 and on */
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, type),  SLE_UINT8,  5, SL_MAX_VERSION),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, flags), SLE_UINT8,  5, SL_MAX_VERSION),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, dest),  SLE_UINT16, 5, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, type),  SLE_UINT8,  5, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, flags), SLE_UINT8,  5, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, dest),  SLE_UINT16, 5, SL_MAX_VERSION),
 
 	/* Refit in current order */
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, refit_cargo),    SLE_UINT8, 36, SL_MAX_VERSION),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, refit_subtype),  SLE_UINT8, 36, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, refit_cargo),    SLE_UINT8, 36, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, refit_subtype),  SLE_UINT8, 36, SL_MAX_VERSION),
 
 	    SLE_REF(Vehicle, orders,               REF_ORDER),
 
@@ -2738,13 +2738,13 @@
 static const SaveLoad _train_desc[] = {
 	SLE_WRITEBYTE(Vehicle, type, VEH_TRAIN, 0), // Train type. VEH_TRAIN in mem, 0 in file.
 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, crash_anim_pos),         SLE_UINT16),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, force_proceed),          SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, railtype),               SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRail, track),                  SLE_UINT8),
-
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, flags),                  SLE_UINT8,  2, SL_MAX_VERSION),
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, crash_anim_pos),         SLE_UINT16),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, force_proceed),          SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, railtype),               SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, track),                  SLE_UINT8),
+
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, flags),                  SLE_UINT8,  2, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRail, days_since_order_progr), SLE_UINT16, 2, SL_MAX_VERSION),
 
 	SLE_CONDNULL(2, 2, 19),
 	/* reserve extra space in savegame here. (currently 11 bytes) */
@@ -2756,17 +2756,17 @@
 static const SaveLoad _roadveh_desc[] = {
 	SLE_WRITEBYTE(Vehicle, type, VEH_ROAD, 1), // Road type. VEH_ROAD in mem, 1 in file.
 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, state),          SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, frame),          SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, blocked_ctr),    SLE_UINT16),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, overtaking),     SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, overtaking_ctr), SLE_UINT8),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, crashed_ctr),    SLE_UINT16),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, reverse_ctr),    SLE_UINT8),
-
-	SLE_CONDREFX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot),     REF_ROADSTOPS, 6, SL_MAX_VERSION),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, state),          SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, frame),          SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, blocked_ctr),    SLE_UINT16),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, overtaking),     SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, overtaking_ctr), SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, crashed_ctr),    SLE_UINT16),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, reverse_ctr),    SLE_UINT8),
+
+	SLE_CONDREFX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, slot),     REF_ROADSTOPS, 6, SL_MAX_VERSION),
 	SLE_CONDNULL(1,                                                                     6, SL_MAX_VERSION),
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot_age), SLE_UINT8,     6, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleRoad, slot_age), SLE_UINT8,     6, SL_MAX_VERSION),
 	/* reserve extra space in savegame here. (currently 16 bytes) */
 	SLE_CONDNULL(16,                                                                    2, SL_MAX_VERSION),
 
@@ -2776,7 +2776,7 @@
 static const SaveLoad _ship_desc[] = {
 	SLE_WRITEBYTE(Vehicle, type, VEH_SHIP, 2), // Ship type. VEH_SHIP in mem, 2 in file.
 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
-	SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleShip, state), SLE_UINT8),
+	SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleShip, state), SLE_UINT8),
 
 	/* reserve extra space in savegame here. (currently 16 bytes) */
 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
@@ -2787,15 +2787,15 @@
 static const SaveLoad _aircraft_desc[] = {
 	SLE_WRITEBYTE(Vehicle, type, VEH_AIRCRAFT, 3), // Aircraft type. VEH_AIRCRAFT in mem, 3 in file.
 	SLE_INCLUDEX(0, INC_VEHICLE_COMMON),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, crashed_counter), SLE_UINT16),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, pos),             SLE_UINT8),
-
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, targetairport),   SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, targetairport),   SLE_UINT16,                5, SL_MAX_VERSION),
-
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleAir, state),           SLE_UINT8),
-
-	SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos),    SLE_UINT8,                 2, SL_MAX_VERSION),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, crashed_counter), SLE_UINT16),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, pos),             SLE_UINT8),
+
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, targetairport),   SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, targetairport),   SLE_UINT16,                5, SL_MAX_VERSION),
+
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, state),           SLE_UINT8),
+
+	SLE_CONDVARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, previous_pos),    SLE_UINT8,                 2, SL_MAX_VERSION),
 
 	/* reserve extra space in savegame here. (currently 15 bytes) */
 	SLE_CONDNULL(15,                                                                                      2, SL_MAX_VERSION),
@@ -2826,8 +2826,8 @@
 	    SLE_VAR(Vehicle, progress,      SLE_UINT8),
 	    SLE_VAR(Vehicle, vehstatus,     SLE_UINT8),
 
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk0), SLE_UINT16),
-	    SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleSpecial, unk2), SLE_UINT8),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, unk0), SLE_UINT16),
+	    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, unk2), SLE_UINT8),
 
 	/* reserve extra space in savegame here. (currently 16 bytes) */
 	SLE_CONDNULL(16, 2, SL_MAX_VERSION),
@@ -2860,16 +2860,16 @@
 	    SLE_VAR(Vehicle, z_height,      SLE_UINT8),
 	    SLE_VAR(Vehicle, owner,         SLE_UINT8),
 	    SLE_VAR(Vehicle, vehstatus,     SLE_UINT8),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, dest), SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
-	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, dest), SLE_UINT16,                5, SL_MAX_VERSION),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, dest), SLE_FILE_U8 | SLE_VAR_U16, 0, 4),
+	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, dest), SLE_UINT16,                5, SL_MAX_VERSION),
 
 	    SLE_VAR(Vehicle, cur_image,     SLE_UINT16),
 	SLE_CONDVAR(Vehicle, age,           SLE_FILE_U16 | SLE_VAR_I32,  0, 30),
 	SLE_CONDVAR(Vehicle, age,           SLE_INT32,                  31, SL_MAX_VERSION),
 	    SLE_VAR(Vehicle, tick_counter,  SLE_UINT8),
 
-	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, image_override), SLE_UINT16),
-	   SLE_VARX(offsetof(Vehicle, u) + offsetof(VehicleDisaster, unk2),           SLE_UINT16),
+	   SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleDisaster, image_override), SLE_UINT16),
+	   SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleDisaster, unk2),           SLE_UINT16),
 
 	/* reserve extra space in savegame here. (currently 16 bytes) */
 	SLE_CONDNULL(16,                                                 2, SL_MAX_VERSION),
@@ -2913,6 +2913,16 @@
 		v = GetVehicle(index);
 		SlObject(v, (SaveLoad*)_veh_descs[SlReadByte()]);
 
+		switch (v->type) {
+			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;
+		}
+
 		/* Old savegames used 'last_station_visited = 0xFF' */
 		if (CheckSavegameVersion(5) && v->last_station_visited == 0xFF)
 			v->last_station_visited = INVALID_STATION;
--- a/src/vehicle.h	Sun Apr 29 20:16:58 2007 +0000
+++ b/src/vehicle.h	Sun Apr 29 21:24:08 2007 +0000
@@ -316,6 +316,107 @@
 
 	void BeginLoading();
 	void LeaveStation();
+
+	/**
+	 * 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.
+	 */
+	virtual const char* GetTypeString() = 0;
+};
+
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Train();
+ *
+ * As side-effect the vehicle type is set correctly.
+ *
+ * A special vehicle is one of the following:
+ *  - smoke
+ *  - electric sparks for trains
+ *  - explosions
+ *  - bulldozer (road works)
+ *  - bubbles (industry)
+ */
+struct SpecialVehicle : public Vehicle {
+	/** Initializes the Vehicle to a special vehicle */
+	SpecialVehicle() { this->type = VEH_SPECIAL; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~SpecialVehicle() {}
+
+	const char *GetTypeString() { return "special vehicle"; }
+};
+
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Train();
+ *
+ * As side-effect the vehicle type is set correctly.
+ */
+struct DisasterVehicle : public Vehicle {
+	/** Initializes the Vehicle to a disaster vehicle */
+	DisasterVehicle() { this->type = VEH_DISASTER; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~DisasterVehicle() {}
+
+	const char *GetTypeString() { return "disaster vehicle"; }
+};
+
+/**
+ * This class 'wraps' Vehicle; you do not actually instantiate this class.
+ * You create a Vehicle using AllocateVehicle, so it is added to the pool
+ * and you reinitialize that to a Train using:
+ *   v = new (v) Train();
+ *
+ * As side-effect the vehicle type is set correctly.
+ *
+ * An invalid vehicle must never be used; all (virtual) functions from
+ * Vehicle should assert (NOT_REACHED).
+ */
+struct InvalidVehicle : public Vehicle {
+	/** Initializes the Vehicle to a invalid vehicle */
+	InvalidVehicle() { this->type = VEH_INVALID; }
+
+	/** We want to 'destruct' the right class. */
+	virtual ~InvalidVehicle() {}
+
+	const char *GetTypeString() { return "invalid vehicle"; }
 };
 
 #define is_custom_sprite(x) (x >= 0xFD)
@@ -470,7 +571,7 @@
 static inline void DeleteVehicle(Vehicle *v)
 {
 	DestroyVehicle(v);
-	v->type = VEH_INVALID;
+	v = new (v) InvalidVehicle();
 }
 
 static inline bool IsPlayerBuildableVehicleType(byte type)