Add a "leave early" order timetable flag

Re-arrange timetable GUI slightly.
Add an "extra" drop-down item.
pull/73/head
Jonathan G Rennison 6 years ago
parent a5603b539f
commit 5344ec1931

@ -2029,7 +2029,8 @@ static void LoadUnloadVehicle(Vehicle *front)
/* We loaded less cargo than possible for all cargo types and it's not full
* load and we're not supposed to wait any longer: stop loading. */
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !has_full_load_order &&
front->current_order_time >= (uint)max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
(front->current_order_time >= (uint)max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0) ||
front->current_order.GetLeaveType() == OLT_LEAVE_EARLY)) {
SetBit(front->vehicle_flags, VF_STOP_LOADING);
}

@ -4749,6 +4749,13 @@ STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Switch b
STR_TIMETABLE_LOCK_ORDER_TIME_TOOLTIP :{BLACK}Lock/unlock the amount of time for the highlighted order (Ctrl+Click set lock state for all orders).{}When locked the time will not be changed by timetable autofill or automate.
STR_TIMETABLE_LEAVE_EARLY_ORDER :[leave early]
STR_TIMETABLE_LEAVE_NORMAL :Leave as timetabled
STR_TIMETABLE_LEAVE_EARLY :Leave early
STR_TIMETABLE_EXTRA_DROP_DOWN :{BLACK}Extra
STR_TIMETABLE_EXTRA_DROP_DOWN_TOOLTIP :{BLACK}Extra Options{}{}Leave as timetabled: Vehicles wait until their timetabled departure time before leaving (default).{}Leave Early: Vehicles leave as soon as loading/unloading is done, possibly before the timetabled departure time.
STR_TIMETABLE_ARRIVAL_ABBREVIATION :A:
STR_TIMETABLE_DEPARTURE_ABBREVIATION :D:

@ -432,6 +432,15 @@ public:
if (!this->IsType(OT_CONDITIONAL) && fixed != IsWaitFixed()) SB(this->GetXFlagsRef(), 1, 1, fixed ? 1 : 0);
}
/** Get the leave type */
inline OrderLeaveType GetLeaveType() const { return (OrderLeaveType)GB(this->GetXFlags(), 2, 2); }
/** Set the leave type */
inline void SetLeaveType(OrderLeaveType leave_type)
{
if (leave_type != this->GetLeaveType()) SB(this->GetXFlagsRef(), 2, 2, leave_type);
}
/**
* Get the occupancy value
* @return occupancy

@ -893,6 +893,10 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
int edge = DrawString(rtl ? left : middle, rtl ? middle : right, y, STR_ORDER_TEXT, colour);
if (timetable && timetable_wait_time_valid && order->GetLeaveType() == OLT_LEAVE_EARLY) {
edge = DrawString(rtl ? left : edge + 3, rtl ? edge - 3 : right, y, STR_TIMETABLE_LEAVE_EARLY_ORDER, colour);
}
if (timetable && timetable_wait_time_valid && order->IsWaitFixed()) {
Dimension lock_d = GetSpriteSize(SPR_LOCK);
DrawPixelInfo tmp_dpi;

@ -196,6 +196,15 @@ enum OrderDepotAction {
DA_END
};
/**
* When to leave the station/waiting point.
*/
enum OrderLeaveType {
OLT_NORMAL = 0, ///< Leave when timetabled
OLT_LEAVE_EARLY = 1, ///< Leave as soon as possible
OLT_END
};
/**
* Enumeration for the data to set in #CmdChangeTimetable.
*/
@ -204,9 +213,10 @@ enum ModifyTimetableFlags {
MTF_TRAVEL_TIME, ///< Set travel time.
MTF_TRAVEL_SPEED, ///< Set max travel speed.
MTF_SET_WAIT_FIXED,///< Set wait time fixed flag state.
MTF_SET_LEAVE_TYPE,///< Passes an OrderLeaveType.
MTF_END
};
template <> struct EnumPropsT<ModifyTimetableFlags> : MakeEnumPropsT<ModifyTimetableFlags, byte, MTF_WAIT_TIME, MTF_END, MTF_END, 2> {};
template <> struct EnumPropsT<ModifyTimetableFlags> : MakeEnumPropsT<ModifyTimetableFlags, byte, MTF_WAIT_TIME, MTF_END, MTF_END, 3> {};
/** Clone actions. */

@ -80,7 +80,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_SCHEDULED_DISPATCH, XSCF_NULL, 1, 1, "scheduled_dispatch", NULL, NULL, NULL },
{ XSLFI_MORE_TOWN_GROWTH_RATES, XSCF_NULL, 1, 1, "more_town_growth_rates", NULL, NULL, NULL },
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 1, 1, "multiple_docks", NULL, NULL, "DOCK" },
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 2, 2, "timetable_extra", NULL, NULL, "ORDX" },
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 3, 3, "timetable_extra", NULL, NULL, "ORDX" },
{ XSLFI_TRAIN_FLAGS_EXTRA, XSCF_NULL, 1, 1, "train_flags_extra", NULL, NULL, NULL },
{ XSLFI_TRAIN_THROUGH_LOAD, XSCF_NULL, 2, 2, "train_through_load", NULL, NULL, NULL },
{ XSLFI_ORDER_EXTRA_DATA, XSCF_NULL, 1, 1, "order_extra_data", NULL, NULL, NULL },

