(svn r16441) -Codechange: new class SpecializedVehicle used as superclass for all vehicle types

This commit is contained in:
smatz 2009-05-26 22:10:13 +00:00
parent aa546e513f
commit 7ee882d03f
15 changed files with 150 additions and 135 deletions

View File

@ -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++;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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);
}

View File

@ -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 */

View File

@ -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;

View File

@ -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));
}
}
}

View File

@ -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();

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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),

View File

@ -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;
}

View File

@ -491,6 +491,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
@ -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)