(svn r23504) -Feature: Aircraft range.

replace/41b28d7194a279bdc17475d4fbe2ea6ec885a466
michi_cc 13 years ago
parent 686f51d810
commit def8e7215b

@ -25,17 +25,28 @@ enum AircraftSubType {
AIR_ROTOR = 6 ///< rotor of an helicopter
};
/** Aircraft flags. */
enum VehicleAirFlags {
VAF_DEST_TOO_FAR = 0, ///< Next destination is too far away.
};
void HandleAircraftEnterHangar(Aircraft *v);
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, EngineImageType image_type);
void UpdateAirplanesOnNewStation(const Station *st);
void UpdateAircraftCache(Aircraft *v);
void UpdateAircraftCache(Aircraft *v, bool update_range = false);
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir);
void AircraftNextAirportPos_and_Order(Aircraft *v);
void SetAircraftPosition(Aircraft *v, int x, int y, int z);
int GetAircraftFlyingAltitude(const Aircraft *v);
/** Variables that are cached to improve performance and such. */
struct AircraftCache {
uint32 cached_max_range_sqr; ///< Cached squared maximum range.
uint16 cached_max_range; ///< Cached maximum range.
};
/**
* Aircraft, helicopters, rotors and their shadows belong to this class.
*/
@ -48,6 +59,9 @@ struct Aircraft : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
DirectionByte last_direction;
byte number_consecutive_turns; ///< Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
byte turn_counter; ///< Ticks between each turn to prevent > 45 degree turns.
byte flags; ///< Aircraft flags. @see VehicleAirFlags
AircraftCache acache;
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
Aircraft() : SpecializedVehicleBase() {}
@ -83,6 +97,15 @@ struct Aircraft : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
* return (this->subtype == AIR_HELICOPTER) || (this->subtype == AIR_AIRCRAFT); */
return this->subtype <= AIR_AIRCRAFT;
}
/**
* Get the range of this aircraft.
* @return Range in tiles or 0 if unlimited range.
*/
uint16 GetRange() const
{
return this->acache.cached_max_range;
}
};
/**

@ -311,7 +311,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
v->InvalidateNewGRFCacheOfChain();
UpdateAircraftCache(v);
UpdateAircraftCache(v, true);
VehicleMove(v, false);
VehicleMove(u, false);
@ -537,8 +537,9 @@ static void PlayAircraftSound(const Vehicle *v)
* Update cached values of an aircraft.
* Currently caches callback 36 max speed.
* @param v Vehicle
* @param update_range Update the aircraft range.
*/
void UpdateAircraftCache(Aircraft *v)
void UpdateAircraftCache(Aircraft *v, bool update_range)
{
uint max_speed = GetVehicleProperty(v, PROP_AIRCRAFT_SPEED, 0);
if (max_speed != 0) {
@ -555,6 +556,13 @@ void UpdateAircraftCache(Aircraft *v)
v->vcache.cached_cargo_age_period = GetVehicleProperty(v, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(v->engine_type)->cargo_age_period);
Aircraft *u = v->Next(); // Shadow for mail
u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
/* Update aircraft range. */
if (update_range) {
v->acache.cached_max_range = GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range);
/* Squared it now so we don't have to do it later all the time. */
v->acache.cached_max_range_sqr = v->acache.cached_max_range * v->acache.cached_max_range;
}
}
@ -1836,6 +1844,34 @@ static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc)
return FreeTerminal(v, MAX_TERMINALS, apc->num_helipads + MAX_TERMINALS);
}
/**
* Handle the 'dest too far' flag and the corresponding news message for aircraft.
* @param v The aircraft.
* @param too_far True if the current destination is too far away.
*/
static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
{
if (too_far) {
if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) {
SetBit(v->flags, VAF_DEST_TOO_FAR);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
if (v->owner == _local_company) {
/* Post a news message. */
SetDParam(0, v->index);
AddVehicleNewsItem(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, NS_ADVICE, v->index);
}
}
return;
}
if (HasBit(v->flags, VAF_DEST_TOO_FAR)) {
/* Not too far anymore, clear flag and message. */
ClrBit(v->flags, VAF_DEST_TOO_FAR);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
DeleteVehicleNews(v->index, STR_NEWS_AIRCRAFT_DEST_TOO_FAR);
}
}
static bool AircraftEventHandler(Aircraft *v, int loop)
{
v->tick_counter++;
@ -1854,7 +1890,22 @@ static bool AircraftEventHandler(Aircraft *v, int loop)
if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return true;
AirportGoToNextPosition(v);
if (v->state == FLYING) {
/* If we are flying, unconditionally clear the 'dest too far' state. */
AircraftHandleDestTooFar(v, false);
} else if (v->acache.cached_max_range_sqr != 0) {
/* Check the distance to the next destination. This code works because the target
* airport is only updated after take off and not on the ground. */
Station *cur_st = Station::GetIfValid(v->targetairport);
Station *next_st = v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT) ? Station::GetIfValid(v->current_order.GetDestination()) : NULL;
if (cur_st != NULL && cur_st->airport.tile != INVALID_TILE && next_st != NULL && next_st->airport.tile != INVALID_TILE) {
uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
AircraftHandleDestTooFar(v, dist > v->acache.cached_max_range_sqr);
}
}
if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) AirportGoToNextPosition(v);
return true;
}

