1
0
Fork 0

Codechange: Go to hangar orders store the DepotID instead of the StationID.

pull/10691/head
J0anJosep 2023-08-25 11:39:01 +02:00
parent 620d14c502
commit 678b6ad467
13 changed files with 123 additions and 88 deletions

View File

@ -41,6 +41,7 @@
#include "framerate_type.h" #include "framerate_type.h"
#include "aircraft_cmd.h" #include "aircraft_cmd.h"
#include "vehicle_cmd.h" #include "vehicle_cmd.h"
#include "depot_base.h"
#include "table/strings.h" #include "table/strings.h"
@ -136,7 +137,7 @@ static StationID FindNearestHangar(const Aircraft *v)
if (v->current_order.IsType(OT_GOTO_STATION) || if (v->current_order.IsType(OT_GOTO_STATION) ||
(v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) { (v->current_order.IsType(OT_GOTO_DEPOT) && (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0)) {
last_dest = Station::GetIfValid(v->last_station_visited); last_dest = Station::GetIfValid(v->last_station_visited);
next_dest = Station::GetIfValid(v->current_order.GetDestination()); next_dest = Station::GetIfValid(GetTargetDestination(v->current_order, true));
} else { } else {
last_dest = GetTargetAirportIfValid(v); last_dest = GetTargetAirportIfValid(v);
next_dest = Station::GetIfValid(v->GetNextStoppingStation().value); next_dest = Station::GetIfValid(v->GetNextStoppingStation().value);
@ -407,9 +408,10 @@ ClosestDepot Aircraft::FindClosestDepot()
if (station == INVALID_STATION) return ClosestDepot(); if (station == INVALID_STATION) return ClosestDepot();
st = Station::Get(station); st = Station::Get(station);
assert(st->airport.hangar != nullptr);
} }
return ClosestDepot(st->xy, st->index); return ClosestDepot(st->xy, st->airport.hangar->index);
} }
static void CheckIfAircraftNeedsService(Aircraft *v) static void CheckIfAircraftNeedsService(Aircraft *v)
@ -424,13 +426,13 @@ static void CheckIfAircraftNeedsService(Aircraft *v)
* we don't want to consider going to a depot too. */ * we don't want to consider going to a depot too. */
if (!v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.IsType(OT_GOTO_STATION)) return; if (!v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.IsType(OT_GOTO_STATION)) return;
const Station *st = Station::Get(v->current_order.GetDestination()); const Station *st = Station::Get(GetTargetDestination(v->current_order, true));
assert(st != nullptr); assert(st != nullptr);
/* only goto depot if the target airport has a depot */ /* only goto depot if the target airport has a depot */
if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) { if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) {
v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE); v->current_order.MakeGoToDepot(st->airport.hangar->index, ODTFB_SERVICE);
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
} else if (v->current_order.IsType(OT_GOTO_DEPOT)) { } else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
v->current_order.MakeDummy(); v->current_order.MakeDummy();
@ -892,7 +894,7 @@ static bool AircraftController(Aircraft *v)
/* Jump into our "holding pattern" state machine if possible */ /* Jump into our "holding pattern" state machine if possible */
if (v->pos >= afc->nofelements) { if (v->pos >= afc->nofelements) {
v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N); v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N);
} else if (v->targetairport != v->current_order.GetDestination()) { } else if (v->targetairport != GetTargetDestination(v->current_order, true)) {
/* If not possible, just get out of here fast */ /* If not possible, just get out of here fast */
v->state = FLYING; v->state = FLYING;
UpdateAircraftCache(v); UpdateAircraftCache(v);
@ -1449,7 +1451,7 @@ static void AircraftLandAirplane(Aircraft *v)
void AircraftNextAirportPos_and_Order(Aircraft *v) void AircraftNextAirportPos_and_Order(Aircraft *v)
{ {
if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) { if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) {
v->targetairport = v->current_order.GetDestination(); v->targetairport = GetTargetDestination(v->current_order, true);
} }
const Station *st = GetTargetAirportIfValid(v); const Station *st = GetTargetAirportIfValid(v);
@ -1539,7 +1541,7 @@ static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *ap
return; return;
/* We are leaving a hangar, but have to go to the exact same one; re-enter */ /* We are leaving a hangar, but have to go to the exact same one; re-enter */
if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) { if (v->current_order.IsType(OT_GOTO_DEPOT) && GetTargetDestination(v->current_order, true) == v->targetairport) {
VehicleEnterDepot(v); VehicleEnterDepot(v);
return; return;
} }
@ -1548,7 +1550,7 @@ static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *ap
if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return; if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
/* We are already at the target airport, we need to find a terminal */ /* We are already at the target airport, we need to find a terminal */
if (v->current_order.GetDestination() == v->targetairport) { if (GetTargetDestination(v->current_order, true) == v->targetairport) {
/* FindFreeTerminal: /* FindFreeTerminal:
* 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */ * 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
if (v->subtype == AIR_HELICOPTER) { if (v->subtype == AIR_HELICOPTER) {
@ -1599,7 +1601,7 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *
case OT_GOTO_STATION: // ready to fly to another airport case OT_GOTO_STATION: // ready to fly to another airport
break; break;
case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc. case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
go_to_hangar = v->current_order.GetDestination() == v->targetairport; go_to_hangar = GetTargetDestination(v->current_order, true) == v->targetairport;
break; break;
case OT_CONDITIONAL: case OT_CONDITIONAL:
/* In case of a conditional order we just have to wait a tick /* In case of a conditional order we just have to wait a tick
@ -2103,7 +2105,7 @@ static bool AircraftEventHandler(Aircraft *v, int loop)
/* Check the distance to the next destination. This code works because the target /* 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. */ * airport is only updated after take off and not on the ground. */
Station *cur_st = Station::GetIfValid(v->targetairport); 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()) : nullptr; Station *next_st = Station::GetIfValid(GetTargetDestination(v->current_order, true));
if (cur_st != nullptr && cur_st->airport.tile != INVALID_TILE && next_st != nullptr && next_st->airport.tile != INVALID_TILE) { if (cur_st != nullptr && cur_st->airport.tile != INVALID_TILE && next_st != nullptr && next_st->airport.tile != INVALID_TILE) {
uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile); uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
@ -2169,18 +2171,7 @@ void UpdateAirplanesOnNewStation(const Station *st)
if (!v->IsNormalAircraft() || v->targetairport != st->index) continue; if (!v->IsNormalAircraft() || v->targetairport != st->index) continue;
assert(v->state == FLYING); assert(v->state == FLYING);
Order *o = &v->current_order;
/* The aircraft is heading to a hangar, but the new station doesn't have one,
* or the aircraft can't land on the new station. Cancel current order. */
if (o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && o->GetDestination() == st->index &&
(!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
o->MakeDummy();
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
}
v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation); v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation);
UpdateAircraftCache(v); UpdateAircraftCache(v);
} }
/* Heliports don't have a hangar. Invalidate all go to hangar orders from all aircraft. */
if (!st->airport.HasHangar()) RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, st->index, true);
} }