@ -71,6 +71,10 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
order->SetWaitFixed(val != 0);
break;
case MTF_SET_LEAVE_TYPE:
order->SetLeaveType((OrderLeaveType)val);
break;
default:
NOT_REACHED();
}
@ -113,8 +117,8 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
* @param p1 Various bitstuffed elements
* - p1 = (bit 0-19) - Vehicle with the orders to change.
* - p1 = (bit 20-27) - Order index to modify.
* - p1 = (bit 28-29) - Timetable data to change (@see ModifyTimetableFlags)
* - p1 = (bit 30) - 0 to set timetable wait/travel time, 1 to clear it
* - p1 = (bit 28-30) - Timetable data to change (@see ModifyTimetableFlags)
* - p1 = (bit 31) - 0 to set timetable wait/travel time, 1 to clear it
* @param p2 The amount of time to wait.
* - p2 = (bit 0-15) - The data to modify as specified by p1 bits 28-29.
* 0 to clear times, UINT16_MAX to clear speed limit.
@ -135,15 +139,16 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
Order *order = v->GetOrder(order_number);
if (order == NULL || order->IsType(OT_IMPLICIT)) return CMD_ERROR;
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 3>(p1);
if (mtf >= MTF_END) return CMD_ERROR;
bool clear_field = GB(p1, 30, 1) == 1;
bool clear_field = GB(p1, 31, 1) == 1;
int wait_time = order->GetWaitTime();
int travel_time = order->GetTravelTime();
int max_speed = order->GetMaxSpeed();
bool wait_fixed = order->IsWaitFixed();
OrderLeaveType leave_type = order->GetLeaveType();
switch (mtf) {
case MTF_WAIT_TIME:
wait_time = GB(p2, 0, 16);
@ -164,11 +169,16 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
wait_fixed = GB(p2, 0, 16) != 0;
break;
case MTF_SET_LEAVE_TYPE:
leave_type = (OrderLeaveType)GB(p2, 0, 16);
if (leave_type >= OLT_END) return CMD_ERROR;
break;
default:
NOT_REACHED();
}
if (wait_time != order->GetWaitTime()) {
if (wait_time != order->GetWaitTime() || leave_type != order->GetLeaveType()) {
switch (order->GetType()) {
case OT_GOTO_STATION:
if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
@ -187,6 +197,7 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
if (wait_fixed != order->IsWaitFixed() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
if (leave_type != order->GetLeaveType() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
if (flags & DC_EXEC) {
switch (mtf) {
@ -216,6 +227,12 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
}
break;
case MTF_SET_LEAVE_TYPE:
if (leave_type != order->GetLeaveType()) {
ChangeTimetable(v, order_number, leave_type, MTF_SET_LEAVE_TYPE, true);
}
break;
default:
break;
}
@ -231,8 +248,8 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
* @param p1 Various bitstuffed elements
* - p1 = (bit 0-19) - Vehicle with the orders to change.
* - p1 = (bit 20-27) - unused
* - p1 = (bit 28-29) - Timetable data to change (@see ModifyTimetableFlags)
* - p1 = (bit 30) - 0 to set timetable wait/travel time, 1 to clear it
* - p1 = (bit 28-30) - Timetable data to change (@see ModifyTimetableFlags)
* - p1 = (bit 31) - 0 to set timetable wait/travel time, 1 to clear it
* @param p2 The amount of time to wait.
* - p2 = (bit 0-15) - The data to modify as specified by p1 bits 28-29.
* 0 to clear times, UINT16_MAX to clear speed limit.
@ -249,7 +266,7 @@ CommandCost CmdBulkChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p
CommandCost ret = CheckOwnership(v->owner);
if (ret.Failed()) return ret;
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 3>(p1);
if (mtf >= MTF_END) return CMD_ERROR;
if (v->GetNumOrders() == 0) return CMD_ERROR;

@ -389,6 +389,7 @@ struct TimetableWindow : Window {
this->EnableWidget(WID_VT_ADD_VEH_GROUP);
this->SetWidgetDisabledState(WID_VT_LOCK_ORDER_TIME, !wait_lockable);
this->SetWidgetLoweredState(WID_VT_LOCK_ORDER_TIME, wait_locked);
this->SetWidgetDisabledState(WID_VT_EXTRA, disable || (selected % 2 != 0));
} else {
this->DisableWidget(WID_VT_START_DATE);
this->DisableWidget(WID_VT_CHANGE_TIME);
@ -402,6 +403,7 @@ struct TimetableWindow : Window {
this->DisableWidget(WID_VT_SHARED_ORDER_LIST);
this->DisableWidget(WID_VT_ADD_VEH_GROUP);
this->DisableWidget(WID_VT_LOCK_ORDER_TIME);
this->DisableWidget(WID_VT_EXTRA);
}
this->SetWidgetLoweredState(WID_VT_AUTOFILL, HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE));
@ -673,7 +675,7 @@ struct TimetableWindow : Window {
if (order_number >= v->GetNumOrders()) order_number = 0;
return v->index | (order_number << 20) | (mtf << 28) | (clear ? 1 << 30 : 0);
return v->index | (order_number << 20) | (mtf << 28) | (clear ? 1 << 31 : 0);
}
virtual void OnClick(Point pt, int widget, int click_count)
@ -840,11 +842,41 @@ struct TimetableWindow : Window {
ShowQueryString(STR_EMPTY, STR_GROUP_RENAME_CAPTION, MAX_LENGTH_GROUP_NAME_CHARS, this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS);
break;
}
case WID_VT_EXTRA: {
VehicleOrderID real = (this->sel_index + 1) / 2;
if (real >= this->vehicle->GetNumOrders()) real = 0;
const Order *order = this->vehicle->GetOrder(real);
bool leave_type_disabled = (order == NULL) ||
((!(order->IsType(OT_GOTO_STATION) || (order->IsType(OT_GOTO_DEPOT) && !(order->GetDepotActionType() & ODATFB_HALT))) ||
(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL));
DropDownList *list = new DropDownList();
*list->Append() = new DropDownListStringItem(STR_TIMETABLE_LEAVE_NORMAL, OLT_NORMAL, leave_type_disabled);
*list->Append() = new DropDownListStringItem(STR_TIMETABLE_LEAVE_EARLY, OLT_LEAVE_EARLY, leave_type_disabled);
ShowDropDownList(this, list, order != NULL ? order->GetLeaveType() : -1, WID_VT_EXTRA);
break;
}
}
this->SetDirty();
}
virtual void OnDropdownSelect(int widget, int index) OVERRIDE
{
switch (widget) {
case WID_VT_EXTRA: {
VehicleOrderID order_number = (this->sel_index + 1) / 2;
if (order_number >= this->vehicle->GetNumOrders()) order_number = 0;
uint32 p1 = this->vehicle->index | (order_number << 20) | (MTF_SET_LEAVE_TYPE << 28);
DoCommandP(0, p1, index, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
}
default:
break;
}
}
virtual void OnQueryTextFinished(char *str)
{
if (str == NULL) return;
@ -963,12 +995,13 @@ static const NWidgetPart _nested_timetable_widgets[] = {
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_SPEED), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CLEAR_SPEED, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP),
EndContainer(),
NWidget(NWID_VERTICAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_SCHEDULED_DISPATCH), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_SCHEDULED_DISPATCH, STR_TIMETABLE_SCHEDULED_DISPATCH_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_AUTOMATE), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_AUTOMATE, STR_TIMETABLE_AUTOMATE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_AUTO_SEPARATION), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_AUTO_SEPARATION, STR_TIMETABLE_AUTO_SEPARATION_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_RESET_LATENESS), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_RESET_LATENESS, STR_TIMETABLE_RESET_LATENESS_TOOLTIP),
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VT_EXTRA), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_EXTRA_DROP_DOWN, STR_TIMETABLE_EXTRA_DROP_DOWN_TOOLTIP),
EndContainer(),
NWidget(NWID_VERTICAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_AUTOMATE), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_AUTOMATE, STR_TIMETABLE_AUTOMATE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_SCHEDULED_DISPATCH), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_SCHEDULED_DISPATCH, STR_TIMETABLE_SCHEDULED_DISPATCH_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_RESET_LATENESS), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_RESET_LATENESS, STR_TIMETABLE_RESET_LATENESS_TOOLTIP),
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VT_EXPECTED_SELECTION),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_EXPECTED), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_BLACK_STRING, STR_TIMETABLE_EXPECTED_TOOLTIP),
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 0), SetFill(1, 1), EndContainer(),