@ -739,6 +739,13 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
DrawString(left, right, y, STR_PURCHASE_INFO_RUNNINGCOST);
y += FONT_HEIGHT_NORMAL;
uint16 range = e->GetRange();
if (range != 0) {
SetDParam(0, range);
DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_RANGE);
y += FONT_HEIGHT_NORMAL;
}
return y;
}

@ -448,6 +448,20 @@ Date Engine::GetLifeLengthInDays() const
return (this->info.lifelength + _settings_game.vehicle.extend_vehicle_life) * DAYS_IN_LEAP_YEAR;
}
/**
* Get the range of an aircraft type.
* @return Range of the aircraft type in tiles or 0 if unlimited range.
*/
uint16 Engine::GetRange() const
{
switch (this->type) {
case VEH_AIRCRAFT:
return GetEngineProperty(this->index, PROP_AIRCRAFT_RANGE, this->u.air.max_range);
default: NOT_REACHED();
}
}
/**
* Initializes the EngineOverrideManager with the default engines.
*/

@ -110,6 +110,7 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
uint GetDisplayWeight() const;
uint GetDisplayMaxTractiveEffort() const;
Date GetLifeLengthInDays() const;
uint16 GetRange() const;
/**
* Check if the engine is a ground vehicle.

@ -170,20 +170,22 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
CargoID cargo = e->GetDefaultCargoType();
uint16 mail_capacity;
uint capacity = e->GetDisplayDefaultCapacity(&mail_capacity);
uint16 range = e->GetRange();
SetDParam(0, e->GetCost());
SetDParam(1, e->GetDisplayMaxSpeed());
SetDParam(2, cargo);
SetDParam(3, capacity);
SetDParam(7, range);
if (mail_capacity > 0) {
SetDParam(4, CT_MAIL);
SetDParam(5, mail_capacity);
SetDParam(6, e->GetRunningCost());
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST;
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST;
} else {
SetDParam(4, e->GetRunningCost());
return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
}
}

@ -105,6 +105,7 @@ struct AircraftVehicleInfo {
uint16 max_speed; ///< Maximum speed (1 unit = 8 mph = 12.8 km-ish/h)
byte mail_capacity; ///< Mail capacity (bags).
uint16 passenger_capacity; ///< Passenger capacity (persons).
uint16 max_range; ///< Maximum range of this aircraft.
};
/** Information about a road vehicle. */

