Skip to content

Commit

Permalink
Add conditional order for waiting cargo as percentage of vehicle capa…
Browse files Browse the repository at this point in the history
…city

See: #738
  • Loading branch information
JGRennison committed Sep 3, 2024
1 parent 2e3f7d5 commit c463cc1
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 16 deletions.
5 changes: 5 additions & 0 deletions src/lang/extra/english.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ STR_ORDER_CONDITIONAL_COUNTER_VALUE :Counter value
STR_ORDER_CONDITIONAL_TIME_DATE_VALUE :Current time/date
STR_ORDER_CONDITIONAL_TIMETABLE_STATE :Timetable state
STR_ORDER_CONDITIONAL_DISPATCH_SLOT :Dispatch slot
STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_PERCENTAGE :Waiting cargo / capacity

##after STR_ORDER_STOP_LOCATION_FAR_END
STR_ORDER_STOP_LOCATION_THROUGH :[through load]
Expand Down Expand Up @@ -1773,12 +1774,16 @@ STR_ORDER_CONDITIONAL_IN_INVALID_SLOT :Jump to order {
STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE_DISPLAY :Jump to order {COMMA} when Load percentage of {STRING} {STRING} {COMMA}
STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_DISPLAY :Jump to order {COMMA} when {STRING} at {STRING1} {STRING} {CARGO_SHORT}
STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_VIA_DISPLAY :Jump to order {COMMA} when {STRING} at {STRING1} via {STRING1} {STRING} {CARGO_SHORT}
STR_ORDER_CONDITIONAL_CARGO_WAITING_GENERAL_DISPLAY :Jump to order {COMMA} when {STRING} at {STRING1} {STRING} {STRING}
STR_ORDER_CONDITIONAL_CARGO_WAITING_GENERAL_VIA_DISPLAY :Jump to order {COMMA} when {STRING} at {STRING1} via {STRING1} {STRING} {STRING}
STR_ORDER_CONDITIONAL_COUNTER :Jump to order {COMMA} when value of {TRCOUNTER} {STRING} {COMMA}
STR_ORDER_CONDITIONAL_INVALID_COUNTER :Jump to order {COMMA} when value of {PUSH_COLOUR}{RED}{STRING}{POP_COLOUR} {STRING} {COMMA}
STR_ORDER_CONDITIONAL_TIME_HHMM :Jump to order {COMMA} when {STRING} {STRING} {TIME_HHMM}
STR_ORDER_CONDITIONAL_TIMETABLE :Jump to order {COMMA} when {STRING} {STRING} {TT_TICKS}
STR_ORDER_CONDITIONAL_DISPATCH_SLOT_DISPLAY :Jump to order {COMMA} when {STRING} {STRING} {STRING}

STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY :{COMMA} percent of {STRING} capacity

STR_ORDER_TRY_ACQUIRE_SLOT :Try to acquire slot: {STRING1}
STR_ORDER_RELEASE_SLOT :Release slot: {STRING1}

Expand Down
2 changes: 2 additions & 0 deletions src/order_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ void ClearOrderDestinationRefcountMap();
* OCV_TIMETABLE: Timetable lateness/earliness
* OCV_TIME_DATE: Time/date
* OCV_CARGO_WAITING_AMOUNT: Bits 0-15: Cargo quantity comparison value, Bits 16-31: Via station ID + 2
* OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: Bits 0-15: Cargo quantity comparison value, Bits 16-31: Via station ID + 2
* OCV_CARGO_LOAD_PERCENTAGE: Cargo percentage comparison value
* OCV_DISPATCH_SLOT: Bits 0-15: Dispatch schedule ID
* OCV_PERCENT: Bits 0-7: Jump counter
Expand All @@ -77,6 +78,7 @@ void ClearOrderDestinationRefcountMap();
* OCV_CARGO_ACCEPTANCE: Bits 0-15: Station ID to test + 1
* OCV_FREE_PLATFORMS: Bits 0-15: Station ID to test + 1
* OCV_CARGO_WAITING_AMOUNT: Bits 0-15: Station ID to test + 1
* OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: Bits 0-15: Station ID to test + 1
*/

struct OrderExtraInfo {
Expand Down
36 changes: 32 additions & 4 deletions src/order_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
TileIndex Order::GetAuxiliaryLocation(bool secondary) const
{
if (this->IsType(OT_CONDITIONAL)) {
if (secondary && this->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT && GB(this->GetXData(), 16, 16) != 0) {
if (secondary && ConditionVariableTestsCargoWaitingAmount(this->GetConditionVariable()) && GB(this->GetXData(), 16, 16) != 0) {
const Station *st = Station::GetIfValid(GB(this->GetXData(), 16, 16) - 2);
if (st != nullptr) return st->xy;
}
Expand Down Expand Up @@ -1291,6 +1291,7 @@ static CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOr
break;

case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
if (!CargoSpec::Get(new_order.GetConditionValue())->IsValid()) return CMD_ERROR;
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
break;
Expand Down Expand Up @@ -2074,6 +2075,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
break;

case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
case OCV_COUNTER_VALUE:
case OCV_TIME_DATE:
case OCV_TIMETABLE:
Expand All @@ -2095,6 +2097,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
switch (order->GetConditionVariable()) {
case OCV_CARGO_LOAD_PERCENTAGE:
case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
if (!(data < NUM_CARGO && CargoSpec::Get(data)->IsValid())) return CMD_ERROR;
break;

Expand Down Expand Up @@ -2124,6 +2127,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
case MOF_COND_VALUE_3:
switch (order->GetConditionVariable()) {
case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
if (!(data == NEW_STATION || Station::GetIfValid(data) != nullptr)) return CMD_ERROR;
if (GB(order->GetXData2(), 0, 16) - 1 == data) return CMD_ERROR;
break;
Expand Down Expand Up @@ -2284,7 +2288,8 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
/* Check whether old conditional variable had a cargo as value */
OrderConditionVariable old_condition = order->GetConditionVariable();
bool old_var_was_cargo = (order->GetConditionVariable() == OCV_CARGO_ACCEPTANCE || order->GetConditionVariable() == OCV_CARGO_WAITING
|| order->GetConditionVariable() == OCV_CARGO_LOAD_PERCENTAGE || order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT);
|| order->GetConditionVariable() == OCV_CARGO_LOAD_PERCENTAGE || order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT
|| order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE);
bool old_var_was_slot = (order->GetConditionVariable() == OCV_SLOT_OCCUPANCY || order->GetConditionVariable() == OCV_VEH_IN_SLOT);
bool old_var_was_counter = (order->GetConditionVariable() == OCV_COUNTER_VALUE);
bool old_var_was_time = (order->GetConditionVariable() == OCV_TIME_DATE);
Expand Down Expand Up @@ -2336,6 +2341,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
break;
case OCV_CARGO_LOAD_PERCENTAGE:
case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
if (!old_var_was_cargo) order->SetConditionValue((uint16_t) GetFirstValidCargo());
order->GetXDataRef() = 0;
order->SetConditionComparator(OCC_EQUALS);
Expand Down Expand Up @@ -2389,6 +2395,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin
break;

case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
case OCV_COUNTER_VALUE:
SB(order->GetXDataRef(), 0, 16, data);
break;
Expand Down Expand Up @@ -2421,7 +2428,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uin

case MOF_COND_STATION_ID:
SB(order->GetXData2Ref(), 0, 16, data + 1);
if (order->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT && data == GB(order->GetXData(), 16, 16) - 2) {
if (ConditionVariableTestsCargoWaitingAmount(order->GetConditionVariable()) && data == GB(order->GetXData(), 16, 16) - 2) {
/* Clear via if station is set to the same ID */
SB(order->GetXDataRef(), 16, 16, 0);
}
Expand Down Expand Up @@ -3051,7 +3058,7 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool
RemoveVehicleOrdersIf(v, [&](const Order *o) {
OrderType ot = o->GetType();
if (ot == OT_CONDITIONAL) {
if (type == OT_GOTO_STATION && o->GetConditionVariable() == OCV_CARGO_WAITING_AMOUNT) {
if (type == OT_GOTO_STATION && ConditionVariableTestsCargoWaitingAmount(o->GetConditionVariable())) {
if (GB(order->GetXData(), 16, 16) - 2 == destination) SB(order->GetXDataRef(), 16, 16, INVALID_STATION + 2);
}
if (type == OT_GOTO_STATION && ConditionVariableHasStationID(o->GetConditionVariable())) {
Expand Down Expand Up @@ -3380,6 +3387,27 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
}
break;
}
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE: {
StationID next_station = GB(order->GetXData2(), 0, 16) - 1;
if (Station::IsValidID(next_station)) {
uint32_t waiting;
if (GB(order->GetXData(), 16, 16) == 0) {
waiting = Station::Get(next_station)->goods[value].CargoAvailableCount();
} else {
waiting = Station::Get(next_station)->goods[value].CargoAvailableViaCount(GB(order->GetXData(), 16, 16) - 2);
}

uint32_t veh_capacity = 0;
for (const Vehicle *v_iter = v; v_iter != nullptr; v_iter = v_iter->Next()) {
if (v_iter->cargo_type == value) veh_capacity += v_iter->cargo_cap;
}
uint32_t percentage = GB(order->GetXData(), 0, 16);
uint32_t threshold = static_cast<uint32_t>(((uint64_t)veh_capacity * percentage) / 100);

skip_order = OrderConditionCompare(occ, waiting, threshold);
}
break;
}
case OCV_CARGO_ACCEPTANCE: {
StationID next_station = GB(order->GetXData2(), 0, 16) - 1;
if (Station::IsValidID(next_station)) skip_order = OrderConditionCompare(occ, HasBit(Station::Get(next_station)->goods[value].status, GoodsEntry::GES_ACCEPTANCE), value);
Expand Down
32 changes: 23 additions & 9 deletions src/order_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ static const OrderConditionVariable _order_conditional_variable[] = {
OCV_REQUIRES_SERVICE,
OCV_CARGO_WAITING,
OCV_CARGO_WAITING_AMOUNT,
OCV_CARGO_WAITING_AMOUNT_PERCENTAGE,
OCV_CARGO_ACCEPTANCE,
OCV_FREE_PLATFORMS,
OCV_SLOT_OCCUPANCY,
Expand Down Expand Up @@ -1047,21 +1048,32 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(2, CargoSpec::Get(order->GetConditionValue())->name);
SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator());
SetDParam(4, order->GetXData());
} else if (ocv == OCV_CARGO_WAITING_AMOUNT) {
} else if (ocv == OCV_CARGO_WAITING_AMOUNT || ocv == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE) {
const bool percent_mode = (ocv == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE);
ArrayStringParameters<10> tmp_params;
StringID substr;

tmp_params.SetParam(0, order->GetConditionSkipToOrder() + 1);
tmp_params.SetParam(1, CargoSpec::Get(order->GetConditionValue())->name);
set_station_id(2, tmp_params);

auto output_condition_value = [&](int param_offset) {
if (percent_mode) {
auto capacity_params = MakeParameters(GB(order->GetXData(), 0, 16), CargoSpec::Get(order->GetConditionValue())->name);
_temp_special_strings[0] = GetStringWithArgs(STR_ORDER_CONDITIONAL_CARGO_WAITING_PERCENT_CAPACITY, capacity_params);
tmp_params.SetParam(param_offset, SPECSTR_TEMP_START);
} else {
tmp_params.SetParam(param_offset, order->GetConditionValue());
tmp_params.SetParam(param_offset + 1, GB(order->GetXData(), 0, 16));
}
};

if (GB(order->GetXData(), 16, 16) == 0) {
substr = STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_DISPLAY;
substr = percent_mode ? STR_ORDER_CONDITIONAL_CARGO_WAITING_GENERAL_DISPLAY : STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_DISPLAY;
tmp_params.SetParam(4, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator());
tmp_params.SetParam(5, order->GetConditionValue());
tmp_params.SetParam(6, GB(order->GetXData(), 0, 16));
output_condition_value(5);
} else {
substr = STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_VIA_DISPLAY;
substr = percent_mode ? STR_ORDER_CONDITIONAL_CARGO_WAITING_GENERAL_VIA_DISPLAY : STR_ORDER_CONDITIONAL_CARGO_WAITING_AMOUNT_VIA_DISPLAY;
const Station *via_st = Station::GetIfValid(GB(order->GetXData(), 16, 16) - 2);
if (via_st == nullptr) {
tmp_params.SetParam(4, STR_ORDER_CONDITIONAL_UNDEFINED_STATION);
Expand All @@ -1070,8 +1082,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
tmp_params.SetParam(5, via_st->index);
}
tmp_params.SetParam(6, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + order->GetConditionComparator());
tmp_params.SetParam(7, order->GetConditionValue());
tmp_params.SetParam(8, GB(order->GetXData(), 0, 16));
output_condition_value(7);
}
_temp_special_strings[0] = GetStringWithArgs(substr, tmp_params);
SetDParam(0, SPECSTR_TEMP_START);
Expand Down Expand Up @@ -2298,7 +2309,7 @@ struct OrdersWindow : public GeneralVehicleWindow {
OrderConditionVariable ocv = (order == nullptr) ? OCV_LOAD_PERCENTAGE : order->GetConditionVariable();
bool is_cargo = (ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_CARGO_WAITING);
bool is_slot_occupancy = (ocv == OCV_SLOT_OCCUPANCY || ocv == OCV_VEH_IN_SLOT);
bool is_auxiliary_cargo = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ocv == OCV_CARGO_WAITING_AMOUNT);
bool is_auxiliary_cargo = (ocv == OCV_CARGO_LOAD_PERCENTAGE || ConditionVariableTestsCargoWaitingAmount(ocv));
bool is_counter = (ocv == OCV_COUNTER_VALUE);
bool is_time_date = (ocv == OCV_TIME_DATE);
bool is_timetable = (ocv == OCV_TIMETABLE);
Expand Down Expand Up @@ -2347,7 +2358,7 @@ struct OrdersWindow : public GeneralVehicleWindow {
aux_sel->SetDisplayedPlane(SZSP_NONE);
}

if (ocv == OCV_CARGO_WAITING_AMOUNT) {
if (ConditionVariableTestsCargoWaitingAmount(ocv)) {
aux2_sel->SetDisplayedPlane(DP_COND_AUX2_VIA);
} else if (is_sched_dispatch) {
this->GetWidget<NWidgetCore>(WID_O_COND_SCHED_TEST)->widget_data = STR_TRACE_RESTRICT_DISPATCH_SLOT_SHORT_NEXT + GB(order->GetConditionValue(), ODCB_SRC_START, ODCB_SRC_COUNT);
Expand Down Expand Up @@ -2611,6 +2622,7 @@ struct OrdersWindow : public GeneralVehicleWindow {
break;

case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
case OCV_COUNTER_VALUE:
value = GB(order->GetXData(), 0, 16);
break;
Expand Down Expand Up @@ -3270,6 +3282,7 @@ struct OrdersWindow : public GeneralVehicleWindow {
break;

case OCV_CARGO_WAITING_AMOUNT:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
case OCV_COUNTER_VALUE:
value = GB(order->GetXData(), 0, 16);
break;
Expand Down Expand Up @@ -3379,6 +3392,7 @@ struct OrdersWindow : public GeneralVehicleWindow {

case OCV_COUNTER_VALUE:
case OCV_TIME_DATE:
case OCV_CARGO_WAITING_AMOUNT_PERCENTAGE:
value = Clamp(value, 0, 0xFFFF);
break;

Expand Down
8 changes: 7 additions & 1 deletion src/order_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,18 @@ enum OrderConditionVariable {
OCV_TIME_DATE, ///< Skip based on current time/date
OCV_TIMETABLE, ///< Skip based on timetable state
OCV_DISPATCH_SLOT, ///< Skip based on scheduled dispatch slot state
OCV_CARGO_WAITING_AMOUNT_PERCENTAGE, ///< Skip based on the amount of a specific cargo waiting at station, relative to the vehicle capacity
OCV_END
};

inline bool ConditionVariableHasStationID(OrderConditionVariable ocv)
{
return ocv == OCV_CARGO_WAITING || ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_FREE_PLATFORMS || ocv == OCV_CARGO_WAITING_AMOUNT;
return ocv == OCV_CARGO_WAITING || ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_FREE_PLATFORMS || ocv == OCV_CARGO_WAITING_AMOUNT || ocv == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE;
}

inline bool ConditionVariableTestsCargoWaitingAmount(OrderConditionVariable ocv)
{
return ocv == OCV_CARGO_WAITING_AMOUNT || ocv == OCV_CARGO_WAITING_AMOUNT_PERCENTAGE;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/saveload/afterload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4132,7 +4132,7 @@ bool AfterLoadGame()
};

for (Order *order = order_list->GetFirstOrder(); order != nullptr; order = order->next) {
/* Fixup station ID for OCV_CARGO_WAITING, OCV_CARGO_ACCEPTANCE, OCV_FREE_PLATFORMS, OCV_CARGO_WAITING_AMOUNT */
/* Fixup station ID for OCV_CARGO_WAITING, OCV_CARGO_ACCEPTANCE, OCV_FREE_PLATFORMS, OCV_CARGO_WAITING_AMOUNT, OCV_CARGO_WAITING_AMOUNT_PERCENTAGE */
if (order->IsType(OT_CONDITIONAL) && ConditionVariableHasStationID(order->GetConditionVariable())) {
StationID next_id = get_real_station(order);
SB(order->GetXData2Ref(), 0, 16, next_id + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/sl/extended_ver_sl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" },
{ XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 7, 7, "variable_day_length", nullptr, nullptr, nullptr },
{ XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 18, 18, "more_cond_orders", nullptr, nullptr, nullptr },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 19, 19, "more_cond_orders", nullptr, nullptr, nullptr },
{ XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr },
{ XSLFI_REVERSE_AT_WAYPOINT, XSCF_NULL, 1, 1, "reverse_at_waypoint", nullptr, nullptr, nullptr },
{ XSLFI_VEH_LIFETIME_PROFIT, XSCF_NULL, 1, 1, "veh_lifetime_profit", nullptr, nullptr, nullptr },
Expand Down

0 comments on commit c463cc1

Please sign in to comment.