View File

@ -43,16 +43,21 @@ inline bool IsDepotTile(Tile tile)
return IsRailDepotTile(tile) || IsRoadDepotTile(tile) || IsShipDepotTile(tile) || IsHangarTile(tile); return IsRailDepotTile(tile) || IsRoadDepotTile(tile) || IsShipDepotTile(tile) || IsHangarTile(tile);
} }
extern DepotID GetHangarIndex(TileIndex t);
/** /**
* Get the index of which depot is attached to the tile. * Get the index of which depot is attached to the tile.
* @param t the tile * @param t the tile
* @pre IsRailDepotTile(t) || IsRoadDepotTile(t) || IsShipDepotTile(t) * @pre IsDepotTile(t)
* @return DepotID * @return DepotID
*/ */
inline DepotID GetDepotIndex(Tile t) inline DepotID GetDepotIndex(Tile t)
{ {
/* Hangars don't have a Depot class, thus store no DepotID. */ assert(IsDepotTile(t));
assert(IsRailDepotTile(t) || IsRoadDepotTile(t) || IsShipDepotTile(t));
/* Hangars don't store depot id on m2. */
if (IsTileType(t, MP_STATION)) return GetHangarIndex(t);
return t.m2(); return t.m2();
} }

View File

@ -246,18 +246,14 @@ CommandCost CmdClearOrderBackup(DoCommandFlag flags, TileIndex tile, ClientID us
* Removes an order from all vehicles. Triggers when, say, a station is removed. * Removes an order from all vehicles. Triggers when, say, a station is removed.
* @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]). * @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]).
* @param destination The destination. Can be a StationID, DepotID or WaypointID. * @param destination The destination. Can be a StationID, DepotID or WaypointID.
* @param hangar Only used for airports in the destination.
* When false, remove airport and hangar orders.
* When true, remove either airport or hangar order.
*/ */
/* static */ void OrderBackup::RemoveOrder(OrderType type, DestinationID destination, bool hangar) /* static */ void OrderBackup::RemoveOrder(OrderType type, DestinationID destination)
{ {
for (OrderBackup *ob : OrderBackup::Iterate()) { for (OrderBackup *ob : OrderBackup::Iterate()) {
for (Order *order = ob->orders; order != nullptr; order = order->next) { for (Order *order = ob->orders; order != nullptr; order = order->next) {
OrderType ot = order->GetType(); OrderType ot = order->GetType();
if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue; if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
if (ot == OT_GOTO_DEPOT && hangar && !IsHangarTile(ob->tile)) continue; // Not an aircraft? Can't have a hangar order. if (ot == OT_IMPLICIT) ot = OT_GOTO_STATION;
if (ot == OT_IMPLICIT || (IsHangarTile(ob->tile) && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
if (ot == type && order->GetDestination() == destination) { if (ot == type && order->GetDestination() == destination) {
/* Remove the order backup! If a station/depot gets removed, we can't/shouldn't restore those broken orders. */ /* Remove the order backup! If a station/depot gets removed, we can't/shouldn't restore those broken orders. */
delete ob; delete ob;

View File

@ -59,7 +59,7 @@ public:
static void ClearGroup(GroupID group); static void ClearGroup(GroupID group);
static void ClearVehicle(const Vehicle *v); static void ClearVehicle(const Vehicle *v);
static void RemoveOrder(OrderType type, DestinationID destination, bool hangar); static void RemoveOrder(OrderType type, DestinationID destination);
}; };
#endif /* ORDER_BACKUP_H */ #endif /* ORDER_BACKUP_H */

View File

@ -650,7 +650,7 @@ TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
case OT_GOTO_DEPOT: case OT_GOTO_DEPOT:
if (this->GetDestination() == INVALID_DEPOT) return INVALID_TILE; if (this->GetDestination() == INVALID_DEPOT) return INVALID_TILE;
return (v->type == VEH_AIRCRAFT) ? Station::Get(this->GetDestination())->xy : Depot::Get(this->GetDestination())->xy; return Depot::Get(this->GetDestination())->xy;
default: default:
return INVALID_TILE; return INVALID_TILE;
@ -684,6 +684,28 @@ uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int
return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile); return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile);
} }
/**
* Get the station or depot index associated to an order of a vehicle.
* For aircraft, it will return the index of the associated station, even for go to hangar orders.
* @param o Order to check.
* @param is_aircraft Whether the order is of an aircraft vehicle.
* @return index associated to a station or depot, or INVALID_STATION.
*/
DestinationID GetTargetDestination(const Order &o, bool is_aircraft)
{
DestinationID destination_id = o.GetDestination();
switch (o.GetType()) {
case OT_GOTO_STATION:
return destination_id;
case OT_GOTO_DEPOT:
assert(Depot::IsValidID(destination_id));
return is_aircraft ? GetStationIndex(Depot::Get(destination_id)->xy) : destination_id;
default:
return INVALID_STATION;
}
}
/** /**
* Add an order to the orderlist of a vehicle. * Add an order to the orderlist of a vehicle.
* @param flags operation to perform * @param flags operation to perform
@ -763,18 +785,6 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case OT_GOTO_DEPOT: { case OT_GOTO_DEPOT: {
if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) { if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) {
if (v->type == VEH_AIRCRAFT) {
const Station *st = Station::GetIfValid(new_order.GetDestination());
if (st == nullptr) return CMD_ERROR;
ret = CheckOwnership(st->owner);
if (ret.Failed()) return ret;
if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
return CMD_ERROR;
}
} else {
const Depot *dp = Depot::GetIfValid(new_order.GetDestination()); const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
if (dp == nullptr) return CMD_ERROR; if (dp == nullptr) return CMD_ERROR;
@ -795,10 +805,13 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (!IsShipDepotTile(dp->xy)) return CMD_ERROR; if (!IsShipDepotTile(dp->xy)) return CMD_ERROR;
break; break;
case VEH_AIRCRAFT:
if (!CanVehicleUseStation(v, Station::GetByTile(dp->xy)) || !IsHangarTile(dp->xy)) return CMD_ERROR;
break;
default: return CMD_ERROR; default: return CMD_ERROR;
} }
} }
}
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR; if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR; if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
@ -1780,24 +1793,11 @@ void CheckOrders(const Vehicle *v)
* Removes an order from all vehicles. Triggers when, say, a station is removed. * Removes an order from all vehicles. Triggers when, say, a station is removed.
* @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]). * @param type The type of the order (OT_GOTO_[STATION|DEPOT|WAYPOINT]).
* @param destination The destination. Can be a StationID, DepotID or WaypointID. * @param destination The destination. Can be a StationID, DepotID or WaypointID.
* @param hangar Only used for airports in the destination.
* When false, remove airport and hangar orders.
* When true, remove either airport or hangar order.
*/ */
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar) void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination)
{ {
/* Aircraft have StationIDs for depot orders and never use DepotIDs
* This fact is handled specially below
*/
/* Go through all vehicles */ /* Go through all vehicles */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::Iterate()) {
if ((v->type == VEH_AIRCRAFT && v->current_order.IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : v->current_order.GetType()) == type &&
(!hangar || v->type == VEH_AIRCRAFT) && v->current_order.GetDestination() == destination) {
v->current_order.MakeDummy();
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
}
/* Clear the order from the order-list */ /* Clear the order from the order-list */
int id = -1; int id = -1;
for (Order *order : v->Orders()) { for (Order *order : v->Orders()) {
@ -1806,8 +1806,7 @@ restart:
OrderType ot = order->GetType(); OrderType ot = order->GetType();
if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue; if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
if (ot == OT_GOTO_DEPOT && hangar && v->type != VEH_AIRCRAFT) continue; // Not an aircraft? Can't have a hangar order. if (ot == OT_IMPLICIT) ot = OT_GOTO_STATION;
if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
if (ot == type && order->GetDestination() == destination) { if (ot == type && order->GetDestination() == destination) {
/* We want to clear implicit orders, but we don't want to make them /* We want to clear implicit orders, but we don't want to make them
* dummy orders. They should just vanish. Also check the actual order * dummy orders. They should just vanish. Also check the actual order
@ -1841,7 +1840,7 @@ restart:
} }
} }
OrderBackup::RemoveOrder(type, destination, hangar); OrderBackup::RemoveOrder(type, destination);
} }
/** /**
@ -2054,7 +2053,8 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
v->SetDestTile(Depot::Get(order->GetDestination())->xy); v->SetDestTile(Depot::Get(order->GetDestination())->xy);
} else { } else {
Aircraft *a = Aircraft::From(v); Aircraft *a = Aircraft::From(v);
DestinationID destination = a->current_order.GetDestination(); DestinationID destination_depot = a->current_order.GetDestination();
StationID destination = GetStationIndex(Depot::Get(destination_depot)->xy);
if (a->targetairport != destination) { if (a->targetairport != destination) {
/* The aircraft is now heading for a different hangar than the next in the orders */ /* The aircraft is now heading for a different hangar than the next in the orders */
a->SetDestTile(a->GetOrderStationLocation(destination)); a->SetDestTile(a->GetOrderStationLocation(destination));

View File

@ -15,7 +15,7 @@
#include "company_type.h" #include "company_type.h"
/* Functions */ /* Functions */
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar = false); void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination);
void InvalidateVehicleOrder(const Vehicle *v, int data); void InvalidateVehicleOrder(const Vehicle *v, int data);
void CheckOrders(const Vehicle*); void CheckOrders(const Vehicle*);
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false, bool reset_order_indices = true); void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false, bool reset_order_indices = true);
@ -23,6 +23,7 @@ bool ProcessOrders(Vehicle *v);
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth = 0, bool pbs_look_ahead = false); bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth = 0, bool pbs_look_ahead = false);
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v); VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v);
uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth = 0); uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth = 0);
DestinationID GetTargetDestination(const Order &o, bool is_aircraft);
void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable, int left, int middle, int right); void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int y, bool selected, bool timetable, int left, int middle, int right);

