Update to 14.0-beta1

This commit is contained in:
dP
2024-02-04 02:18:17 +05:30
parent 79037e2c65
commit 33ef333b57
1325 changed files with 138465 additions and 70987 deletions

View File

@@ -195,7 +195,7 @@ bool Order::Equals(const Order &other) const
* @return the packed representation.
* @note unpacking is done in the constructor.
*/
uint32 Order::Pack() const
uint32_t Order::Pack() const
{
return this->dest << 16 | this->flags << 8 | this->type;
}
@@ -205,9 +205,9 @@ uint32 Order::Pack() const
* representation as possible.
* @return the TTD-like packed representation.
*/
uint16 Order::MapOldOrder() const
uint16_t Order::MapOldOrder() const
{
uint16 order = this->GetType();
uint16_t order = this->GetType();
switch (this->type) {
case OT_GOTO_STATION:
if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
@@ -231,13 +231,13 @@ uint16 Order::MapOldOrder() const
* Create an order based on a packed representation of that order.
* @param packed the packed representation.
*/
Order::Order(uint32 packed)
Order::Order(uint32_t packed)
{
this->type = (OrderType)GB(packed, 0, 8);
this->flags = GB(packed, 8, 8);
this->dest = GB(packed, 16, 16);
this->next = nullptr;
this->refit_cargo = CT_NO_REFIT;
this->refit_cargo = CARGO_NO_REFIT;
this->wait_time = 0;
this->travel_time = 0;
this->max_speed = UINT16_MAX;
@@ -571,31 +571,6 @@ void OrderList::RemoveVehicle(Vehicle *v)
if (v == this->first_shared) this->first_shared = v->NextShared();
}
/**
* Checks whether a vehicle is part of the shared vehicle chain.
* @param v is the vehicle to search in the shared vehicle chain.
*/
bool OrderList::IsVehicleInSharedOrdersList(const Vehicle *v) const
{
for (const Vehicle *v_shared = this->first_shared; v_shared != nullptr; v_shared = v_shared->NextShared()) {
if (v_shared == v) return true;
}
return false;
}
/**
* Gets the position of the given vehicle within the shared order vehicle list.
* @param v is the vehicle of which to get the position
* @return position of v within the shared vehicle chain.
*/
int OrderList::GetPositionInSharedOrderList(const Vehicle *v) const
{
int count = 0;
for (const Vehicle *v_shared = v->PreviousShared(); v_shared != nullptr; v_shared = v_shared->PreviousShared()) count++;
return count;
}
/**
* Checks whether all orders of the list have a filled timetable.
* @return whether all orders have a filled timetable.
@@ -619,8 +594,8 @@ void OrderList::DebugCheckSanity() const
VehicleOrderID check_num_orders = 0;
VehicleOrderID check_num_manual_orders = 0;
uint check_num_vehicles = 0;
Ticks check_timetable_duration = 0;
Ticks check_total_duration = 0;
TimerGameTick::Ticks check_timetable_duration = 0;
TimerGameTick::Ticks check_total_duration = 0;
Debug(misc, 6, "Checking OrderList {} for sanity...", this->index);
@@ -744,7 +719,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (ret.Failed()) return ret;
/* Validate properties we don't want to have different from default as they are set by other commands. */
if (new_order.GetRefitCargo() != CT_NO_REFIT || new_order.GetWaitTime() != 0 || new_order.GetTravelTime() != 0 || new_order.GetMaxSpeed() != UINT16_MAX) return CMD_ERROR;
if (new_order.GetRefitCargo() != CARGO_NO_REFIT || new_order.GetWaitTime() != 0 || new_order.GetTravelTime() != 0 || new_order.GetMaxSpeed() != UINT16_MAX) return CMD_ERROR;
/* Check if the inserted order is to the correct destination (owner, type),
* and has the correct flags if any */
@@ -754,13 +729,13 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (st == nullptr) return CMD_ERROR;
if (st->owner != OWNER_NONE) {
CommandCost ret = CheckOwnership(st->owner);
ret = CheckOwnership(st->owner);
if (ret.Failed()) return ret;
}
if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
if (!CanVehicleUseStation(v, st)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, GetVehicleCannotUseStationReason(v, st));
for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED);
if (!CanVehicleUseStation(u, st)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER_SHARED, GetVehicleCannotUseStationReason(u, st));
}
/* Non stop only allowed for ground vehicles. */
@@ -768,8 +743,17 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
/* Filter invalid load/unload types. */
switch (new_order.GetLoadType()) {
case OLF_LOAD_IF_POSSIBLE: case OLFB_FULL_LOAD: case OLF_FULL_LOAD_ANY: case OLFB_NO_LOAD: break;
default: return CMD_ERROR;
case OLF_LOAD_IF_POSSIBLE:
case OLFB_NO_LOAD:
break;
case OLFB_FULL_LOAD:
case OLF_FULL_LOAD_ANY:
if (v->HasUnbunchingOrder()) return_cmd_error(STR_ERROR_UNBUNCHING_NO_FULL_LOAD);
break;
default:
return CMD_ERROR;
}
switch (new_order.GetUnloadType()) {
case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break;
@@ -781,7 +765,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case OSL_PLATFORM_NEAR_END:
case OSL_PLATFORM_MIDDLE:
if (v->type != VEH_TRAIN) return CMD_ERROR;
FALLTHROUGH;
[[fallthrough]];
case OSL_PLATFORM_FAR_END:
break;
@@ -800,7 +784,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (st == nullptr) return CMD_ERROR;
CommandCost ret = CheckOwnership(st->owner);
ret = CheckOwnership(st->owner);
if (ret.Failed()) return ret;
if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
@@ -811,7 +795,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (dp == nullptr) return CMD_ERROR;
CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
ret = CheckOwnership(GetTileOwner(dp->xy));
if (ret.Failed()) return ret;
switch (v->type) {
@@ -847,17 +831,17 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
default: return CMD_ERROR;
case VEH_TRAIN: {
if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
if (!(wp->facilities & FACIL_TRAIN)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_NO_RAIL_WAYPOINT);
CommandCost ret = CheckOwnership(wp->owner);
ret = CheckOwnership(wp->owner);
if (ret.Failed()) return ret;
break;
}
case VEH_SHIP:
if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
if (!(wp->facilities & FACIL_DOCK)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_NO_BUOY);
if (wp->owner != OWNER_NONE) {
CommandCost ret = CheckOwnership(wp->owner);
ret = CheckOwnership(wp->owner);
if (ret.Failed()) return ret;
}
break;
@@ -874,6 +858,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
if (skip_to != 0 && skip_to >= v->GetNumOrders()) return CMD_ERROR; // Always allow jumping to the first (even when there is no order).
if (new_order.GetConditionVariable() >= OCV_END) return CMD_ERROR;
if (v->HasUnbunchingOrder()) return_cmd_error(STR_ERROR_UNBUNCHING_NO_CONDITIONAL);
OrderConditionComparator occ = new_order.GetConditionComparator();
if (occ >= OCC_END) return CMD_ERROR;
@@ -890,7 +875,7 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case OCV_LOAD_PERCENTAGE:
case OCV_RELIABILITY:
if (new_order.GetConditionValue() > 100) return CMD_ERROR;
FALLTHROUGH;
[[fallthrough]];
default:
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
@@ -952,7 +937,7 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
/* We are inserting an order just before the current implicit order.
* We do not know whether we will reach current implicit or the newly inserted order first.
* So, disable creation of implicit orders until we are on track again. */
uint16 &gv_flags = u->GetGroundVehicleFlags();
uint16_t &gv_flags = u->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
}
if (sel_ord <= u->cur_implicit_order_index) {
@@ -962,6 +947,9 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
u->cur_implicit_order_index = cur;
}
}
/* Unbunching data is no longer valid. */
u->ResetDepotUnbunching();
/* Update any possible open window of the vehicle */
InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
}
@@ -1076,6 +1064,8 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
if (u->cur_implicit_order_index >= u->GetNumOrders()) u->cur_implicit_order_index = 0;
}
}
/* Unbunching data is no longer valid. */
u->ResetDepotUnbunching();
/* Update any possible open window of the vehicle */
InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
@@ -1122,6 +1112,9 @@ CommandCost CmdSkipToOrder(DoCommandFlag flags, VehicleID veh_id, VehicleOrderID
v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
v->UpdateRealOrderIndex();
/* Unbunching data is no longer valid. */
v->ResetDepotUnbunching();
InvalidateVehicleOrder(v, VIWD_MODIFY_ORDERS);
/* We have an aircraft/ship, they have a mini-schedule, so update them all */
@@ -1198,6 +1191,9 @@ CommandCost CmdMoveOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID movi
} else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
u->cur_implicit_order_index++;
}
/* Unbunching data is no longer valid. */
u->ResetDepotUnbunching();
assert(v->orders == u->orders);
/* Update any possible open window of the vehicle */
@@ -1237,7 +1233,7 @@ CommandCost CmdMoveOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID movi
* @param data the data to modify
* @return the cost of this operation or an error
*/
CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID sel_ord, ModifyOrderFlags mof, uint16 data)
CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID sel_ord, ModifyOrderFlags mof, uint16_t data)
{
if (mof >= MOF_END) return CMD_ERROR;
@@ -1251,6 +1247,7 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (sel_ord >= v->GetNumOrders()) return CMD_ERROR;
Order *order = v->GetOrder(sel_ord);
assert(order != nullptr);
switch (order->GetType()) {
case OT_GOTO_STATION:
if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD) return CMD_ERROR;
@@ -1298,10 +1295,27 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return CMD_ERROR;
if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
if (data == order->GetLoadType()) return CMD_ERROR;
if ((data & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) && v->HasUnbunchingOrder()) return_cmd_error(STR_ERROR_UNBUNCHING_NO_FULL_LOAD);
break;
case MOF_DEPOT_ACTION:
if (data >= DA_END) return CMD_ERROR;
/* The vehicle must always go to the depot (not just if it needs servicing) in order to unbunch there. */
if ((data == DA_SERVICE) && (order->GetDepotActionType() & ODATFB_UNBUNCH)) return_cmd_error(STR_ERROR_UNBUNCHING_NO_SERVICE_IF_NEEDED);
/* Check if we are allowed to add unbunching. We are always allowed to remove it. */
if (data == DA_UNBUNCH) {
/* Only one unbunching order is allowed in a vehicle's orders. If this order already has an unbunching action, no error is needed. */
if (v->HasUnbunchingOrder() && !(order->GetDepotActionType() & ODATFB_UNBUNCH)) return_cmd_error(STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED);
for (Order *o : v->Orders()) {
/* We don't allow unbunching if the vehicle has a conditional order. */
if (o->IsType(OT_CONDITIONAL)) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL);
/* We don't allow unbunching if the vehicle has a full load order. */
if (o->IsType(OT_GOTO_STATION) && o->GetLoadType() & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD);
/* The vehicle must always go to the depot (not just if it needs servicing) in order to unbunch there. */
if (o->IsType(OT_GOTO_DEPOT) && o->GetDepotOrderType() & ODTFB_SERVICE) return_cmd_error(STR_ERROR_UNBUNCHING_NO_SERVICE_IF_NEEDED);
}
}
break;
case MOF_COND_VARIABLE:
@@ -1350,7 +1364,7 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case MOF_NON_STOP:
order->SetNonStopType((OrderNonStopFlags)data);
if (data & ONSF_NO_STOP_AT_DESTINATION_STATION) {
order->SetRefit(CT_NO_REFIT);
order->SetRefit(CARGO_NO_REFIT);
order->SetLoadType(OLF_LOAD_IF_POSSIBLE);
order->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
}
@@ -1366,7 +1380,7 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case MOF_LOAD:
order->SetLoadType((OrderLoadFlags)data);
if (data & OLFB_NO_LOAD) order->SetRefit(CT_NO_REFIT);
if (data & OLFB_NO_LOAD) order->SetRefit(CARGO_NO_REFIT);
break;
case MOF_DEPOT_ACTION: {
@@ -1374,18 +1388,26 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case DA_ALWAYS_GO:
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_UNBUNCH));
break;
case DA_SERVICE:
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() | ODTFB_SERVICE));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
order->SetRefit(CT_NO_REFIT);
order->SetRefit(CARGO_NO_REFIT);
break;
case DA_STOP:
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_UNBUNCH));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() | ODATFB_HALT));
order->SetRefit(CT_NO_REFIT);
order->SetRefit(CARGO_NO_REFIT);
break;
case DA_UNBUNCH:
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() | ODATFB_UNBUNCH));
break;
default:
@@ -1412,7 +1434,7 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
case OCV_LOAD_PERCENTAGE:
case OCV_RELIABILITY:
if (order->GetConditionValue() > 100) order->SetConditionValue(100);
FALLTHROUGH;
[[fallthrough]];
default:
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
@@ -1454,6 +1476,10 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se
u->current_order.GetLoadType() != order->GetLoadType()) {
u->current_order.SetLoadType(order->GetLoadType());
}
/* Unbunching data is no longer valid. */
u->ResetDepotUnbunching();
InvalidateVehicleOrder(u, VIWD_MODIFY_ORDERS);
}
}
@@ -1513,7 +1539,7 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve
/* Sanity checks */
if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
CommandCost ret = CheckOwnership(src->owner);
ret = CheckOwnership(src->owner);
if (ret.Failed()) return ret;
/* Trucks can't share orders with busses (and visa versa) */
@@ -1532,7 +1558,7 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve
* are temporarily invalid due to reconstruction. */
const Station *st = Station::Get(order->GetDestination());
if (CanVehicleUseStation(src, st) && !CanVehicleUseStation(dst, st)) {
return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
return CommandCost(STR_ERROR_CAN_T_COPY_SHARE_ORDER, GetVehicleCannotUseStationReason(dst, st));
}
}
@@ -1570,15 +1596,16 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve
/* Sanity checks */
if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
CommandCost ret = CheckOwnership(src->owner);
ret = CheckOwnership(src->owner);
if (ret.Failed()) return ret;
/* Trucks can't copy all the orders from busses (and visa versa),
* and neither can helicopters and aircraft. */
for (const Order *order : src->Orders()) {
if (OrderGoesToStation(dst, order) &&
!CanVehicleUseStation(dst, Station::Get(order->GetDestination()))) {
return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
if (!OrderGoesToStation(dst, order)) continue;
Station *st = Station::Get(order->GetDestination());
if (!CanVehicleUseStation(dst, st)) {
return CommandCost(STR_ERROR_CAN_T_COPY_SHARE_ORDER, GetVehicleCannotUseStationReason(dst, st));
}
}
@@ -1641,7 +1668,7 @@ CommandCost CmdCloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID ve
*/
CommandCost CmdOrderRefit(DoCommandFlag flags, VehicleID veh, VehicleOrderID order_number, CargoID cargo)
{
if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT && cargo != CT_AUTO_REFIT) return CMD_ERROR;
if (cargo >= NUM_CARGO && cargo != CARGO_NO_REFIT && cargo != CARGO_AUTO_REFIT) return CMD_ERROR;
const Vehicle *v = Vehicle::GetIfValid(veh);
if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
@@ -1653,7 +1680,7 @@ CommandCost CmdOrderRefit(DoCommandFlag flags, VehicleID veh, VehicleOrderID ord
if (order == nullptr) return CMD_ERROR;
/* Automatic refit cargo is only supported for goto station orders. */
if (cargo == CT_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
if (cargo == CARGO_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
@@ -1661,7 +1688,7 @@ CommandCost CmdOrderRefit(DoCommandFlag flags, VehicleID veh, VehicleOrderID ord
order->SetRefit(cargo);
/* Make the depot order an 'always go' order. */
if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
if (cargo != CARGO_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
}
@@ -1770,12 +1797,9 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool
/* Go through all vehicles */
for (Vehicle *v : Vehicle::Iterate()) {
Order *order;
order = &v->current_order;
if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
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) {
order->MakeDummy();
v->current_order.MakeDummy();
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
}
@@ -1861,6 +1885,9 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
if (!keep_orderlist) v->orders = nullptr;
}
/* Unbunching data is no longer valid. */
v->ResetDepotUnbunching();
if (reset_order_indices) {
v->cur_implicit_order_index = v->cur_real_order_index = 0;
if (v->current_order.IsType(OT_LOADING)) {
@@ -1871,13 +1898,21 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
/**
* Clamp the service interval to the correct min/max. The actual min/max values
* depend on whether it's in percent or days.
* @param interval proposed service interval
* @return Clamped service interval
* depend on whether it's in days, minutes, or percent.
* @param interval The proposed service interval.
* @param ispercent Whether the interval is a percent.
* @return The service interval clamped to use the chosen units.
*/
uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
uint16_t GetServiceIntervalClamped(int interval, bool ispercent)
{
return ispercent ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
/* Service intervals are in percents. */
if (ispercent) return Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT);
/* Service intervals are in minutes. */
if (TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU)) return Clamp(interval, MIN_SERVINT_MINUTES, MAX_SERVINT_MINUTES);
/* Service intervals are in days. */
return Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
}
/**
@@ -1923,6 +1958,12 @@ static bool OrderConditionCompare(OrderConditionComparator occ, int variable, in
}
}
template <typename T, std::enable_if_t<std::is_base_of<StrongTypedefBase, T>::value, int> = 0>
static bool OrderConditionCompare(OrderConditionComparator occ, T variable, int value)
{
return OrderConditionCompare(occ, variable.base(), value);
}
/**
* Process a conditional order and determine the next order.
* @param order the order the vehicle currently has
@@ -1935,17 +1976,17 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
bool skip_order = false;
OrderConditionComparator occ = order->GetConditionComparator();
uint16 value = order->GetConditionValue();
uint16_t value = order->GetConditionValue();
switch (order->GetConditionVariable()) {
case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, nullptr), value); break;
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / DAYS_IN_LEAP_YEAR, value); break;
case OCV_AGE: skip_order = OrderConditionCompare(occ, TimerGameCalendar::DateToYear(v->age), value); break;
case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
case OCV_UNCONDITIONALLY: skip_order = true; break;
case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(v->max_age - v->age + DAYS_IN_LEAP_YEAR - 1, 0) / DAYS_IN_LEAP_YEAR, value); break;
case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(TimerGameCalendar::DateToYear(v->max_age - v->age + CalendarTime::DAYS_IN_LEAP_YEAR - 1), TimerGameCalendar::Year(0)), value); break;
default: NOT_REACHED();
}
@@ -1981,26 +2022,27 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
}
if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
/* If the vehicle can't find its destination, delay its next search.
* In case many vehicles are in this state, use the vehicle index to spread out pathfinder calls. */
if (v->dest_tile == 0 && TimerGameEconomy::date_fract != (v->index % Ticks::DAY_TICKS)) break;
/* We need to search for the nearest depot (hangar). */
TileIndex location;
DestinationID destination;
bool reverse;
ClosestDepot closestDepot = v->FindClosestDepot();
if (v->FindClosestDepot(&location, &destination, &reverse)) {
if (closestDepot.found) {
/* PBS reservations cannot reverse */
if (pbs_look_ahead && reverse) return false;
if (pbs_look_ahead && closestDepot.reverse) return false;
v->SetDestTile(location);
v->current_order.SetDestination(destination);
v->SetDestTile(closestDepot.location);
v->current_order.SetDestination(closestDepot.destination);
/* If there is no depot in front, reverse automatically (trains only) */
if (v->type == VEH_TRAIN && reverse) Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DC_EXEC, v->index, false);
if (v->type == VEH_TRAIN && closestDepot.reverse) Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DC_EXEC, v->index, false);
if (v->type == VEH_AIRCRAFT) {
Aircraft *a = Aircraft::From(v);
if (a->state == FLYING && a->targetairport != destination) {
if (a->state == FLYING && a->targetairport != closestDepot.destination) {
/* The aircraft is now heading for a different hangar than the next in the orders */
extern void AircraftNextAirportPos_and_Order(Aircraft *a);
AircraftNextAirportPos_and_Order(a);
}
}
@@ -2045,7 +2087,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
/* Disable creation of implicit orders.
* When inserting them we do not know that we would have to make the conditional orders point to them. */
if (v->IsGroundVehicle()) {
uint16 &gv_flags = v->GetGroundVehicleFlags();
uint16_t &gv_flags = v->GetGroundVehicleFlags();
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
}
} else {
@@ -2142,7 +2184,6 @@ bool ProcessOrders(Vehicle *v)
if (order == nullptr || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
if (v->type == VEH_AIRCRAFT) {
/* Aircraft do something vastly different here, so handle separately */
extern void HandleMissingAircraftOrders(Aircraft *v);
HandleMissingAircraftOrders(Aircraft::From(v));
return false;
}