Skip to content

Commit

Permalink
First implementation of conditional order checking slot occupancy
Browse files Browse the repository at this point in the history
  • Loading branch information
KeldorKatarn committed Apr 11, 2018
1 parent 4bae1be commit 524e3e5
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 8 deletions.
6 changes: 6 additions & 0 deletions src/lang/english.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4307,6 +4307,7 @@ STR_ORDER_CONDITIONAL_REMAINING_LIFETIME :Remaining lifet
STR_ORDER_CONDITIONAL_CARGO_WAITING :Waiting cargo
STR_ORDER_CONDITIONAL_ACCEPTANCE_DROPDOWN :Accepted cargo
STR_ORDER_CONDITIONAL_FREE_PLATFORMS :Free platforms
STR_ORDER_CONDITIONAL_SLOT_OCCUPANCY :Slot occupancy
STR_ORDER_CONDITIONAL_PERCENT :Percent of times

STR_ORDER_CONDITIONAL_REQUIRES_SERVICE_ORDER :Requires service {STRING}
Expand All @@ -4329,6 +4330,7 @@ STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE :is false

STR_ORDER_CONDITIONAL_VALUE_TOOLTIP :{BLACK}The value to compare the vehicle data against
STR_ORDER_CONDITIONAL_CARGO_TOOLTIP :{BLACK}The cargo to compare the station data against
STR_ORDER_CONDITIONAL_SLOT_TOOLTIP :{BLACK}The train slot to check the occupancy of
STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Enter value to compare against

STR_ORDER_CONDITIONAL_COMPARATOR_ACCEPTS :accepts
Expand All @@ -4339,6 +4341,8 @@ STR_ORDER_CONDITIONAL_COMPARATOR_HAS_LESS_THAN :has less than
STR_ORDER_CONDITIONAL_COMPARATOR_HAS_LESS_EQUALS :has less than or exactly
STR_ORDER_CONDITIONAL_COMPARATOR_HAS_MORE_THAN :has more than
STR_ORDER_CONDITIONAL_COMPARATOR_HAS_MORE_EQUALS :has more than or exactly
STR_ORDER_CONDITIONAL_COMPARATOR_FULLY_OCCUPIED :is fully occupied
STR_ORDER_CONDITIONAL_COMPARATOR_NOT_YET_FULLY_OCCUPIED :is not fully occupied

