diff --git a/src/aircraft.h b/src/aircraft.h index eb11f755a8..0876fee7f4 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 c704645db2..4993b6d4ab 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 9368646de1..c6cc16a05c 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 ad28db2d21..ed8e5ee68e 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 410dab64ec..1e9ec81805 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 5f8612bc96..012233164a 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 4a9ce9190c..6c64e4a7a8 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 6e4d44d94a..10c93d97fb 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 c39712e962..33ffc16322 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 6de1b96e05..936d13c614 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 dccebcd5d8..5338bd554c 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_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(offsetof(Vehicle, u) + offsetof(VehicleRoad, slot), REF_ROADSTOPS, 6, SL_MAX_VERSION), + 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 4d4b51abc6..df5daf1a42 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)