(svn r12667) -Feature: conditional 'skip/jump' orders.

This commit is contained in:
rubidium 2008-04-12 11:58:19 +00:00
parent 04b9600920
commit ac94b6384b
6 changed files with 463 additions and 37 deletions

View File

@ -2652,8 +2652,8 @@ STR_8800_TRAIN_DEPOT :{WHITE}{TOWN} T
STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First train arrives at {STATION}! STR_8801_CITIZENS_CELEBRATE_FIRST :{BLACK}{BIGFONT}Citizens celebrate . . .{}First train arrives at {STATION}!
STR_8802_DETAILS :{WHITE}{VEHICLE} (Details) STR_8802_DETAILS :{WHITE}{VEHICLE} (Details)
STR_8803_TRAIN_IN_THE_WAY :{WHITE}Train in the way STR_8803_TRAIN_IN_THE_WAY :{WHITE}Train in the way
STR_8804 :{SETX 10}{COMMA}: {STRING3} {STRING2} STR_8804 :{SETX 10}{COMMA}: {STRING4} {STRING2}
STR_8805 :{RIGHTARROW}{SETX 10}{COMMA}: {STRING3} {STRING2} STR_8805 :{RIGHTARROW}{SETX 10}{COMMA}: {STRING4} {STRING2}
STR_ORDER_GO_TO :Go to STR_ORDER_GO_TO :Go to
STR_ORDER_GO_NON_STOP_TO :Go non-stop to STR_ORDER_GO_NON_STOP_TO :Go non-stop to
STR_ORDER_GO_VIA :Go via STR_ORDER_GO_VIA :Go via
@ -2685,7 +2685,7 @@ STR_ORDER_TOOLTIP_FULL_LOAD :{BLACK}Change t
STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Change the unloading behaviour of the highlighted order STR_ORDER_TOOLTIP_UNLOAD :{BLACK}Change the unloading behaviour of the highlighted order
STR_GO_TO_STATION :{STRING} {STATION} {STRING} STR_GO_TO_STATION :{STRING} {STATION} {STRING}
STR_ORDER_GO_TO_DROPDOWN_TOOLTIP :Insert an advanced order STR_ORDER_GO_TO_DROPDOWN_TOOLTIP :{BLACK}Insert an advanced order
STR_ORDER_GO_TO_NEAREST_DEPOT :Go to nearest depot STR_ORDER_GO_TO_NEAREST_DEPOT :Go to nearest depot
STR_ORDER_GO_TO_NEAREST_HANGAR :Go to nearest hangar STR_ORDER_GO_TO_NEAREST_HANGAR :Go to nearest hangar
STR_ORDER_NEAREST_DEPOT :the nearest STR_ORDER_NEAREST_DEPOT :the nearest
@ -2699,7 +2699,29 @@ STR_GO_TO_DEPOT :{STRING} {TOWN}
STR_GO_TO_NEAREST_DEPOT :{STRING} {STRING} {STRING} STR_GO_TO_NEAREST_DEPOT :{STRING} {STRING} {STRING}
STR_GO_TO_HANGAR :{STRING} {STATION} Hangar STR_GO_TO_HANGAR :{STRING} {STATION} Hangar
STR_TIMETABLE_GO_TO :{STRING3} {STRING2} STR_ORDER_CONDITIONAL :Conditional order jump
STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP :{BLACK}Vehicle data to base jumping on
STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP :{BLACK}How to compare the vehicle data to the given value
STR_ORDER_CONDITIONAL_VALUE_TOOLTIP :{BLACK}The value to compare the vehicle data against
STR_ORDER_CONDITIONAL_VALUE_CAPT :{WHITE}Enter value to compare against
STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE :Load percentage
STR_ORDER_CONDITIONAL_RELIABILITY :Reliability
STR_ORDER_CONDITIONAL_MAX_SPEED :Maximum speed
STR_ORDER_CONDITIONAL_AGE :Vehicle age (years)
STR_ORDER_CONDITIONAL_REQUIRES_SERVICE :Requires service
STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS :is equal to
STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS :is not equal to
STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN :is less than
STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS :is less or equal to
STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN :is more than
STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS :is more or equal to
STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE :is true
STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE :is false
STR_CONDITIONAL_VALUE :{SKIP}{BLACK}{COMMA}
STR_CONDITIONAL_NUM :Jump to order {COMMA} when {STRING} {STRING} {COMMA}
STR_CONDITIONAL_TRUE_FALSE :Jump to order {COMMA} when {STRING} {STRING}
STR_TIMETABLE_GO_TO :{STRING4} {STRING2}
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Travel (not timetabled) STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Travel (not timetabled)
STR_TIMETABLE_TRAVEL_FOR :Travel for {STRING1} STR_TIMETABLE_TRAVEL_FOR :Travel for {STRING1}
STR_TIMETABLE_STAY_FOR :and stay for {STRING1} STR_TIMETABLE_STAY_FOR :and stay for {STRING1}

View File