View File

@ -34,6 +34,7 @@
#include "error.h" #include "error.h"
#include "order_cmd.h" #include "order_cmd.h"
#include "company_cmd.h" #include "company_cmd.h"
#include "depot_base.h"
#include "widgets/order_widget.h" #include "widgets/order_widget.h"
@ -309,7 +310,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
/* Going to a specific depot. */ /* Going to a specific depot. */
SetDParam(0, STR_ORDER_GO_TO_DEPOT_FORMAT); SetDParam(0, STR_ORDER_GO_TO_DEPOT_FORMAT);
SetDParam(2, v->type); SetDParam(2, v->type);
SetDParam(3, order->GetDestination()); SetDParam(3, GetTargetDestination(*order, v->type == VEH_AIRCRAFT));
} }
if (order->GetDepotOrderType() & ODTFB_SERVICE) { if (order->GetDepotOrderType() & ODTFB_SERVICE) {
@ -384,8 +385,7 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
/* check depot first */ /* check depot first */
if (IsDepotTypeTile(tile, (TransportType)(uint)v->type) && IsTileOwner(tile, _local_company)) { if (IsDepotTypeTile(tile, (TransportType)(uint)v->type) && IsTileOwner(tile, _local_company)) {
order.MakeGoToDepot(v->type == VEH_AIRCRAFT ? GetStationIndex(tile) : GetDepotIndex(tile), order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
ODTFB_PART_OF_ORDERS,
(_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
if (_ctrl_pressed) { if (_ctrl_pressed) {

View File

@ -2785,6 +2785,35 @@ bool AfterLoadGame()
} }
} }
if (IsSavegameVersionBefore(SLV_DEPOTID_IN_HANGAR_ORDERS)) {
/* Update go to hangar orders so they store the DepotID instead of StationID. */
for (Aircraft *a : Aircraft::Iterate()) {
if (!a->IsNormalAircraft()) continue;
/* Update current order. */
if (a->current_order.IsType(OT_GOTO_DEPOT)) {
Depot *dep = Station::Get(a->current_order.GetDestination())->airport.hangar;
if (dep == nullptr) {
/* Aircraft heading to a removed hangar. */
a->current_order.MakeDummy();
} else {
a->current_order.SetDestination(dep->index);
}
}
/* Update each aircraft order list once. */
if (a->orders == nullptr) continue;
if (a->orders->GetFirstSharedVehicle() != a) continue;
for (Order *order : a->Orders()) {
if (!order->IsType(OT_GOTO_DEPOT)) continue;
StationID station_id = order->GetDestination();
Station *st = Station::Get(station_id);
order->SetDestination(st->airport.hangar->index);
}
}
}
/* In old versions it was possible to remove an airport while a plane was /* In old versions it was possible to remove an airport while a plane was
* taking off or landing. This gives all kind of problems when building * taking off or landing. This gives all kind of problems when building
* another airport in the same station so we don't allow that anymore. * another airport in the same station so we don't allow that anymore.

View File

@ -385,6 +385,8 @@ enum SaveLoadVersion : uint16_t {
SLV_ROAD_WAYPOINTS, ///< 338 PR#12572 Road waypoints SLV_ROAD_WAYPOINTS, ///< 338 PR#12572 Road waypoints
SLV_ADD_DEPOTS_TO_HANGARS, ///< 339 PR#10691 Add depots to airports that have a hangar. SLV_ADD_DEPOTS_TO_HANGARS, ///< 339 PR#10691 Add depots to airports that have a hangar.
SLV_DEPOTID_IN_HANGAR_ORDERS, ///< 340 PR#10691 Go to hangar orders store the DepotID instead of StationID.
SL_MAX_VERSION, ///< Highest possible saveload version SL_MAX_VERSION, ///< Highest possible saveload version
}; };

View File

@ -245,18 +245,13 @@ static int ScriptOrderPositionToRealOrderPosition(VehicleID vehicle_id, ScriptOr
const Order *order = ::ResolveOrder(vehicle_id, order_position); const Order *order = ::ResolveOrder(vehicle_id, order_position);
if (order == nullptr || order->GetType() == OT_CONDITIONAL) return INVALID_TILE; if (order == nullptr || order->GetType() == OT_CONDITIONAL) return INVALID_TILE;
const Vehicle *v = ::Vehicle::Get(vehicle_id);
switch (order->GetType()) { switch (order->GetType()) {
case OT_GOTO_DEPOT: { case OT_GOTO_DEPOT: {
/* We don't know where the nearest depot is... (yet) */ /* We don't know where the nearest depot is... (yet) */
if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) return INVALID_TILE; if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) return INVALID_TILE;
if (v->type != VEH_AIRCRAFT) return ::Depot::Get(order->GetDestination())->xy; return ::Depot::Get(order->GetDestination())->xy;
/* Aircraft's hangars are referenced by StationID, not DepotID */
const Station *st = ::Station::Get(order->GetDestination());
if (!st->airport.HasHangar()) return INVALID_TILE;
return st->airport.GetHangarTile(0);
} }
case OT_GOTO_STATION: { case OT_GOTO_STATION: {

View File

@ -747,10 +747,25 @@ void Airport::AddHangar()
*/ */
void Airport::RemoveHangar() void Airport::RemoveHangar()
{ {
RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->hangar->index);
for (Aircraft *a : Aircraft::Iterate()) {
if (!a->IsNormalAircraft()) continue;
if (!a->current_order.IsType(OT_GOTO_DEPOT)) continue;
if (a->current_order.GetDestination() != this->hangar->index) continue;
a->current_order.MakeDummy();
}
delete this->hangar; delete this->hangar;
this->hangar = nullptr; this->hangar = nullptr;
} }
DepotID GetHangarIndex(TileIndex t) {
assert(IsAirportTile(t));
assert(Station::GetByTile(t)->airport.hangar != nullptr);
return Station::GetByTile(t)->airport.hangar->index;
}
bool StationCompare::operator() (const Station *lhs, const Station *rhs) const bool StationCompare::operator() (const Station *lhs, const Station *rhs) const
{ {
return lhs->index < rhs->index; return lhs->index < rhs->index;

View File

@ -1619,7 +1619,7 @@ void VehicleEnterDepot(Vehicle *v)
* Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */ * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
if ((v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && if ((v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) &&
real_order != nullptr && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) && real_order != nullptr && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
(v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) { v->current_order.GetDestination() != GetDepotIndex(v->tile)) {
/* We are heading for another depot, keep driving. */ /* We are heading for another depot, keep driving. */
return; return;
} }

View File

@ -45,6 +45,7 @@
#include "train_cmd.h" #include "train_cmd.h"
#include "hotkeys.h" #include "hotkeys.h"
#include "group_cmd.h" #include "group_cmd.h"
#include "depot_base.h"
#include "safeguards.h" #include "safeguards.h"
@ -3141,7 +3142,7 @@ public:
case OT_GOTO_DEPOT: { case OT_GOTO_DEPOT: {
SetDParam(0, v->type); SetDParam(0, v->type);
SetDParam(1, v->current_order.GetDestination()); SetDParam(1, GetTargetDestination(v->current_order, v->type == VEH_AIRCRAFT));
SetDParam(2, PackVelocity(v->GetDisplaySpeed(), v->type)); SetDParam(2, PackVelocity(v->GetDisplaySpeed(), v->type));
if (v->current_order.GetDestination() == INVALID_DEPOT) { if (v->current_order.GetDestination() == INVALID_DEPOT) {
/* This case *only* happens when multiple nearest depot orders /* This case *only* happens when multiple nearest depot orders