@ -2961,7 +2961,7 @@ void Vehicle::HandleLoading(bool mode)
if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
/* Not the first call for this tick, or still loading */
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) {
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || (this->current_order_time < wait_time && this->current_order.GetLeaveType() != OLT_LEAVE_EARLY)) {
if (!mode && this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_ADVANCE_IN_PLATFORM)) this->AdvanceLoadingInStation();
return;
}
@ -2999,7 +2999,7 @@ void Vehicle::HandleWaiting(bool stop_waiting)
case OT_WAITING: {
uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
/* Vehicles holds on until waiting Timetabled time expires. */
if (!stop_waiting && this->current_order_time < wait_time) {
if (!stop_waiting && this->current_order_time < wait_time && this->current_order.GetLeaveType() != OLT_LEAVE_EARLY) {
return;
}

@ -38,6 +38,7 @@ enum VehicleTimetableWidgets {
WID_VT_CLEAR_SPEED, ///< Clear speed limit button.
WID_VT_SCHEDULED_DISPATCH, ///< Scheduled Dispatch button.
WID_VT_LOCK_ORDER_TIME, ///< Lock order time button.
WID_VT_EXTRA, ///< Extra drop down menu.
};
#endif /* WIDGETS_TIMETABLE_WIDGET_H */

Loading…
Cancel
Save