diff options
-rw-r--r-- | src/ai/api/ai_vehicle.cpp | 5 | ||||
-rw-r--r-- | src/aircraft.h | 6 | ||||
-rw-r--r-- | src/aircraft_cmd.cpp | 7 | ||||
-rw-r--r-- | src/effectvehicle_base.h | 2 | ||||
-rw-r--r-- | src/elrail.cpp | 12 | ||||
-rw-r--r-- | src/roadveh.h | 7 | ||||
-rw-r--r-- | src/roadveh_cmd.cpp | 8 | ||||
-rw-r--r-- | src/saveload/afterload.cpp | 56 | ||||
-rw-r--r-- | src/saveload/vehicle_sl.cpp | 24 | ||||
-rw-r--r-- | src/settings.cpp | 13 | ||||
-rw-r--r-- | src/ship.h | 2 | ||||
-rw-r--r-- | src/station.cpp | 16 | ||||
-rw-r--r-- | src/train.h | 10 | ||||
-rw-r--r-- | src/train_cmd.cpp | 56 | ||||
-rw-r--r-- | src/vehicle_base.h | 61 |
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) |