@ -66,7 +66,7 @@ public:
* Get the type of order of this order. * Get the type of order of this order.
* @return the order type. * @return the order type.
*/ */
inline OrderType GetType() const { return (OrderType)GB(this->type, 0, 6); } inline OrderType GetType() const { return (OrderType)GB(this->type, 0, 4); }
/** /**
* 'Free' the order * 'Free' the order
@ -111,6 +111,12 @@ public:
*/ */
void MakeDummy(); void MakeDummy();
/**
* Makes this order an conditional order.
* @param order the order to jump to.
*/
void MakeConditional(VehicleOrderID order);
/** /**
* Free a complete order chain. * Free a complete order chain.
* @note do not use on "current_order" vehicle orders! * @note do not use on "current_order" vehicle orders!
@ -170,6 +176,14 @@ public:
inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 4); } inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 4); }
/** What are we going to do when in the depot. */ /** What are we going to do when in the depot. */
inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 4); } inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 4); }
/** What variable do we have to compare? */
inline OrderConditionVariable GetConditionVariable() const { return (OrderConditionVariable)GB(this->dest, 11, 5); }
/** What is the comparator to use? */
inline OrderConditionComparator GetConditionComparator() const { return (OrderConditionComparator)GB(this->type, 5, 3); }
/** Get the order to skip to. */
inline VehicleOrderID GetConditionSkipToOrder() const { return this->flags; }
/** Get the value to base the skip on. */
inline uint16 GetConditionValue() const { return GB(this->dest, 0, 11); }
/** Set how the consist must be loaded. */ /** Set how the consist must be loaded. */
inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 4, load_type); } inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 4, load_type); }
@ -180,7 +194,15 @@ public:
/** Set the cause to go to the depot. */ /** Set the cause to go to the depot. */
inline void SetDepotOrderType(OrderDepotTypeFlags depot_order_type) { SB(this->flags, 0, 4, depot_order_type); } inline void SetDepotOrderType(OrderDepotTypeFlags depot_order_type) { SB(this->flags, 0, 4, depot_order_type); }
/** Set what we are going to do in the depot. */ /** Set what we are going to do in the depot. */
inline void SetDepotActionType(OrderDepotActionFlags depot_service_type) { SB(this->flags, 4, 4, depot_service_type); } inline void SetDepotActionType(OrderDepotActionFlags depot_service_type) { SB(this->flags, 4, 4, depot_service_type); }
/** Set variable we have to compare. */
inline void SetConditionVariable(OrderConditionVariable condition_variable) { SB(this->dest, 11, 5, condition_variable); }
/** Set the comparator to use. */
inline void SetConditionComparator(OrderConditionComparator condition_comparator) { SB(this->type, 5, 3, condition_comparator); }
/** Get the order to skip to. */
inline void SetConditionSkipToOrder(VehicleOrderID order_id) { this->flags = order_id; }
/** Set the value to base the skip on. */
inline void SetConditionValue(uint16 value) { SB(this->dest, 0, 11, value); }
bool ShouldStopAtStation(const Vehicle *v, StationID station) const; bool ShouldStopAtStation(const Vehicle *v, StationID station) const;

View File

