summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsmatz <smatz@openttd.org>2009-05-26 22:10:13 +0000
committersmatz <smatz@openttd.org>2009-05-26 22:10:13 +0000
commit7ee882d03f4c41d8659ed82fd5be0d0efbae0a0c (patch)
tree7107a4626a58464bd677e9fb8f7576cadf1b8bf2
parentaa546e513f6b121377fd1b6cad1b727f89b66528 (diff)
downloadopenttd-7ee882d03f4c41d8659ed82fd5be0d0efbae0a0c.tar.xz
(svn r16441) -Codechange: new class SpecializedVehicle used as superclass for all vehicle types
-rw-r--r--src/ai/api/ai_vehicle.cpp5
-rw-r--r--src/aircraft.h6
-rw-r--r--src/aircraft_cmd.cpp7
-rw-r--r--src/effectvehicle_base.h2
-rw-r--r--src/elrail.cpp12
-rw-r--r--src/roadveh.h7
-rw-r--r--src/roadveh_cmd.cpp8
-rw-r--r--src/saveload/afterload.cpp56
-rw-r--r--src/saveload/vehicle_sl.cpp24
-rw-r--r--src/settings.cpp13
-rw-r--r--src/ship.h2
-rw-r--r--src/station.cpp16
-rw-r--r--src/train.h10
-rw-r--r--src/train_cmd.cpp56
-rw-r--r--src/vehicle_base.h61
15 files changed, 150 insertions, 135 deletions
diff --git a/src/ai/api/ai_vehicle.cpp b/src/ai/api/ai_vehicle.cpp
index fb6c8abdc..a905d42c6 100644
--- a/src/ai/api/ai_vehicle.cpp
+++ b/src/ai/api/ai_vehicle.cpp
@@ -28,8 +28,9 @@
if (!IsValidVehicle(vehicle_id)) return -1;
int num = 1;
- if (::Vehicle::Get(vehicle_id)->type == VEH_TRAIN) {
- const Train *v = (Train *)::Vehicle::Get(vehicle_id);
+
+ const Train *v = ::Train::GetIfValid(vehicle_id);
+ if (v != NULL) {
while ((v = GetNextUnit(v)) != NULL) num++;
}
diff --git a/src/aircraft.h b/src/aircraft.h
index 24f4659f0..090add20d 100644
--- a/src/aircraft.h
+++ b/src/aircraft.h
@@ -96,7 +96,7 @@ struct AircraftCache {
*
* As side-effect the vehicle type is set correctly.
*/
-struct Aircraft : public Vehicle {
+struct Aircraft : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
AircraftCache acache; ///< Cache of often used calculated values
uint16 crashed_counter;
@@ -125,10 +125,10 @@ struct Aircraft : public Vehicle {
void OnNewDay();
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
- Aircraft *Next() { return (Aircraft *)this->Vehicle::Next(); }
- const Aircraft *Next() const { return (const Aircraft *)this->Vehicle::Next(); }
};
+#define FOR_ALL_AIRCRAFT(var) FOR_ALL_VEHICLES_OF_TYPE(Aircraft, var)
+
SpriteID GetRotorImage(const Aircraft *v);
Station *GetTargetAirportIfValid(const Aircraft *v);
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
index dc169ff5c..7bf6a79e0 100644
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -2073,10 +2073,9 @@ void UpdateAirplanesOnNewStation(const Station *st)
/* only 1 station is updated per function call, so it is enough to get entry_point once */
const AirportFTAClass *ap = st->Airport();
- Vehicle *u;
- FOR_ALL_VEHICLES(u) {
- if (u->type == VEH_AIRCRAFT && IsNormalAircraft(u)) {
- Aircraft *v = (Aircraft *)u;
+ Aircraft *v;
+ FOR_ALL_AIRCRAFT(v) {
+ if (IsNormalAircraft(v)) {
if (v->targetairport == st->index) { // if heading to this airport
/* update position of airplane. If plane is not flying, landing, or taking off
* you cannot delete airport, so it doesn't matter */
diff --git a/src/effectvehicle_base.h b/src/effectvehicle_base.h
index 1c4c3f339..2f2926a86 100644
--- a/src/effectvehicle_base.h
+++ b/src/effectvehicle_base.h
@@ -22,7 +22,7 @@
* - bulldozer (road works)
* - bubbles (industry)
*/
-struct EffectVehicle : public Vehicle {
+struct EffectVehicle : public SpecializedVehicle<EffectVehicle, VEH_EFFECT> {
uint16 animation_state;
byte animation_substate;
diff --git a/src/elrail.cpp b/src/elrail.cpp
index 68b4a0e1d..901f46dde 100644
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -532,8 +532,8 @@ void DrawCatenary(const TileInfo *ti)
bool SettingsDisableElrail(int32 p1)
{
- Vehicle *v;
Company *c;
+ Train *t;
bool disable = (p1 != 0);
/* we will now walk through all electric train engines and change their railtypes if it is the wrong one*/
@@ -554,10 +554,7 @@ bool SettingsDisableElrail(int32 p1)
/* when disabling elrails, make sure that all existing trains can run on
* normal rail too */
if (disable) {
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_TRAIN) continue;
-
- Train *t = (Train *)v;
+ FOR_ALL_TRAINS(t) {
if (t->railtype == RAILTYPE_ELECTRIC) {
/* this railroad vehicle is now compatible only with elrail,
* so add there also normal rail compatibility */
@@ -569,10 +566,9 @@ bool SettingsDisableElrail(int32 p1)
}
/* Fix the total power and acceleration for trains */
- FOR_ALL_VEHICLES(v) {
+ FOR_ALL_TRAINS(t) {
/* power and acceleration is cached only for front engines */
- if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
- Train *t = (Train *)v;
+ if (IsFrontEngine(t)) {
TrainPowerChanged(t);
UpdateTrainAcceleration(t);
}
diff --git a/src/roadveh.h b/src/roadveh.h
index 64218e62f..1e688e289 100644
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -123,7 +123,7 @@ struct RoadVehicleCache {
*
* As side-effect the vehicle type is set correctly.
*/
-struct RoadVehicle : public Vehicle {
+struct RoadVehicle : public SpecializedVehicle<RoadVehicle, VEH_ROAD> {
RoadVehicleCache rcache; ///< Cache of often used calculated values
byte state; ///< @see RoadVehicleStates
byte frame;
@@ -160,9 +160,8 @@ struct RoadVehicle : public Vehicle {
Trackdir GetVehicleTrackdir() const;
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
- RoadVehicle *First() { return (RoadVehicle *)this->Vehicle::First(); }
- RoadVehicle *Next() { return (RoadVehicle *)this->Vehicle::Next(); }
- const RoadVehicle *Next() const { return (const RoadVehicle *)this->Vehicle::Next(); }
};
+#define FOR_ALL_ROADVEHICLES(var) FOR_ALL_VEHICLES_OF_TYPE(RoadVehicle, var)
+
#endif /* ROADVEH_H */
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 6bbe7ef93..e78b69275 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -432,10 +432,8 @@ CommandCost CmdSendRoadVehToDepot(TileIndex tile, DoCommandFlag flags, uint32 p1
*/
CommandCost CmdTurnRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Vehicle *u = Vehicle::GetIfValid(p1);
- if (u == NULL || u->type != VEH_ROAD || !CheckOwnership(u->owner)) return CMD_ERROR;
-
- RoadVehicle *v = (RoadVehicle *)u;
+ RoadVehicle *v = RoadVehicle::GetIfValid(p1);
+ if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
if (v->vehstatus & VS_STOPPED ||
v->vehstatus & VS_CRASHED ||
@@ -2065,7 +2063,7 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
}
}
- if (flags & DC_EXEC) RoadVehUpdateCache((RoadVehicle *)Vehicle::Get(p1)->First());
+ if (flags & DC_EXEC) RoadVehUpdateCache(RoadVehicle::Get(p1)->First());
_returned_refit_capacity = total_capacity;
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index a298108aa..c4f9b9c81 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -921,16 +921,14 @@ bool AfterLoadGame()
/* Elrails got added in rev 24 */
if (CheckSavegameVersion(24)) {
- Vehicle *v;
RailType min_rail = RAILTYPE_ELECTRIC;
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_TRAIN) {
- RailType rt = RailVehInfo(v->engine_type)->railtype;
+ Train *v;
+ FOR_ALL_TRAINS(v) {
+ RailType rt = RailVehInfo(v->engine_type)->railtype;
- ((Train *)v)->railtype = rt;
- if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL;
- }
+ v->railtype = rt;
+ if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL;
}
/* .. so we convert the entire map from normal to elrail (so maintain "fairness") */
@@ -963,8 +961,8 @@ bool AfterLoadGame()
}
}
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true);
+ FOR_ALL_TRAINS(v) {
+ if (IsFrontEngine(v) || IsFreeWagon(v)) TrainConsistChanged(v, true);
}
}
@@ -1046,20 +1044,15 @@ bool AfterLoadGame()
}
if (CheckSavegameVersion(25)) {
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_ROAD) {
- RoadVehicle *rv = (RoadVehicle *)v;
- rv->vehstatus &= ~0x40;
- rv->slot = NULL;
- rv->slot_age = 0;
- }
+ RoadVehicle *rv;
+ FOR_ALL_ROADVEHICLES(rv) {
+ rv->vehstatus &= ~0x40;
+ rv->slot = NULL;
+ rv->slot_age = 0;
}
} else {
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_ROAD) continue;
- RoadVehicle *rv = (RoadVehicle *)v;
+ RoadVehicle *rv;
+ FOR_ALL_ROADVEHICLES(rv) {
if (rv->slot != NULL) rv->slot->num_vehicles++;
}
}
@@ -1382,10 +1375,8 @@ bool AfterLoadGame()
if (CheckSavegameVersion(69)) {
/* In some old savegames a bit was cleared when it should not be cleared */
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_ROAD) continue;
- RoadVehicle *rv = (RoadVehicle *)v;
+ RoadVehicle *rv;
+ FOR_ALL_ROADVEHICLES(rv) {
if (rv->state == 250 || rv->state == 251) {
SetBit(rv->state, RVS_IS_STOPPING);
}
@@ -1708,15 +1699,12 @@ bool AfterLoadGame()
/* Reserve all tracks trains are currently on. */
if (CheckSavegameVersion(101)) {
- Vehicle *u;
- FOR_ALL_VEHICLES(u) {
- if (u->type == VEH_TRAIN) {
- Train *v = (Train *)u;
- if ((v->track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
- TryReserveRailTrack(v->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(v->tile)));
- } else if ((v->track & TRACK_BIT_MASK) != TRACK_BIT_NONE) {
- TryReserveRailTrack(v->tile, TrackBitsToTrack(v->track));
- }
+ Train *t;
+ FOR_ALL_TRAINS(t) {
+ if ((t->track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
+ TryReserveRailTrack(t->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(t->tile)));
+ } else if ((t->track & TRACK_BIT_MASK) != TRACK_BIT_NONE) {
+ TryReserveRailTrack(t->tile, TrackBitsToTrack(t->track));
}
}
}
diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp
index 3170bb34a..65c1347d0 100644
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -20,16 +20,14 @@
*/
void ConnectMultiheadedTrains()
{
- Vehicle *v;
+ Train *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_TRAIN) {
- ((Train *)v)->other_multiheaded_part = NULL;
- }
+ FOR_ALL_TRAINS(v) {
+ v->other_multiheaded_part = NULL;
}
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
+ FOR_ALL_TRAINS(v) {
+ if (IsFrontEngine(v) || IsFreeWagon(v)) {
/* Two ways to associate multiheaded parts to each other:
* sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
* bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
@@ -45,7 +43,7 @@ void ConnectMultiheadedTrains()
bool sequential_matching = IsFrontEngine(v);
- for (Train *u = (Train *)v; u != NULL; u = (Train *)GetNextVehicle(u)) {
+ for (Train *u = v; u != NULL; u = GetNextVehicle(u)) {
if (u->other_multiheaded_part != NULL) continue; // we already linked this one
if (IsMultiheaded(u)) {
@@ -167,13 +165,11 @@ void UpdateOldAircraft()
st->airport_flags = 0; // reset airport
}
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
+ Aircraft *a;
+ FOR_ALL_AIRCRAFT(a) {
/* airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor)
* skip those */
- if (v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) {
- Aircraft *v_oldstyle = (Aircraft *)v;
- Aircraft *a = (Aircraft *)v_oldstyle;
+ if (IsNormalAircraft(a)) {
/* airplane in terminal stopped doesn't hurt anyone, so goto next */
if (a->vehstatus & VS_STOPPED && a->state == 0) {
a->state = HANGAR;
@@ -182,7 +178,7 @@ void UpdateOldAircraft()
AircraftLeaveHangar(a); // make airplane visible if it was in a depot for example
a->vehstatus &= ~VS_STOPPED; // make airplane moving
- a->cur_speed = v_oldstyle->max_speed; // so aircraft don't have zero speed while in air
+ a->cur_speed = a->max_speed; // so aircraft don't have zero speed while in air
if (!a->current_order.IsType(OT_GOTO_STATION) && !a->current_order.IsType(OT_GOTO_DEPOT)) {
/* reset current order so aircraft doesn't have invalid "station-only" order */
a->current_order.MakeDummy();
diff --git a/src/settings.cpp b/src/settings.cpp
index 37e64fb4f..fac9a0dfb 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -695,10 +695,10 @@ static bool DeleteSelectStationWindow(int32 p1)
static bool UpdateConsists(int32 p1)
{
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
+ Train *t;
+ FOR_ALL_TRAINS(t) {
/* Update the consist of all trains so the maximum speed is set correctly. */
- if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true);
+ if (IsFrontEngine(t) || IsFreeWagon(t)) TrainConsistChanged(t, true);
}
return true;
}
@@ -732,10 +732,9 @@ static bool CheckInterval(int32 p1)
static bool TrainAccelerationModelChanged(int32 p1)
{
- Vehicle *v;
-
- FOR_ALL_VEHICLES(v) {
- if (v->type == VEH_TRAIN && IsFrontEngine(v)) UpdateTrainAcceleration((Train *)v);
+ Train *t;
+ FOR_ALL_TRAINS(t) {
+ if (IsFrontEngine(t)) UpdateTrainAcceleration(t);
}
return true;
diff --git a/src/ship.h b/src/ship.h
index f6306a8d4..67f1a8748 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -22,7 +22,7 @@ void GetShipSpriteSize(EngineID engine, uint &width, uint &height);
*
* As side-effect the vehicle type is set correctly.
*/
-struct Ship: public Vehicle {
+struct Ship: public SpecializedVehicle<Ship, VEH_SHIP> {
TrackBitsByte state;
/** Initializes the Vehicle to a ship */
diff --git a/src/station.cpp b/src/station.cpp
index 57c9f150f..279bfbee8 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -69,11 +69,9 @@ Station::~Station()
loading_vehicles.front()->LeaveStation();
}
- Vehicle *v;
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_AIRCRAFT || !IsNormalAircraft(v)) continue;
-
- Aircraft *a = (Aircraft *)v;
+ Aircraft *a;
+ FOR_ALL_AIRCRAFT(a) {
+ if (!IsNormalAircraft(a)) continue;
if (a->targetairport == this->index) a->targetairport = INVALID_STATION;
}
@@ -463,12 +461,8 @@ RoadStop::~RoadStop()
/* Clear the slot assignment of all vehicles heading for this road stop */
if (num_vehicles != 0) {
- Vehicle *v;
-
- FOR_ALL_VEHICLES(v) {
- if (v->type != VEH_ROAD) continue;
- RoadVehicle *rv = (RoadVehicle *)v;
-
+ RoadVehicle *rv;
+ FOR_ALL_ROADVEHICLES(rv) {
if (rv->slot == this) ClearSlot(rv);
}
}
diff --git a/src/train.h b/src/train.h
index fb99e730e..a96ccb3f2 100644
--- a/src/train.h
+++ b/src/train.h
@@ -301,7 +301,7 @@ struct TrainCache {
*
* As side-effect the vehicle type is set correctly.
*/
-struct Train : public Vehicle {
+struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
TrainCache tcache;
/* Link between the two ends of a multiheaded engine */
@@ -338,14 +338,10 @@ struct Train : public Vehicle {
Trackdir GetVehicleTrackdir() const;
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
- Train *First() { return (Train *)this->Vehicle::First(); }
- Train *First() const { return (Train *)this->Vehicle::First(); }
- Train *Next() { return (Train *)this->Vehicle::Next(); }
- Train *Next() const { return (Train *)this->Vehicle::Next(); }
- Train *Previous() { return (Train *)this->Vehicle::Previous(); }
- Train *Previous() const { return (Train *)this->Vehicle::Previous(); }
};
+#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)
+
/**
* Get the next part of a multi-part engine.
* Will only work on a multi-part engine (EngineHasArticPart(v) == true),
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 568bf18bd..f8a3a923e 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -973,18 +973,17 @@ static Train *UnlinkWagon(Train *v, Train *first)
static Train *FindGoodVehiclePos(const Train *src)
{
- Vehicle *dst;
EngineID eng = src->engine_type;
TileIndex tile = src->tile;
- FOR_ALL_VEHICLES(dst) {
- if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile && !HASBITS(dst->vehstatus, VS_CRASHED)) {
+ Train *dst;
+ FOR_ALL_TRAINS(dst) {
+ if (IsFreeWagon(dst) && dst->tile == tile && !HASBITS(dst->vehstatus, VS_CRASHED)) {
/* check so all vehicles in the line have the same engine. */
- Vehicle *v = dst;
-
- while (v->engine_type == eng) {
- v = v->Next();
- if (v == NULL) return (Train *)dst;
+ Train *t = dst;
+ while (t->engine_type == eng) {
+ t = t->Next();
+ if (t == NULL) return dst;
}
}
}
@@ -1045,25 +1044,22 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
VehicleID s = GB(p1, 0, 16);
VehicleID d = GB(p1, 16, 16);
- Vehicle *src_v = Vehicle::GetIfValid(s);
- if (src_v == NULL || src_v->type != VEH_TRAIN || !CheckOwnership(src_v->owner)) return CMD_ERROR;
+ Train *src = Train::GetIfValid(s);
+ if (src == NULL || !CheckOwnership(src->owner)) return CMD_ERROR;
/* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
- if (HASBITS(src_v->vehstatus, VS_CRASHED)) return CMD_ERROR;
-
- Train *src = (Train *)src_v;
+ if (HASBITS(src->vehstatus, VS_CRASHED)) return CMD_ERROR;
/* if nothing is selected as destination, try and find a matching vehicle to drag to. */
Train *dst;
if (d == INVALID_VEHICLE) {
dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
} else {
- Vehicle *dst_v = Vehicle::GetIfValid(d);
- if (dst_v == NULL || dst_v->type != VEH_TRAIN || !CheckOwnership(dst_v->owner)) return CMD_ERROR;
+ dst = Train::GetIfValid(d);
+ if (dst == NULL || !CheckOwnership(dst->owner)) return CMD_ERROR;
/* Do not allow appending to crashed vehicles, too */
- if (HASBITS(dst_v->vehstatus, VS_CRASHED)) return CMD_ERROR;
- dst = (Train *)dst_v;
+ if (HASBITS(dst->vehstatus, VS_CRASHED)) return CMD_ERROR;
}
/* if an articulated part is being handled, deal with its parent vehicle */
@@ -1399,13 +1395,12 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
/* Check if we deleted a vehicle window */
Window *w = NULL;
- Vehicle *vt = Vehicle::GetIfValid(p1);
- if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
+ Train *v = Train::GetIfValid(p1);
+ if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
if (p2 > 1) return CMD_ERROR;
- if (HASBITS(vt->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
+ if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
- Train *v = (Train *)vt;
while (IsArticulatedPart(v)) v = v->Previous();
Train *first = v->First();
@@ -1955,10 +1950,8 @@ static void ReverseTrainDirection(Train *v)
*/
CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Vehicle *vt = Vehicle::GetIfValid(p1);
- if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
-
- Train *v = (Train *)vt;
+ Train *v = Train::GetIfValid(p1);
+ if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
if (p2 != 0) {
/* turn a single unit around */
@@ -2015,10 +2008,10 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32
*/
CommandCost CmdForceTrainProceed(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
- Vehicle *v = Vehicle::GetIfValid(p1);
- if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+ Train *t = Train::GetIfValid(p1);
+ if (t == NULL || !CheckOwnership(t->owner)) return CMD_ERROR;
- if (flags & DC_EXEC) ((Train *)v)->force_proceed = 0x50;
+ if (flags & DC_EXEC) t->force_proceed = 0x50;
return CommandCost();
}
@@ -2039,10 +2032,9 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
byte new_subtype = GB(p2, 8, 8);
bool only_this = HasBit(p2, 16);
- Vehicle *vt = Vehicle::GetIfValid(p1);
- if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
+ Train *v = Train::GetIfValid(p1);
+ if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR;
- Train *v = (Train *)vt;
if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE);
@@ -2116,7 +2108,7 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1,
_returned_refit_capacity = num;
/* Update the train's cached variables */
- if (flags & DC_EXEC) TrainConsistChanged((Train *)Vehicle::Get(p1)->First(), false);
+ if (flags & DC_EXEC) TrainConsistChanged(Train::Get(p1)->First(), false);
return cost;
}
diff --git a/src/vehicle_base.h b/src/vehicle_base.h
index 8883470ab..368835b66 100644
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -492,6 +492,64 @@ public:
};
/**
+ * Class defining several overloaded accessors so we don't
+ * have to cast vehicle types that often
+ */
+template <class T, VehicleType Type>
+struct SpecializedVehicle : public Vehicle {
+ static const VehicleType EXPECTED_TYPE = Type; ///< Specialized type
+
+ /**
+ * Get the first vehicle in the chain
+ * @return first vehicle in the chain
+ */
+ FORCEINLINE T *First() const { return (T *)this->Vehicle::First(); }
+
+ /**
+ * Get next vehicle in the chain
+ * @return next vehicle in the chain
+ */
+ FORCEINLINE T *Next() const { return (T *)this->Vehicle::Next(); }
+
+ /**
+ * Get previous vehicle in the chain
+ * @return previous vehicle in the chain
+ */
+ FORCEINLINE T *Previous() const { return (T *)this->Vehicle::Previous(); }
+
+
+ /**
+ * Tests whether given index is a valid index for vehicle of this type
+ * @param index tested index
+ * @return is this index valid index of T?
+ */
+ static FORCEINLINE bool IsValidID(size_t index)
+ {
+ return Vehicle::IsValidID(index) && Vehicle::Get(index)->type == Type;
+ }
+
+ /**
+ * Gets vehicle with given index
+ * @return pointer to vehicle with given index casted to T *
+ */
+ static FORCEINLINE T *Get(size_t index)
+ {
+ return (T *)Vehicle::Get(index);
+ }
+
+ /**
+ * Returns vehicle if the index is a valid index for this vehicle type
+ * @return pointer to vehicle with given index if it's a vehicle of this type
+ */
+ static FORCEINLINE T *GetIfValid(size_t index)
+ {
+ return IsValidID(index) ? Get(index) : NULL ;
+ }
+};
+
+#define FOR_ALL_VEHICLES_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, vehicle_index, var, 0) if (var->type == name::EXPECTED_TYPE)
+
+/**
* 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:
@@ -499,7 +557,7 @@ public:
*
* As side-effect the vehicle type is set correctly.
*/
-struct DisasterVehicle : public Vehicle {
+struct DisasterVehicle : public SpecializedVehicle<DisasterVehicle, VEH_DISASTER> {
uint16 image_override;
VehicleID big_ufo_destroyer_target;
@@ -512,7 +570,6 @@ struct DisasterVehicle : public Vehicle {
const char *GetTypeString() const { return "disaster vehicle"; }
void UpdateDeltaXY(Direction direction);
bool Tick();
- DisasterVehicle *Next() { return (DisasterVehicle*)this->Vehicle::Next(); }
};
#define FOR_ALL_VEHICLES_FROM(var, start) FOR_ALL_ITEMS_FROM(Vehicle, vehicle_index, var, start)