mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r23504) -Feature: Aircraft range.
This commit is contained in:
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…
Reference in New Issue