STR_ORDERS_SKIP_BUTTON :{BLACK}Skip
STR_ORDERS_SKIP_TOOLTIP :{BLACK}Skip the current order, and start the next. Ctrl+Click skips to the selected order
Expand Down Expand Up @@ -4440,6 +4444,8 @@ STR_ORDER_OUT_OF_RANGE :{RED} (Next des
STR_ORDER_CONDITIONAL_UNCONDITIONAL :Jump to order {COMMA}
STR_ORDER_CONDITIONAL_NUM :Jump to order {COMMA} when {STRING} {STRING} {COMMA}
STR_ORDER_CONDITIONAL_CARGO :Jump to order {COMMA} when {STRING} {STRING} {STRING}
STR_ORDER_CONDITIONAL_SLOT :Jump to order {COMMA} when {TRSLOT} {STRING}
STR_ORDER_CONDITIONAL_INVALID_SLOT :Jump to order {COMMA} when {RED}{STRING} {PREVIOUS_COLOUR}{STRING}
STR_ORDER_CONDITIONAL_TRUE_FALSE :Jump to order {COMMA} when {STRING} {STRING}

STR_INVALID_ORDER :{RED} (Invalid Order)
Expand Down
44 changes: 42 additions & 2 deletions src/order_cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "order_backup.h"
#include "cheat_type.h"
#include "viewport_func.h"
#include "tracerestrict.h"

#include "table/strings.h"

Expand Down Expand Up @@ -1112,10 +1113,16 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
OrderConditionComparator occ = new_order.GetConditionComparator();
if (occ >= OCC_END) return CMD_ERROR;
switch (new_order.GetConditionVariable()) {
case OCV_SLOT_OCCUPANCY: {
if (!TraceRestrictSlot::IsValidID(new_order.GetConditionValue())) return CMD_ERROR;
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
break;
}
case OCV_CARGO_WAITING:
case OCV_CARGO_ACCEPTANCE:
if (!CargoSpec::Get(new_order.GetConditionValue())->IsValid()) return CMD_ERROR;
/* FALL THROUGH */

case OCV_REQUIRES_SERVICE:
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
break;
Expand Down Expand Up @@ -1300,6 +1307,21 @@ static CargoID GetFirstValidCargo()
return 0;
}

/**
* Get the first valid TraceRestrictSlot. Or INVALID_TRACE_RESTRICT_SLOT_ID if no slots are defined.
*/
static TraceRestrictSlotID GetFirstValidTraceRestrictSlot()
{
const TraceRestrictSlot* slot;
FOR_ALL_TRACE_RESTRICT_SLOTS(slot)
{
// Stupid way to get the first valid slot but there is no "GetFirstValidSlot()".
return slot->index;
}

return INVALID_TRACE_RESTRICT_SLOT_ID;
}

/**
* Delete an order from the orderlist of a vehicle.
* @param tile unused
Expand Down Expand Up @@ -1664,6 +1686,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case OCV_REQUIRES_SERVICE:
case OCV_CARGO_ACCEPTANCE:
case OCV_CARGO_WAITING:
case OCV_SLOT_OCCUPANCY:
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
break;

Expand All @@ -1684,6 +1707,11 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case OCV_PERCENT:
if (data > 100) return CMD_ERROR;
break;

case OCV_SLOT_OCCUPANCY:
// Can't encode more than 2047, even though there could be more slots.
if (data > 2047 || !TraceRestrictSlot::IsValidID(data)) return CMD_ERROR;
break;

case OCV_CARGO_ACCEPTANCE:
case OCV_CARGO_WAITING:
Expand Down Expand Up @@ -1765,6 +1793,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case MOF_COND_VARIABLE: {
/* Check whether old conditional variable had a cargo as value */
bool old_var_was_cargo = (order->GetConditionVariable() == OCV_CARGO_ACCEPTANCE || order->GetConditionVariable() == OCV_CARGO_WAITING);
bool old_var_was_slot = (order->GetConditionVariable() == OCV_SLOT_OCCUPANCY);
order->SetConditionVariable((OrderConditionVariable)data);

OrderConditionComparator occ = order->GetConditionComparator();
Expand All @@ -1773,6 +1802,11 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
order->SetConditionComparator(OCC_EQUALS);
order->SetConditionValue(0);
break;

case OCV_SLOT_OCCUPANCY:
if (!old_var_was_slot) order->SetConditionValue((uint16)GetFirstValidTraceRestrictSlot());
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
break;

case OCV_CARGO_ACCEPTANCE:
case OCV_CARGO_WAITING:
Expand All @@ -1781,7 +1815,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
break;

case OCV_REQUIRES_SERVICE:
if (old_var_was_cargo) order->SetConditionValue(0);
if (old_var_was_cargo || old_var_was_slot) order->SetConditionValue(0);
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
order->SetConditionValue(0);
break;
Expand All @@ -1796,7 +1830,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
FALLTHROUGH;

default:
if (old_var_was_cargo) order->SetConditionValue(0);
if (old_var_was_cargo || old_var_was_slot) order->SetConditionValue(0);
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
break;
}
Expand Down Expand Up @@ -2394,6 +2428,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
uint16 value = order->GetConditionValue();
bool has_manual_depot_order = (HasBit(v->vehicle_flags, VF_SHOULD_GOTO_DEPOT) || HasBit(v->vehicle_flags, VF_SHOULD_SERVICE_AT_DEPOT));