@ -822,6 +822,7 @@ STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND :{WHITE}{VEHICLE
STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE} can't find a path to continue
STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} is lost
STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}{VEHICLE}'s profit last year was {CURRENCY_LONG}
STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} can't get to the next destination because it is out of range
STR_NEWS_ORDER_REFIT_FAILED :{WHITE}{VEHICLE} stopped because an ordered refit failed
STR_NEWS_VEHICLE_AUTORENEW_FAILED :{WHITE}Autorenew failed on {VEHICLE}{}{STRING}
@ -2927,6 +2928,7 @@ STR_PURCHASE_INFO_REFITTABLE_TO :{BLACK}Refittab
STR_PURCHASE_INFO_ALL_TYPES :All cargo types
STR_PURCHASE_INFO_ALL_BUT :All but {GOLD}
STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Tractive Effort: {GOLD}{FORCE}
STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Range: {GOLD}{COMMA} tiles
STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Train vehicle selection list - click on vehicle for information
STR_BUY_VEHICLE_ROAD_VEHICLE_LIST_TOOLTIP :{BLACK}Road vehicle selection list - click on vehicle for information
@ -3047,6 +3049,8 @@ STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {C
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {CURRENCY_LONG} Weight: {WEIGHT_SHORT}{}Speed: {VELOCITY} Power: {POWER} Max. T.E.: {6:FORCE}{}Running Cost: {4:CURRENCY_LONG}/yr{}Capacity: {5:CARGO_LONG}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_CAPACITY_RUNCOST:{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY} Range: {7:COMMA} tiles{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY} Range: {7:COMMA} tiles{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
# Autoreplace window
STR_REPLACE_VEHICLES_WHITE :{WHITE}Replace {STRING}
@ -3132,6 +3136,7 @@ STR_VEHICLE_STATUS_STOPPED :{RED}Stopped
STR_VEHICLE_STATUS_TRAIN_STOPPING_VEL :{RED}Stopping, {VELOCITY}
STR_VEHICLE_STATUS_TRAIN_NO_POWER :{RED}No power
STR_VEHICLE_STATUS_TRAIN_STUCK :{ORANGE}Waiting for free path
STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR :{ORANGE}Too far to next destination
STR_VEHICLE_STATUS_HEADING_FOR_STATION_VEL :{LTBLUE}Heading for {STATION}, {VELOCITY}
STR_VEHICLE_STATUS_NO_ORDERS_VEL :{LTBLUE}No orders, {VELOCITY}
@ -3160,6 +3165,7 @@ STR_VEHICLE_INFO_AGE :{COMMA} year{P
STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} year{P "" s} ({COMMA})
STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_MAX_SPEED_RANGE :{BLACK}Max. speed: {LTBLUE}{VELOCITY} {BLACK}Range: {LTBLUE}{COMMA} tiles
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE}
@ -3883,6 +3889,7 @@ STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Can't sh
STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Can't stop sharing order list...
STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Can't copy order list...
STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... too far from previous destination
STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... aircraft has not enough range
# Timetable related errors
STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Can't timetable vehicle...

@ -1646,6 +1646,10 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int
break;
}
case PROP_AIRCRAFT_RANGE: // 0x1F Max aircraft range
avi->max_range = buf->ReadWord();
break;
default:
ret = CommonVehicleChangeInfo(ei, prop, buf);
break;

@ -53,6 +53,7 @@ enum PropertyID {
PROP_AIRCRAFT_PASSENGER_CAPACITY = 0x0F, ///< Passenger Capacity
PROP_AIRCRAFT_MAIL_CAPACITY = 0x11, ///< Mail Capacity
PROP_AIRCRAFT_CARGO_AGE_PERIOD = 0x1C, ///< Number of ticks before carried cargo is aged
PROP_AIRCRAFT_RANGE = 0x1F, ///< Aircraft range
};
#endif /* NEWGRF_PROPERTIES_H */

@ -166,7 +166,7 @@ public:
inline void SetConditionValue(uint16 value) { SB(this->dest, 0, 11, value); }
bool ShouldStopAtStation(const Vehicle *v, StationID station) const;
TileIndex GetLocation(const Vehicle *v) const;
TileIndex GetLocation(const Vehicle *v, bool airport = false) const;
/** Checks if this order has travel_time and if needed wait_time set. */
inline bool IsCompletelyTimetabled() const

