summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/aircraft.h18
-rw-r--r--src/aircraft_cmd.cpp5
-rw-r--r--src/disaster_cmd.cpp2
-rw-r--r--src/oldloader.cpp18
-rw-r--r--src/roadveh.h19
-rw-r--r--src/roadveh_cmd.cpp2
-rw-r--r--src/ship.h19
-rw-r--r--src/ship_cmd.cpp2
-rw-r--r--src/train.h18
-rw-r--r--src/train_cmd.cpp8
-rw-r--r--src/vehicle.cpp88
-rw-r--r--src/vehicle.h103
12 files changed, 246 insertions, 56 deletions
diff --git a/src/aircraft.h b/src/aircraft.h
index eb11f755a..0876fee7f 100644
--- a/src/aircraft.h
+++ b/src/aircraft.h
@@ -115,4 +115,22 @@ void UpdateAirplanesOnNewStation(const Station *st);
*/
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 */
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
index c704645db..4993b6d4a 100644
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -269,7 +269,8 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
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 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
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;
diff --git a/src/disaster_cmd.cpp b/src/disaster_cmd.cpp
index 9368646de..c6cc16a05 100644
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -121,7 +121,7 @@ static void DisasterVehicleUpdateImage(Vehicle *v)
* 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;
diff --git a/src/oldloader.cpp b/src/oldloader.cpp
index ad28db2d2..ed8e5ee68 100644
--- a/src/oldloader.cpp
+++ b/src/oldloader.cpp
@@ -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 @@ static bool LoadOldVehicleUnion(LoadgameState *ls, int num)
* 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 */
diff --git a/src/roadveh.h b/src/roadveh.h
index 410dab64e..1e9ec8180 100644
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -22,4 +22,23 @@ static inline bool IsRoadVehInDepotStopped(const Vehicle* v)
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 */
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 5f8612bc9..012233164 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -205,7 +205,7 @@ int32 CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
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();
diff --git a/src/ship.h b/src/ship.h
index 4a9ce9190..6c64e4a7a 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -23,4 +23,23 @@ static inline bool IsShipInDepotStopped(const Vehicle* v)
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 */
diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp
index 6e4d44d94..10c93d97f 100644
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -910,7 +910,7 @@ int32 CmdBuildShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
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;
diff --git a/src/train.h b/src/train.h
index c39712e96..33ffc1632 100644
--- a/src/train.h
+++ b/src/train.h
@@ -228,4 +228,22 @@ void CcCloneTrain(bool success, TileIndex tile, uint32 p1, uint32 p2);
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 */
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 6de1b96e0..936d13c61 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -552,7 +552,7 @@ static void AddArticulatedParts(Vehicle **vl)
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 @@ static int32 CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 flags)
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 @@ static void AddRearEngineToMultiheadedTrain(Vehicle* v, Vehicle* u, bool buildin
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 @@ int32 CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
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();
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index dccebcd5d..5338bd554 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -89,7 +89,7 @@ static void VehiclePoolNewBlock(uint start_item)
* 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 @@ static Vehicle *InitializeVehicle(Vehicle *v)
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 @@ Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type)
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 @@ extern const SaveLoad _common_veh_desc[] = {
/* 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 @@ extern const SaveLoad _common_veh_desc[] = {
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_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(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_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 _train_desc[] = {
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 _roadveh_desc[] = {
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 _ship_desc[] = {
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_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(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_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(offsetof(Vehicle, u) + offsetof(VehicleAir, state), SLE_UINT8),
+ SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleAir, state), SLE_UINT8),
- SLE_CONDVARX(offsetof(Vehicle, u) + offsetof(VehicleAir, previous_pos), SLE_UINT8, 2, SL_MAX_VERSION),
+ 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 @@ static const SaveLoad _special_desc[] = {
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 @@ static const SaveLoad _disaster_desc[] = {
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 @@ static void Load_VEHS()
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;
diff --git a/src/vehicle.h b/src/vehicle.h
index 4d4b51abc..df5daf1a4 100644
--- a/src/vehicle.h
+++ b/src/vehicle.h
@@ -316,6 +316,107 @@ struct Vehicle {
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 @@ void DestroyVehicle(Vehicle *v);
static inline void DeleteVehicle(Vehicle *v)
{
DestroyVehicle(v);
- v->type = VEH_INVALID;
+ v = new (v) InvalidVehicle();
}
static inline bool IsPlayerBuildableVehicleType(byte type)