// OrderConditionCompare ignores the last parameter for occ == OCC_IS_TRUE or occ == OCC_IS_FALSE.
switch (order->GetConditionVariable()) {
case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
Expand All @@ -2411,6 +2446,11 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
if (Station::IsValidID(next_station)) skip_order = OrderConditionCompare(occ, HasBit(Station::Get(next_station)->goods[value].status, GoodsEntry::GES_ACCEPTANCE), value);
break;
}
case OCV_SLOT_OCCUPANCY: {
const TraceRestrictSlot* slot = TraceRestrictSlot::GetIfValid(value);
if (slot != nullptr) skip_order = OrderConditionCompare(occ, slot->occupants.size() >= slot->max_occupancy, value);
break;
}
case OCV_FREE_PLATFORMS: {
StationID next_station = GetNextRealStation(v, order);
if (Station::IsValidID(next_station)) skip_order = OrderConditionCompare(occ, GetFreeStationPlatforms(next_station), value);
Expand Down
75 changes: 70 additions & 5 deletions src/order_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "hotkeys.h"
#include "aircraft.h"
#include "engine_func.h"
#include "tracerestrict.h"

#include "widgets/order_widget.h"

Expand Down Expand Up @@ -61,6 +62,8 @@ static const StringID _cargo_type_unload_order_drowdown[] = {
};
static const uint32 _cargo_type_unload_order_drowdown_hidden_mask = 0x8; // 01000

DropDownList* GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected);