@ -559,14 +559,16 @@ static void DeleteOrderWarnings(const Vehicle *v)
/**
* Returns a tile somewhat representing the order destination (not suitable for pathfinding).
* @param v The vehicle to get the location for.
* @param airport Get the airport tile and not the station location for aircraft.
* @return destination of order, or INVALID_TILE if none.
*/
TileIndex Order::GetLocation(const Vehicle *v) const
TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
{
switch (this->GetType()) {
case OT_GOTO_WAYPOINT:
case OT_GOTO_STATION:
case OT_IMPLICIT:
if (airport && v->type == VEH_AIRCRAFT) return Station::Get(this->GetDestination())->airport.tile;
return BaseStation::Get(this->GetDestination())->xy;
case OT_GOTO_DEPOT:
@ -580,8 +582,6 @@ TileIndex Order::GetLocation(const Vehicle *v) const
static uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth = 0)
{
assert(v->type == VEH_SHIP);
if (cur->IsType(OT_CONDITIONAL)) {
if (conditional_depth > v->GetNumOrders()) return 0;
@ -592,10 +592,10 @@ static uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle
return max(dist1, dist2);
}
TileIndex prev_tile = prev->GetLocation(v);
TileIndex cur_tile = cur->GetLocation(v);
TileIndex prev_tile = prev->GetLocation(v, true);
TileIndex cur_tile = cur->GetLocation(v, true);
if (prev_tile == INVALID_TILE || cur_tile == INVALID_TILE) return 0;
return DistanceManhattan(prev_tile, cur_tile);
return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile);
}
/**
@ -1384,6 +1384,34 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
return CommandCost();
}
/**
* Check if an aircraft has enough range for an order list.
* @param v Aircraft to check.
* @param first First order in the source order list.
* @return True if the aircraft has enough range for the orders, false otherwise.
*/
bool CheckAircraftOrderDistance(const Aircraft *v, const Order *first)
{
if (first == NULL) return true;
/* Iterate over all orders to check the distance between all
* 'goto' orders and their respective next order (of any type). */
for (const Order *o = first; o != NULL; o = o->next) {
switch (o->GetType()) {
case OT_GOTO_STATION:
case OT_GOTO_DEPOT:
case OT_GOTO_WAYPOINT:
/* If we don't have a next order, we've reached the end and must check the first order instead. */
if (GetOrderDistance(o, o->next != NULL ? o->next : first, v) > v->acache.cached_max_range_sqr) return false;
break;
default: break;
}
}
return true;
}
/**
* Clone/share/copy an order-list of another vehicle.
* @param tile unused
@ -1433,6 +1461,11 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
}
}
/* Check for aircraft range limits. */
if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src->GetFirstOrder())) {
return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
}
if (src->orders.list == NULL && !OrderList::CanAllocateItem()) {
return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
}
@ -1475,6 +1508,11 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
}
}
/* Check for aircraft range limits. */
if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src->GetFirstOrder())) {
return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
}
/* make sure there are orders available */
int delta = dst->IsOrderListShared() ? src->GetNumOrders() + 1 : src->GetNumOrders() - dst->GetNumOrders();
if (!Order::CanAllocateItem(delta) ||

@ -231,8 +231,9 @@
* 164 23290
* 165 23304
* 166 23415
* 167 23504
*/
extern const uint16 SAVEGAME_VERSION = 166; ///< Current savegame version of OpenTTD.
extern const uint16 SAVEGAME_VERSION = 167; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading

@ -434,7 +434,7 @@ void AfterLoadVehicles(bool part_of_load)
rotor->cur_image = GetRotorImage(Aircraft::From(v), EIT_ON_MAP);
}
UpdateAircraftCache(Aircraft::From(v));
UpdateAircraftCache(Aircraft::From(v), true);
}
break;
default: break;
@ -745,6 +745,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_CONDVAR(Aircraft, number_consecutive_turns, SLE_UINT8, 2, SL_MAX_VERSION),
SLE_CONDVAR(Aircraft, turn_counter, SLE_UINT8, 136, SL_MAX_VERSION),
SLE_CONDVAR(Aircraft, flags, SLE_UINT8, 167, SL_MAX_VERSION),
SLE_CONDNULL(13, 2, 143), // old reserved space

@ -585,7 +585,7 @@ static const ShipVehicleInfo _orig_ship_vehicle_info[] = {
* @param h mail_capacity (bags)
* @param i passenger_capacity (persons)
*/
#define AVI(a, b, c, d, e, f, g, h, i) { a, b, c, d, e, f, (g * 128) / 10, h, i }
#define AVI(a, b, c, d, e, f, g, h, i) { a, b, c, d, e, f, (g * 128) / 10, h, i, 0 }
#define H AIR_HELI
#define P AIR_CTOL
#define J AIR_CTOL | AIR_FAST

@ -433,7 +433,7 @@ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
case VEH_AIRCRAFT:
v->InvalidateNewGRFCacheOfChain();
v->colourmap = PAL_NONE; // invalidate vehicle colour map
UpdateAircraftCache(Aircraft::From(v));
UpdateAircraftCache(Aircraft::From(v), true);
break;
default: NOT_REACHED();

@ -1996,7 +1996,12 @@ struct VehicleDetailsWindow : Window {
}
} else {
SetDParam(0, v->GetDisplayMaxSpeed());
string = STR_VEHICLE_INFO_MAX_SPEED;
if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->GetRange() > 0) {
SetDParam(1, Aircraft::From(v)->GetRange());
string = STR_VEHICLE_INFO_MAX_SPEED_RANGE;
} else {
string = STR_VEHICLE_INFO_MAX_SPEED;
}
}
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, string);
y += FONT_HEIGHT_NORMAL;
@ -2477,6 +2482,8 @@ public:
}
} else if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_TRAIN_STUCK) && !v->current_order.IsType(OT_LOADING)) {
str = STR_VEHICLE_STATUS_TRAIN_STUCK;
} else if (v->type == VEH_AIRCRAFT && HasBit(Aircraft::From(v)->flags, VAF_DEST_TOO_FAR) && !v->current_order.IsType(OT_LOADING)) {
str = STR_VEHICLE_STATUS_AIRCRAFT_TOO_FAR;
} else { // vehicle is in a "normal" state, show current order
switch (v->current_order.GetType()) {
case OT_GOTO_STATION: {

Loading…
Cancel
Save