@ -93,6 +93,13 @@ void Order::MakeDummy()
this->flags = 0; this->flags = 0;
} }
void Order::MakeConditional(VehicleOrderID order)
{
this->type = OT_CONDITIONAL;
this->flags = 0;
this->dest = order;
}
void Order::SetRefit(CargoID cargo, byte subtype) void Order::SetRefit(CargoID cargo, byte subtype)
{ {
this->refit_cargo = cargo; this->refit_cargo = cargo;
@ -427,6 +434,14 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
break; break;
} }
case OT_CONDITIONAL: {
if (!IsPlayerBuildableVehicleType(v)) return CMD_ERROR;
VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
if (skip_to >= v->num_orders) return CMD_ERROR;
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) return CMD_ERROR;
} break;
default: return CMD_ERROR; default: return CMD_ERROR;
} }
@ -512,6 +527,22 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
InvalidateVehicleOrder(u); InvalidateVehicleOrder(u);
} }
/* As we insert an order, the order to skip to will be 'wrong'. */
VehicleOrderID cur_order_id = 0;
Order *order;
FOR_VEHICLE_ORDERS(v, order) {
if (order->IsType(OT_CONDITIONAL)) {
VehicleOrderID order_id = order->GetConditionSkipToOrder();
if (order_id >= sel_ord) {
order->SetConditionSkipToOrder(order_id + 1);
}
if (order_id == cur_order_id) {
order->SetConditionSkipToOrder((order_id + 1) % v->num_orders);
}
}
cur_order_id++;
}
/* Make sure to rebuild the whole list */ /* Make sure to rebuild the whole list */
RebuildVehicleLists(); RebuildVehicleLists();
} }
@ -625,6 +656,21 @@ CommandCost CmdDeleteOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
InvalidateVehicleOrder(u); InvalidateVehicleOrder(u);
} }
/* As we delete an order, the order to skip to will be 'wrong'. */
VehicleOrderID cur_order_id = 0;
FOR_VEHICLE_ORDERS(v, order) {
if (order->IsType(OT_CONDITIONAL)) {
VehicleOrderID order_id = order->GetConditionSkipToOrder();
if (order_id >= sel_ord) {
order->SetConditionSkipToOrder(max(order_id - 1, 0));
}
if (order_id == cur_order_id) {
order->SetConditionSkipToOrder((order_id + 1) % v->num_orders);
}
}
cur_order_id++;
}
RebuildVehicleLists(); RebuildVehicleLists();
} }
@ -746,6 +792,22 @@ CommandCost CmdMoveOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
InvalidateVehicleOrder(u); InvalidateVehicleOrder(u);
} }
/* As we move an order, the order to skip to will be 'wrong'. */
Order *order;
FOR_VEHICLE_ORDERS(v, order) {
if (order->IsType(OT_CONDITIONAL)) {
VehicleOrderID order_id = order->GetConditionSkipToOrder();
if (order_id == moving_order) {
order_id = target_order;
} else if(order_id > moving_order && order_id <= target_order) {
order_id--;
} else if(order_id < moving_order && order_id >= target_order) {
order_id++;
}
order->SetConditionSkipToOrder(order_id);
}
}
/* Make sure to rebuild the whole list */ /* Make sure to rebuild the whole list */
RebuildVehicleLists(); RebuildVehicleLists();
} }
@ -762,16 +824,17 @@ CommandCost CmdMoveOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
* the order will be inserted before that one * the order will be inserted before that one
* only the first 8 bits used currently (bit 16 - 23) (max 255) * only the first 8 bits used currently (bit 16 - 23) (max 255)
* @param p2 various bitstuffed elements * @param p2 various bitstuffed elements
* - p2 = (bit 0 - 1) - what data to modify (@see ModifyOrderFlags) * - p2 = (bit 0 - 3) - what data to modify (@see ModifyOrderFlags)
* - p2 = (bit 2 - 5) - the data to modify * - p2 = (bit 4 - 15) - the data to modify
*/ */
CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{ {
VehicleOrderID sel_ord = GB(p1, 16, 16); // XXX - automatically truncated to 8 bits. VehicleOrderID sel_ord = GB(p1, 16, 16); // XXX - automatically truncated to 8 bits.
VehicleID veh = GB(p1, 0, 16); VehicleID veh = GB(p1, 0, 16);
ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 2); ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 4);
uint8 data = GB(p2, 2, 4); uint16 data = GB(p2, 4, 11);
if (mof >= MOF_END) return CMD_ERROR;
if (!IsValidVehicleID(veh)) return CMD_ERROR; if (!IsValidVehicleID(veh)) return CMD_ERROR;
Vehicle *v = GetVehicle(veh); Vehicle *v = GetVehicle(veh);
@ -783,22 +846,28 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
Order *order = GetVehicleOrder(v, sel_ord); Order *order = GetVehicleOrder(v, sel_ord);
switch (order->GetType()) { switch (order->GetType()) {
case OT_GOTO_STATION: case OT_GOTO_STATION:
if (mof == MOF_DEPOT_ACTION || GetStation(order->GetDestination())->IsBuoy()) return CMD_ERROR; if (mof == MOF_COND_VARIABLE || mof == MOF_COND_COMPARATOR || mof == MOF_DEPOT_ACTION || mof == MOF_COND_VALUE || GetStation(order->GetDestination())->IsBuoy()) return CMD_ERROR;
break; break;
case OT_GOTO_DEPOT: case OT_GOTO_DEPOT:
if (mof == MOF_UNLOAD || mof == MOF_LOAD) return CMD_ERROR; if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
break; break;
case OT_GOTO_WAYPOINT: case OT_GOTO_WAYPOINT:
if (mof != MOF_NON_STOP) return CMD_ERROR; if (mof != MOF_NON_STOP) return CMD_ERROR;
break; break;
case OT_CONDITIONAL:
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE) return CMD_ERROR;
break;
default: default:
return CMD_ERROR; return CMD_ERROR;
} }
switch (mof) { switch (mof) {
default: NOT_REACHED();
case MOF_NON_STOP: case MOF_NON_STOP:
if (data >= ONSF_END) return CMD_ERROR; if (data >= ONSF_END) return CMD_ERROR;
if (data == order->GetNonStopType()) return CMD_ERROR; if (data == order->GetNonStopType()) return CMD_ERROR;
@ -819,6 +888,36 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
case MOF_DEPOT_ACTION: case MOF_DEPOT_ACTION:
if (data != 0) return CMD_ERROR; if (data != 0) return CMD_ERROR;
break; break;
case MOF_COND_VARIABLE:
if (data >= OCV_END) return CMD_ERROR;
break;
case MOF_COND_COMPARATOR:
if (data >= OCC_END) return CMD_ERROR;
switch (order->GetConditionVariable()) {
case OCV_REQUIRES_SERVICE:
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
break;
default:
if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
break;
}
break;
case MOF_COND_VALUE:
switch (order->GetConditionVariable()) {
case OCV_LOAD_PERCENTAGE:
case OCV_RELIABILITY:
if (data > 100) return CMD_ERROR;
break;
default:
if (data > 2047) return CMD_ERROR;
break;
}
break;
} }
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
@ -846,6 +945,33 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() ^ ODTFB_SERVICE)); order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() ^ ODTFB_SERVICE));
break; break;
case MOF_COND_VARIABLE: {
order->SetConditionVariable((OrderConditionVariable)data);
OrderConditionComparator occ = order->GetConditionComparator();
switch (order->GetConditionVariable()) {
case OCV_REQUIRES_SERVICE:
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
break;
case OCV_LOAD_PERCENTAGE:
case OCV_RELIABILITY:
if (order->GetConditionValue() > 100) order->SetConditionValue(100);
/* FALL THROUGH */
default:
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
break;
}
} break;
case MOF_COND_COMPARATOR:
order->SetConditionComparator((OrderConditionComparator)data);
break;
case MOF_COND_VALUE:
order->SetConditionValue(data);
break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
@ -1416,6 +1542,24 @@ static bool CheckForValidOrders(const Vehicle *v)
return false; return false;
} }
/**
* Compare the variable and value based on the given comparator.
*/
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
{
switch (occ) {
case OCC_EQUALS: return variable == value;
case OCC_NOT_EQUALS: return variable != value;
case OCC_LESS_THAN: return variable < value;
case OCC_LESS_EQUALS: return variable <= value;
case OCC_MORE_THAN: return variable > value;
case OCC_MORE_EQUALS: return variable >= value;
case OCC_IS_TRUE: return variable != 0;
case OCC_IS_FALSE: return variable == 0;
default: NOT_REACHED();
}
}
/** /**
* Handle the orders of a vehicle and determine the next place * Handle the orders of a vehicle and determine the next place
* to go to if needed. * to go to if needed.
@ -1551,6 +1695,27 @@ bool ProcessOrders(Vehicle *v)
v->dest_tile = GetWaypoint(order->GetDestination())->xy; v->dest_tile = GetWaypoint(order->GetDestination())->xy;
break; break;
case OT_CONDITIONAL: {
bool skip_order = false;
OrderConditionComparator occ = order->GetConditionComparator();
uint16 value = order->GetConditionValue();
switch (order->GetConditionVariable()) {
case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16, value); break;
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(), value); break;
case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / 366, value); break;
case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
default: NOT_REACHED();
}
UpdateVehicleTimetable(v, true);
if (skip_order) {
v->cur_order_index = order->GetConditionSkipToOrder();
} else {
v->cur_order_index++;
}
} return false;
default: default:
v->dest_tile = 0; v->dest_tile = 0;
return false; return false;

View File

@ -27,6 +27,8 @@
#include "player_func.h" #include "player_func.h"
#include "newgrf_cargo.h" #include "newgrf_cargo.h"
#include "widgets/dropdown_func.h" #include "widgets/dropdown_func.h"
#include "textbuf_gui.h"
#include "string_func.h"
#include "table/sprites.h" #include "table/sprites.h"
#include "table/strings.h" #include "table/strings.h"
@ -46,13 +48,23 @@ enum OrderWindowWidgets {
ORDER_WIDGET_UNLOAD, ORDER_WIDGET_UNLOAD,
ORDER_WIDGET_REFIT, ORDER_WIDGET_REFIT,
ORDER_WIDGET_SERVICE, ORDER_WIDGET_SERVICE,
ORDER_WIDGET_COND_VARIABLE,
ORDER_WIDGET_COND_COMPARATOR,
ORDER_WIDGET_COND_VALUE,
ORDER_WIDGET_RESIZE_BAR, ORDER_WIDGET_RESIZE_BAR,
ORDER_WIDGET_SHARED_ORDER_LIST, ORDER_WIDGET_SHARED_ORDER_LIST,
ORDER_WIDGET_RESIZE, ORDER_WIDGET_RESIZE,
}; };
/** Under what reason are we using the PlaceObject functionality? */
enum OrderPlaceObjectState {
OPOS_GOTO,
OPOS_CONDITIONAL,
};
struct order_d { struct order_d {
int sel; int sel;
OrderPlaceObjectState goto_type;
}; };
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(order_d)); assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(order_d));
@ -89,7 +101,7 @@ static int GetOrderFromOrderWndPt(Window *w, int y, const Vehicle *v)
* 15 = 14 (w->widget[ORDER_WIDGET_ORDER_LIST].top) + 1 (frame-line) * 15 = 14 (w->widget[ORDER_WIDGET_ORDER_LIST].top) + 1 (frame-line)
* 10 = order text hight * 10 = order text hight
*/ */
int sel = (y - 15) / 10; int sel = (y - w->widget[ORDER_WIDGET_ORDER_LIST].top - 1) / 10;
if ((uint)sel >= w->vscroll.cap) return INVALID_ORDER; if ((uint)sel >= w->vscroll.cap) return INVALID_ORDER;
@ -162,15 +174,42 @@ static const StringID _order_unload_drowdown[] = {
static const StringID _order_goto_dropdown[] = { static const StringID _order_goto_dropdown[] = {
STR_ORDER_GO_TO, STR_ORDER_GO_TO,
STR_ORDER_GO_TO_NEAREST_DEPOT, STR_ORDER_GO_TO_NEAREST_DEPOT,
STR_ORDER_CONDITIONAL,
INVALID_STRING_ID INVALID_STRING_ID
}; };
static const StringID _order_goto_dropdown_aircraft[] = { static const StringID _order_goto_dropdown_aircraft[] = {
STR_ORDER_GO_TO, STR_ORDER_GO_TO,
STR_ORDER_GO_TO_NEAREST_HANGAR, STR_ORDER_GO_TO_NEAREST_HANGAR,
STR_ORDER_CONDITIONAL,
INVALID_STRING_ID INVALID_STRING_ID
}; };
static const StringID _order_conditional_variable[] = {
STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE,
STR_ORDER_CONDITIONAL_RELIABILITY,
STR_ORDER_CONDITIONAL_MAX_SPEED,
STR_ORDER_CONDITIONAL_AGE,
STR_ORDER_CONDITIONAL_REQUIRES_SERVICE,
INVALID_STRING_ID,
};
static const StringID _order_conditional_condition[] = {
STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS,
STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS,
STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN,
STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS,
STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN,
STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS,
STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE,
STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE,
INVALID_STRING_ID,
};
extern uint ConvertSpeedToDisplaySpeed(uint speed);
extern uint ConvertDisplaySpeedToSpeed(uint speed);
static void DrawOrdersWindow(Window *w) static void DrawOrdersWindow(Window *w)
{ {
const Vehicle *v = GetVehicle(w->window_number); const Vehicle *v = GetVehicle(w->window_number);
@ -183,9 +222,11 @@ static void DrawOrdersWindow(Window *w)
if (v->owner == _local_player) { if (v->owner == _local_player) {
/* Set the strings for the dropdown boxes. */ /* Set the strings for the dropdown boxes. */
w->widget[ORDER_WIDGET_NON_STOP].data = _order_non_stop_drowdown[order == NULL ? 0 : order->GetNonStopType()]; w->widget[ORDER_WIDGET_NON_STOP].data = _order_non_stop_drowdown[order == NULL ? 0 : order->GetNonStopType()];
w->widget[ORDER_WIDGET_FULL_LOAD].data = _order_full_load_drowdown[order == NULL ? 0 : order->GetLoadType()]; w->widget[ORDER_WIDGET_FULL_LOAD].data = _order_full_load_drowdown[order == NULL ? 0 : order->GetLoadType()];
w->widget[ORDER_WIDGET_UNLOAD].data = _order_unload_drowdown[order == NULL ? 0 : order->GetUnloadType()]; w->widget[ORDER_WIDGET_UNLOAD].data = _order_unload_drowdown[order == NULL ? 0 : order->GetUnloadType()];
w->widget[ORDER_WIDGET_COND_VARIABLE].data = _order_conditional_variable[order == NULL ? 0 : order->GetConditionVariable()];
w->widget[ORDER_WIDGET_COND_COMPARATOR].data = _order_conditional_condition[order == NULL ? 0 : order->GetConditionComparator()];
/* skip */ /* skip */
w->SetWidgetDisabledState(ORDER_WIDGET_SKIP, v->num_orders <= 1); w->SetWidgetDisabledState(ORDER_WIDGET_SKIP, v->num_orders <= 1);
@ -204,10 +245,13 @@ static void DrawOrdersWindow(Window *w)
w->SetWidgetDisabledState(ORDER_WIDGET_SERVICE, order == NULL); // Refit w->SetWidgetDisabledState(ORDER_WIDGET_SERVICE, order == NULL); // Refit
w->HideWidget(ORDER_WIDGET_REFIT); // Refit w->HideWidget(ORDER_WIDGET_REFIT); // Refit
w->HideWidget(ORDER_WIDGET_SERVICE); // Service w->HideWidget(ORDER_WIDGET_SERVICE); // Service
} else {
w->DisableWidget(ORDER_WIDGET_FULL_LOAD); w->HideWidget(ORDER_WIDGET_COND_VARIABLE);
w->HideWidget(ORDER_WIDGET_COND_COMPARATOR);
w->HideWidget(ORDER_WIDGET_COND_VALUE);
} }
w->ShowWidget(ORDER_WIDGET_NON_STOP);
w->ShowWidget(ORDER_WIDGET_UNLOAD); w->ShowWidget(ORDER_WIDGET_UNLOAD);
w->ShowWidget(ORDER_WIDGET_FULL_LOAD); w->ShowWidget(ORDER_WIDGET_FULL_LOAD);
@ -232,6 +276,22 @@ static void DrawOrdersWindow(Window *w)
w->ShowWidget(ORDER_WIDGET_SERVICE); w->ShowWidget(ORDER_WIDGET_SERVICE);
break; break;
case OT_CONDITIONAL: {
w->HideWidget(ORDER_WIDGET_NON_STOP);
w->HideWidget(ORDER_WIDGET_UNLOAD);
w->HideWidget(ORDER_WIDGET_FULL_LOAD);
w->ShowWidget(ORDER_WIDGET_COND_VARIABLE);
w->ShowWidget(ORDER_WIDGET_COND_COMPARATOR);
w->ShowWidget(ORDER_WIDGET_COND_VALUE);
OrderConditionVariable ocv = order->GetConditionVariable();
w->SetWidgetDisabledState(ORDER_WIDGET_COND_VALUE, ocv == OCV_REQUIRES_SERVICE);
uint value = order->GetConditionValue();
if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
SetDParam(1, value);
} break;
default: // every other orders default: // every other orders
w->DisableWidget(ORDER_WIDGET_NON_STOP); w->DisableWidget(ORDER_WIDGET_NON_STOP);
w->DisableWidget(ORDER_WIDGET_FULL_LOAD); w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
@ -249,7 +309,7 @@ static void DrawOrdersWindow(Window *w)
StringID str; StringID str;
while (order != NULL) { while (order != NULL) {
str = (v->cur_order_index == i) ? STR_8805 : STR_8804; str = (v->cur_order_index == i) ? STR_8805 : STR_8804;
SetDParam(5, STR_EMPTY); SetDParam(6, STR_EMPTY);
if (i - w->vscroll.pos < w->vscroll.cap) { if (i - w->vscroll.pos < w->vscroll.cap) {
switch (order->GetType()) { switch (order->GetType()) {
@ -302,8 +362,8 @@ static void DrawOrdersWindow(Window *w)
} }
if (order->IsRefit()) { if (order->IsRefit()) {
SetDParam(5, STR_REFIT_ORDER); SetDParam(6, STR_REFIT_ORDER);
SetDParam(6, GetCargo(order->GetRefitCargo())->name); SetDParam(7, GetCargo(order->GetRefitCargo())->name);
} }
break; break;
@ -312,6 +372,18 @@ static void DrawOrdersWindow(Window *w)
SetDParam(2, order->GetDestination()); SetDParam(2, order->GetDestination());
break; break;
case OT_CONDITIONAL: {
OrderConditionComparator occ = order->GetConditionComparator();
SetDParam(1, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_CONDITIONAL_TRUE_FALSE : STR_CONDITIONAL_NUM);
SetDParam(2, order->GetConditionSkipToOrder() + 1);
SetDParam(3, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
SetDParam(4, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
uint value = order->GetConditionValue();
if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
SetDParam(5, value);
} break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
@ -462,6 +534,7 @@ static void OrderClick_Goto(Window *w, const Vehicle *v, int i)
if (w->IsWidgetLowered(ORDER_WIDGET_GOTO)) { if (w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
_place_clicked_vehicle = NULL; _place_clicked_vehicle = NULL;
SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w); SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
WP(w, order_d).goto_type = OPOS_GOTO;
} else { } else {
ResetObjectToPlace(); ResetObjectToPlace();
} }
@ -490,7 +563,7 @@ static void OrderClick_FullLoad(Window *w, const Vehicle *v, int load_type)
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_LOAD | (load_type << 2), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_LOAD | (load_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
} }
/** /**
@ -521,6 +594,20 @@ static void OrderClick_NearestDepot(Window *w, const Vehicle *v, int i)
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER)); DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
} }
/**
* Handle the click on the conditional order button.
*
* @param w current window
* @param v current vehicle
*/
static void OrderClick_Conditional(Window *w, const Vehicle *v, int i)
{
w->InvalidateWidget(ORDER_WIDGET_GOTO);
w->LowerWidget(ORDER_WIDGET_GOTO);
SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
WP(w, order_d).goto_type = OPOS_CONDITIONAL;
}
/** /**
* Handle the click on the unload button. * Handle the click on the unload button.
* *
@ -544,7 +631,7 @@ static void OrderClick_Unload(Window *w, const Vehicle *v, int unload_type)
} }
} }
DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | (unload_type << 2), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | (unload_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
} }
/** /**
@ -566,7 +653,7 @@ static void OrderClick_Nonstop(Window *w, const Vehicle *v, int non_stop)
non_stop = (order->GetNonStopType() + 1) % ONSF_END; non_stop = (order->GetNonStopType() + 1) % ONSF_END;
} }
DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_NON_STOP | non_stop << 2, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_NON_STOP | non_stop << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
} }
/** /**
@ -580,7 +667,7 @@ static void OrderClick_Transfer(Window *w, const Vehicle *v, int i)
VehicleOrderID sel_ord = OrderGetSel(w); VehicleOrderID sel_ord = OrderGetSel(w);
const Order *order = GetVehicleOrder(v, sel_ord); const Order *order = GetVehicleOrder(v, sel_ord);
DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | ((order->GetUnloadType() & ~OUFB_NO_UNLOAD) ^ OUFB_TRANSFER) << 2, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER)); DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | ((order->GetUnloadType() & ~OUFB_NO_UNLOAD) ^ OUFB_TRANSFER) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
} }
/** /**
@ -763,12 +850,50 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
ShowTimetableWindow(v); ShowTimetableWindow(v);
break; break;
case ORDER_WIDGET_COND_VARIABLE:
ShowDropDownMenu(w, _order_conditional_variable, GetVehicleOrder(v, OrderGetSel(w))->GetConditionVariable(), ORDER_WIDGET_COND_VARIABLE, 0, 0);
break;
case ORDER_WIDGET_COND_COMPARATOR: {
const Order *o = GetVehicleOrder(v, OrderGetSel(w));
ShowDropDownMenu(w, _order_conditional_condition, o->GetConditionComparator(), ORDER_WIDGET_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
} break;
case ORDER_WIDGET_COND_VALUE: {
const Order *order = GetVehicleOrder(v, OrderGetSel(w));
uint value = order->GetConditionValue();
if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
SetDParam(0, value);
ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, 100, w, CS_NUMERAL);
} break;
case ORDER_WIDGET_SHARED_ORDER_LIST: case ORDER_WIDGET_SHARED_ORDER_LIST:
ShowVehicleListWindow(v); ShowVehicleListWindow(v);
break; break;
} }
break; break;
case WE_ON_EDIT_TEXT:
if (!StrEmpty(e->we.edittext.str)) {
VehicleOrderID sel = OrderGetSel(w);
uint value = atoi(e->we.edittext.str);
switch (GetVehicleOrder(v, sel)->GetConditionVariable()) {
case OCV_MAX_SPEED:
value = ConvertDisplaySpeedToSpeed(value);
break;
case OCV_RELIABILITY:
case OCV_LOAD_PERCENTAGE:
value = Clamp(value, 0, 100);
default:
break;
}
DoCommandP(v->tile, v->index + (sel << 16), MOF_COND_VALUE | Clamp(value, 0, 2047) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
}
break;
case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
switch (e->we.dropdown.button) { switch (e->we.dropdown.button) {
case ORDER_WIDGET_NON_STOP: case ORDER_WIDGET_NON_STOP:
@ -785,10 +910,24 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
case ORDER_WIDGET_GOTO: case ORDER_WIDGET_GOTO:
switch (e->we.dropdown.index) { switch (e->we.dropdown.index) {
case 0: OrderClick_Goto(w, v, 0); break; case 0:
w->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
OrderClick_Goto(w, v, 0);
break;
case 1: OrderClick_NearestDepot(w, v, 0); break; case 1: OrderClick_NearestDepot(w, v, 0); break;
case 2: OrderClick_Conditional(w, v, 0); break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
break;
case ORDER_WIDGET_COND_VARIABLE:
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), MOF_COND_VARIABLE | e->we.dropdown.index << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
break;
case ORDER_WIDGET_COND_COMPARATOR:
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), MOF_COND_COMPARATOR | e->we.dropdown.index << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
break;
} }
break; break;
@ -827,10 +966,29 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
break; break;
case WE_PLACE_OBJ: case WE_PLACE_OBJ:
OrdersPlaceObj(GetVehicle(w->window_number), e->we.place.tile, w); if (WP(w, order_d).goto_type == OPOS_GOTO) {
OrdersPlaceObj(GetVehicle(w->window_number), e->we.place.tile, w);
}
break; break;
case WE_ABORT_PLACE_OBJ: case WE_ABORT_PLACE_OBJ:
if (WP(w, order_d).goto_type == OPOS_CONDITIONAL) {
WP(w, order_d).goto_type = OPOS_GOTO;
if (_cursor.pos.x >= (w->left + w->widget[ORDER_WIDGET_ORDER_LIST].left) &&
_cursor.pos.y >= (w->top + w->widget[ORDER_WIDGET_ORDER_LIST].top) &&
_cursor.pos.x <= (w->left + w->widget[ORDER_WIDGET_ORDER_LIST].right) &&
_cursor.pos.y <= (w->top + w->widget[ORDER_WIDGET_ORDER_LIST].bottom)) {
int order_id = GetOrderFromOrderWndPt(w, _cursor.pos.y - w->top, v);
if (order_id != INVALID_ORDER) {
Order order;
order.next = NULL;
order.index = 0;
order.MakeConditional(order_id);
DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
}
}
}
w->RaiseWidget(ORDER_WIDGET_GOTO); w->RaiseWidget(ORDER_WIDGET_GOTO);
w->InvalidateWidget(ORDER_WIDGET_GOTO); w->InvalidateWidget(ORDER_WIDGET_GOTO);
break; break;
@ -891,6 +1049,10 @@ static const Widget _orders_train_widgets[] = {
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 124, 247, 76, 87, STR_REFIT, STR_REFIT_TIP}, // ORDER_WIDGET_REFIT { WWT_PUSHTXTBTN, RESIZE_TB, 14, 124, 247, 76, 87, STR_REFIT, STR_REFIT_TIP}, // ORDER_WIDGET_REFIT
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 248, 371, 76, 87, STR_SERVICE, STR_SERVICE_HINT}, // ORDER_WIDGET_SERVICE { WWT_PUSHTXTBTN, RESIZE_TB, 14, 248, 371, 76, 87, STR_SERVICE, STR_SERVICE_HINT}, // ORDER_WIDGET_SERVICE
{ WWT_DROPDOWN, RESIZE_TB, 14, 0, 123, 76, 87, STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP}, // ORDER_WIDGET_COND_VARIABLE
{ WWT_DROPDOWN, RESIZE_TB, 14, 124, 247, 76, 87, STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP}, // ORDER_WIDGET_COND_COMPARATOR
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 248, 371, 76, 87, STR_CONDITIONAL_VALUE, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP}, // ORDER_WIDGET_COND_VALUE
{ WWT_PANEL, RESIZE_RTB, 14, 372, 373, 76, 99, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR { WWT_PANEL, RESIZE_RTB, 14, 372, 373, 76, 99, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR
{ WWT_PUSHIMGBTN, RESIZE_LRTB, 14, 372, 385, 76, 87, SPR_SHARED_ORDERS_ICON, STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST { WWT_PUSHIMGBTN, RESIZE_LRTB, 14, 372, 385, 76, 87, SPR_SHARED_ORDERS_ICON, STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST
@ -924,9 +1086,13 @@ static const Widget _orders_widgets[] = {
{ WWT_TEXTBTN, RESIZE_TB, 14, 248, 359, 88, 99, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, // ORDER_WIDGET_GOTO { WWT_TEXTBTN, RESIZE_TB, 14, 248, 359, 88, 99, STR_8826_GO_TO, STR_8856_INSERT_A_NEW_ORDER_BEFORE}, // ORDER_WIDGET_GOTO
{ WWT_DROPDOWN, RESIZE_TB, 14, 360, 371, 88, 99, STR_EMPTY, STR_ORDER_GO_TO_DROPDOWN_TOOLTIP}, // ORDER_WIDGET_GOTO_DROPDOWN { WWT_DROPDOWN, RESIZE_TB, 14, 360, 371, 88, 99, STR_EMPTY, STR_ORDER_GO_TO_DROPDOWN_TOOLTIP}, // ORDER_WIDGET_GOTO_DROPDOWN
{ WWT_DROPDOWN, RESIZE_TB, 14, 0, 185, 76, 87, STR_NULL, STR_ORDER_TOOLTIP_FULL_LOAD}, // ORDER_WIDGET_FULL_LOAD { WWT_DROPDOWN, RESIZE_TB, 14, 0, 185, 76, 87, STR_NULL, STR_ORDER_TOOLTIP_FULL_LOAD}, // ORDER_WIDGET_FULL_LOAD
{ WWT_DROPDOWN, RESIZE_TB, 14, 186, 372, 76, 87, STR_NULL, STR_ORDER_TOOLTIP_UNLOAD}, // ORDER_WIDGET_UNLOAD { WWT_DROPDOWN, RESIZE_TB, 14, 186, 371, 76, 87, STR_NULL, STR_ORDER_TOOLTIP_UNLOAD}, // ORDER_WIDGET_UNLOAD
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 185, 76, 87, STR_REFIT, STR_REFIT_TIP}, // ORDER_WIDGET_REFIT { WWT_PUSHTXTBTN, RESIZE_TB, 14, 0, 185, 76, 87, STR_REFIT, STR_REFIT_TIP}, // ORDER_WIDGET_REFIT
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 186, 372, 76, 87, STR_SERVICE, STR_SERVICE_HINT}, // ORDER_WIDGET_SERVICE { WWT_PUSHTXTBTN, RESIZE_TB, 14, 186, 371, 76, 87, STR_SERVICE, STR_SERVICE_HINT}, // ORDER_WIDGET_SERVICE
{ WWT_DROPDOWN, RESIZE_TB, 14, 0, 123, 76, 87, STR_NULL, STR_ORDER_CONDITIONAL_VARIABLE_TOOLTIP}, // ORDER_WIDGET_COND_VARIABLE
{ WWT_DROPDOWN, RESIZE_TB, 14, 124, 247, 76, 87, STR_NULL, STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP}, // ORDER_WIDGET_COND_COMPARATOR
{ WWT_PUSHTXTBTN, RESIZE_TB, 14, 248, 371, 76, 87, STR_CONDITIONAL_VALUE, STR_ORDER_CONDITIONAL_VALUE_TOOLTIP}, // ORDER_WIDGET_COND_VALUE
{ WWT_PANEL, RESIZE_RTB, 14, 372, 373, 76, 99, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR { WWT_PANEL, RESIZE_RTB, 14, 372, 373, 76, 99, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR
{ WWT_PUSHIMGBTN, RESIZE_LRTB, 14, 372, 385, 76, 87, SPR_SHARED_ORDERS_ICON, STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST { WWT_PUSHIMGBTN, RESIZE_LRTB, 14, 372, 385, 76, 87, SPR_SHARED_ORDERS_ICON, STR_VEH_WITH_SHARED_ORDERS_LIST_TIP}, // ORDER_WIDGET_SHARED_ORDER_LIST
@ -965,10 +1131,14 @@ static const Widget _other_orders_widgets[] = {
{ WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_REFIT { WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_REFIT
{ WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SERVICE { WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SERVICE
{ WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_COND_VARIABLE
{ WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_COND_COMPARATOR
{ WWT_EMPTY, RESIZE_NONE, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_COND_VALUE
{ WWT_PANEL, RESIZE_RTB, 14, 0, 373, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR { WWT_PANEL, RESIZE_RTB, 14, 0, 373, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR
{ WWT_EMPTY, RESIZE_TB, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SHARED_ORDER_LIST { WWT_EMPTY, RESIZE_TB, 14, 0, 0, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SHARED_ORDER_LIST
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 374, 385, 88, 99, 0x0, STR_RESIZE_BUTTON}, // ORDER_WIDGET_RESIZE { WWT_RESIZEBOX, RESIZE_LRTB, 14, 374, 385, 88, 99, 0x0, STR_RESIZE_BUTTON}, // ORDER_WIDGET_RESIZE
{ WIDGETS_END}, { WIDGETS_END},
}; };

View File

@ -27,6 +27,7 @@ enum OrderType {
OT_LEAVESTATION = 4, OT_LEAVESTATION = 4,
OT_DUMMY = 5, OT_DUMMY = 5,
OT_GOTO_WAYPOINT = 6, OT_GOTO_WAYPOINT = 6,
OT_CONDITIONAL = 7,
OT_END OT_END
}; };
@ -85,14 +86,46 @@ enum OrderDepotActionFlags {
ODATFB_NEAREST_DEPOT = 1 << 1, ///< Send the vehicle to the nearest depot. ODATFB_NEAREST_DEPOT = 1 << 1, ///< Send the vehicle to the nearest depot.
}; };
/**
* Variables (of a vehicle) to 'cause' skipping on.
*/
enum OrderConditionVariable {
OCV_LOAD_PERCENTAGE, ///< Skip based on the amount of load
OCV_RELIABILITY, ///< Skip based on the reliability
OCV_MAX_SPEED, ///< Skip based on the maximum speed
OCV_AGE, ///< Skip based on the age
OCV_REQUIRES_SERVICE, ///< Skip when the vehicle requires service
OCV_END
};
/**
* Comparator for the skip reasoning.
*/
enum OrderConditionComparator {
OCC_EQUALS, ///< Skip if both values are equal
OCC_NOT_EQUALS, ///< Skip if both values are not equal
OCC_LESS_THAN, ///< Skip if the value is less than the limit
OCC_LESS_EQUALS, ///< Skip if the value is less or equal to the limit
OCC_MORE_THAN, ///< Skip if the value is more than the limit
OCC_MORE_EQUALS, ///< Skip if the value is more or equal to the limit
OCC_IS_TRUE, ///< Skip if the variable is true
OCC_IS_FALSE, ///< Skip if the variable is false
OCC_END
};
/** /**
* Enumeration for the data to set in CmdModifyOrder. * Enumeration for the data to set in CmdModifyOrder.
*/ */
enum ModifyOrderFlags { enum ModifyOrderFlags {
MOF_NON_STOP, ///< Passes a OrderNonStopFlags. MOF_NON_STOP, ///< Passes a OrderNonStopFlags.
MOF_UNLOAD, ///< Passes an OrderUnloadType. MOF_UNLOAD, ///< Passes an OrderUnloadType.
MOF_LOAD, ///< Passes an OrderLoadType MOF_LOAD, ///< Passes an OrderLoadType
MOF_DEPOT_ACTION, ///< Toggle the 'service' if needed flag. MOF_DEPOT_ACTION, ///< Toggle the 'service' if needed flag.
MOF_COND_VARIABLE, ///< A conditional variable changes.
MOF_COND_COMPARATOR, ///< A comparator changes.
MOF_COND_VALUE, ///< The value to set the condition to.
MOF_END
}; };

View File

@ -116,7 +116,7 @@ static void DrawTimetableWindow(Window *w)
if (i - w->vscroll.pos >= w->vscroll.cap) break; if (i - w->vscroll.pos >= w->vscroll.cap) break;
if (i % 2 == 0) { if (i % 2 == 0) {
SetDParam(2, STR_EMPTY); SetDParam(5, STR_EMPTY);
switch (order->GetType()) { switch (order->GetType()) {
case OT_DUMMY: case OT_DUMMY:
@ -130,8 +130,8 @@ static void DrawTimetableWindow(Window *w)
SetDParam(3, STR_EMPTY); SetDParam(3, STR_EMPTY);
if (order->wait_time > 0) { if (order->wait_time > 0) {
SetDParam(4, STR_TIMETABLE_STAY_FOR); SetDParam(5, STR_TIMETABLE_STAY_FOR);
SetTimetableParams(5, 6, order->wait_time); SetTimetableParams(6, 7, order->wait_time);
} else { } else {
SetDParam(4, STR_EMPTY); SetDParam(4, STR_EMPTY);
} }
@ -178,6 +178,20 @@ static void DrawTimetableWindow(Window *w)
SetDParam(1, order->GetDestination()); SetDParam(1, order->GetDestination());
break; break;
case OT_CONDITIONAL: {
extern uint ConvertSpeedToDisplaySpeed(uint speed);
OrderConditionComparator occ = order->GetConditionComparator();
SetDParam(0, (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) ? STR_CONDITIONAL_TRUE_FALSE : STR_CONDITIONAL_NUM);
SetDParam(1, order->GetConditionSkipToOrder() + 1);
SetDParam(2, STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + order->GetConditionVariable());
SetDParam(3, STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS + occ);
uint value = order->GetConditionValue();
if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
SetDParam(4, value);
} break;
default: break; default: break;
} }