struct CargoTypeOrdersWindow : public Window {
private:
CargoTypeOrdersWindowVariant variant;
Expand Down Expand Up @@ -600,6 +603,7 @@ static const OrderConditionVariable _order_conditional_variable[] = {
OCV_CARGO_WAITING,
OCV_CARGO_ACCEPTANCE,
OCV_FREE_PLATFORMS,
OCV_SLOT_OCCUPANCY,
OCV_PERCENT,
OCV_UNCONDITIONALLY,
};
Expand Down Expand Up @@ -640,6 +644,18 @@ static const StringID _order_conditional_condition_accepts[] = {
INVALID_STRING_ID,
};

static const StringID _order_conditional_condition_is_fully_occupied[] = {
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_NULL,
STR_ORDER_CONDITIONAL_COMPARATOR_FULLY_OCCUPIED,
STR_ORDER_CONDITIONAL_COMPARATOR_NOT_YET_FULLY_OCCUPIED,
INVALID_STRING_ID,
};

extern uint ConvertSpeedToDisplaySpeed(uint speed);
extern uint ConvertDisplaySpeedToSpeed(uint speed);

Expand Down Expand Up @@ -814,6 +830,18 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
SetDParam(2, STR_ORDER_CONDITIONAL_COMPARATOR_HAS + order->GetConditionComparator());
SetDParam(3, order->GetConditionValue());
}
else if (ocv == OCV_SLOT_OCCUPANCY) {
if (TraceRestrictSlot::IsValidID(order->GetConditionValue()))
{
SetDParam(0, STR_ORDER_CONDITIONAL_SLOT);
SetDParam(2, order->GetConditionValue());
}
else {
SetDParam(0, STR_ORDER_CONDITIONAL_INVALID_SLOT);
SetDParam(2, STR_TRACE_RESTRICT_VARIABLE_UNDEFINED);
}
SetDParam(3, order->GetConditionComparator() == OCC_IS_TRUE ? STR_ORDER_CONDITIONAL_COMPARATOR_FULLY_OCCUPIED : STR_ORDER_CONDITIONAL_COMPARATOR_NOT_YET_FULLY_OCCUPIED);
}
else {
OrderConditionComparator occ = order->GetConditionComparator();
bool is_cargo = ocv == OCV_CARGO_ACCEPTANCE || ocv == OCV_CARGO_WAITING;
Expand Down Expand Up @@ -1045,6 +1073,7 @@ struct OrdersWindow : public Window {
/* WID_O_SEL_COND_VALUE */
DP_COND_VALUE_NUMBER = 0, ///< Display number widget
DP_COND_VALUE_CARGO = 1, ///< Display dropdown widget cargo types
DP_COND_VALUE_SLOT = 2, ///< Display dropdown widget tracerestrict slots

/* WID_O_SEL_BOTTOM_MIDDLE */
DP_BOTTOM_MIDDLE_DELETE = 0, ///< Display 'delete' in the middle button of the bottom row of the vehicle order window.
Expand Down Expand Up @@ -1102,9 +1131,10 @@ struct OrdersWindow : public Window {
if (order == NULL) return _order_conditional_condition;
switch (order->GetConditionVariable()) {
case OCV_FREE_PLATFORMS: //fall through
case OCV_CARGO_WAITING: return _order_conditional_condition_has; break;
case OCV_CARGO_ACCEPTANCE: return _order_conditional_condition_accepts; break;
default: return _order_conditional_condition; break;
case OCV_CARGO_WAITING: return _order_conditional_condition_has; break;
case OCV_CARGO_ACCEPTANCE: return _order_conditional_condition_accepts; break;
case OCV_SLOT_OCCUPANCY: return _order_conditional_condition_is_fully_occupied; break;
default: return _order_conditional_condition; break;
}
}

Expand Down Expand Up @@ -1621,12 +1651,19 @@ struct OrdersWindow : public Window {

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;

if (is_cargo) {
CargoSpec* cargo_spec = CargoSpec::Get(order != nullptr ? order->GetConditionValue() : 0);
this->GetWidget<NWidgetCore>(WID_O_COND_CARGO)->widget_data = cargo_spec->name;
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_CARGO);
}
else if (is_slot_occupancy) {
TraceRestrictSlotID slot_id = (order != nullptr && TraceRestrictSlot::IsValidID(order->GetConditionValue()) ? order->GetConditionValue() : INVALID_TRACE_RESTRICT_SLOT_ID);

this->GetWidget<NWidgetCore>(WID_O_COND_SLOT)->widget_data = slot_id != INVALID_TRACE_RESTRICT_SLOT_ID ? STR_TRACE_RESTRICT_SLOT_NAME : STR_TRACE_RESTRICT_VARIABLE_UNDEFINED;
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_SLOT);
}
else {
this->GetWidget<NWidgetStacked>(WID_O_SEL_COND_VALUE)->SetDisplayedPlane(DP_COND_VALUE_NUMBER);
}
Expand Down Expand Up @@ -1745,6 +1782,17 @@ struct OrdersWindow : public Window {
break;
}

case WID_O_COND_SLOT: {
VehicleOrderID sel = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel);

if (order != nullptr && order->IsType(OT_CONDITIONAL)) {
TraceRestrictSlotID value = order->GetConditionValue();
SetDParam(0, value);
}
break;
}

case WID_O_CAPTION:
SetDParam(0, this->vehicle->index);
break;
Expand Down Expand Up @@ -1914,6 +1962,14 @@ struct OrdersWindow : public Window {
break;
}

case WID_O_COND_SLOT: {
int selected;
TraceRestrictSlotID value = this->vehicle->GetOrder(this->OrderGetSel())->GetConditionValue();
DropDownList *list = GetSlotDropDownList(this->vehicle->owner, value, selected);
if (list != nullptr) ShowDropDownList(this, list, selected, WID_O_COND_SLOT, 0, true);
break;
}

case WID_O_REVERSE: {
VehicleOrderID sel_ord = this->OrderGetSel();
const Order *order = this->vehicle->GetOrder(sel_ord);
Expand Down Expand Up @@ -1943,8 +1999,9 @@ struct OrdersWindow : public Window {
OrderConditionVariable cond_var = o->GetConditionVariable();
ShowDropDownMenu(this, GetComparatorStrings(o), o->GetConditionComparator(), WID_O_COND_COMPARATOR, 0,
(cond_var == OCV_REQUIRES_SERVICE ||
cond_var == OCV_CARGO_ACCEPTANCE ||
cond_var == OCV_CARGO_WAITING) ? 0x3F : 0xC0);
cond_var == OCV_CARGO_ACCEPTANCE ||
cond_var == OCV_CARGO_WAITING ||
cond_var == OCV_SLOT_OCCUPANCY) ? 0x3F : 0xC0);
break;
}

Expand Down Expand Up @@ -2031,6 +2088,10 @@ struct OrdersWindow : public Window {
case WID_O_COND_CARGO:
DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VALUE | index << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
break;

case WID_O_COND_SLOT:
DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 20), MOF_COND_VALUE | index << 4, CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
break;
}
}

Expand Down Expand Up @@ -2281,6 +2342,8 @@ static const NWidgetPart _nested_orders_train_widgets[] = {
SetDataTip(STR_BLACK_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_CARGO), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_CARGO_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SLOT), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SLOT_TOOLTIP), SetResize(1, 0),
EndContainer(),
EndContainer(),
EndContainer(),
Expand Down Expand Up @@ -2359,6 +2422,8 @@ static const NWidgetPart _nested_orders_widgets[] = {
SetDataTip(STR_BLACK_COMMA, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_CARGO), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_CARGO_TOOLTIP), SetResize(1, 0),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_O_COND_SLOT), SetMinimalSize(124, 12), SetFill(1, 0),
SetDataTip(STR_NULL, STR_ORDER_CONDITIONAL_SLOT_TOOLTIP), SetResize(1, 0),
EndContainer(),
EndContainer(),
EndContainer(),
Expand Down
1 change: 1 addition & 0 deletions src/order_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ enum OrderConditionVariable {
OCV_CARGO_WAITING, ///< Skip if specified cargo is waiting at next station
OCV_CARGO_ACCEPTANCE, ///< Skip if specified cargo is accepted at next station
OCV_FREE_PLATFORMS, ///< Skip based on free platforms at next station
OCV_SLOT_OCCUPANCY, ///< Test if train slot is fully occupied
OCV_PERCENT, ///< Skip xx percent of times
OCV_END
};
Expand Down
2 changes: 2 additions & 0 deletions src/tracerestrict.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,7 @@ CommandCost CmdDeleteTraceRestrictSlot(TileIndex tile, DoCommandFlag flags, uint

InvalidateWindowClassesData(WC_TRACE_RESTRICT);
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
}

return CommandCost();
Expand Down Expand Up @@ -1626,6 +1627,7 @@ CommandCost CmdAlterTraceRestrictSlot(TileIndex tile, DoCommandFlag flags, uint3
// update windows
InvalidateWindowClassesData(WC_TRACE_RESTRICT);
InvalidateWindowClassesData(WC_TRACE_RESTRICT_SLOTS);
InvalidateWindowClassesData(WC_VEHICLE_ORDERS);
}

return CommandCost();
Expand Down
2 changes: 1 addition & 1 deletion src/tracerestrict_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ static int CDECL SlotNameSorter(const TraceRestrictSlot * const *a, const TraceR
/**
* Get a DropDownList of the group list
*/
static DropDownList *GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected)
DropDownList *GetSlotDropDownList(Owner owner, TraceRestrictSlotID slot_id, int &selected)
{
GUIList<const TraceRestrictSlot*> list;

Expand Down
1 change: 1 addition & 0 deletions src/widgets/order_widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum OrderWidgets {
WID_O_COND_COMPARATOR, ///< Choose condition type.
WID_O_COND_VALUE, ///< Choose condition value.
WID_O_COND_CARGO, ///< Choose condition cargo.
WID_O_COND_SLOT, ///< Choose condition slot.
WID_O_SEL_COND_VALUE, ///< Widget for conditional value or conditional cargo type.
WID_O_SEL_TOP_LEFT, ///< #NWID_SELECTION widget for left part of the top row of the 'your train' order window.
WID_O_SEL_TOP_MIDDLE, ///< #NWID_SELECTION widget for middle part of the top row of the 'your train' order window.
Expand Down

0 comments on commit 524e3e5

Please sign in to comment.