mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r25377) -Feature: timetable spreading of vehicles by Ctrl+Click when setting a start date
This commit is contained in:
parent
a724a9924b
commit
a2af1f69af
|
@ -146,7 +146,7 @@ struct SetDateWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_SD_SET_DATE:
|
||||
if (this->callback != NULL) this->callback(this->parent, ConvertYMDToDate(this->date.year, this->date.month, this->date.day));
|
||||
if (this->callback != NULL) this->callback(this, ConvertYMDToDate(this->date.year, this->date.month, this->date.day));
|
||||
delete this;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3786,7 +3786,7 @@ STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}This tim
|
|||
STR_TIMETABLE_STATUS_START_AT :{BLACK}This timetable will start at {STRING1}
|
||||
|
||||
STR_TIMETABLE_STARTING_DATE :{BLACK}Start date
|
||||
STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable
|
||||
STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable. Ctrl+Click sets the starting point of this timetable and distributes all vehicles sharing this order evenly based on their relative order, if the order is completely timetabled
|
||||
|
||||
STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time
|
||||
STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "window_func.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "cmd_helper.h"
|
||||
#include "core/sort_func.hpp"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -178,17 +179,61 @@ CommandCost CmdSetVehicleOnTime(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Order vehicles based on their timetable. The vehicles will be sorted in order
|
||||
* they would reach the first station.
|
||||
*
|
||||
* @param ap First Vehicle pointer.
|
||||
* @param bp Second Vehicle pointer.
|
||||
* @return Comparison value.
|
||||
*/
|
||||
static int CDECL VehicleTimetableSorter(Vehicle * const *ap, Vehicle * const *bp)
|
||||
{
|
||||
const Vehicle *a = *ap;
|
||||
const Vehicle *b = *bp;
|
||||
|
||||
VehicleOrderID a_order = a->cur_real_order_index;
|
||||
VehicleOrderID b_order = b->cur_real_order_index;
|
||||
int j = (int)b_order - (int)a_order;
|
||||
|
||||
/* Are we currently at an ordered station (un)loading? */
|
||||
bool a_load = a->current_order.IsType(OT_LOADING) && a->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
|
||||
bool b_load = b->current_order.IsType(OT_LOADING) && b->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
|
||||
|
||||
/* If the current order is not loading at the ordered station, decrease the order index by one since we have
|
||||
* not yet arrived at the station (and thus the timetable entry; still in the travelling of the previous one).
|
||||
* Since the ?_order variables are unsigned the -1 will flow under and place the vehicles going to order #0 at
|
||||
* the begin of the list with vehicles arriving at #0. */
|
||||
if (!a_load) a_order--;
|
||||
if (!b_load) b_order--;
|
||||
|
||||
/* First check the order index that accounted for loading, then just the raw one. */
|
||||
int i = (int)b_order - (int)a_order;
|
||||
if (i != 0) return i;
|
||||
if (j != 0) return j;
|
||||
|
||||
/* Look at the time we spent in this order; the higher, the closer to its destination. */
|
||||
i = b->current_order_time - a->current_order_time;
|
||||
if (i != 0) return i;
|
||||
|
||||
/* If all else is equal, use some unique index to sort it the same way. */
|
||||
return b->unitnumber - a->unitnumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the start date of the timetable.
|
||||
* @param tile Not used.
|
||||
* @param flags Operation to perform.
|
||||
* @param p1 Vehicle id.
|
||||
* @param p2 Various bitstuffed elements
|
||||
* - p2 = (bit 0-19) - Vehicle ID.
|
||||
* - p2 = (bit 20) - Set to 1 to set timetable start for all vehicles sharing this order
|
||||
* @param p2 The timetable start date.
|
||||
* @param text Not used.
|
||||
* @return The error or cost of the operation.
|
||||
*/
|
||||
CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
bool timetable_all = HasBit(p1, 20);
|
||||
Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
|
||||
if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
|
||||
|
||||
|
@ -200,13 +245,39 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
|||
if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR;
|
||||
if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
|
||||
if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR;
|
||||
if (timetable_all && !v->orders.list->IsCompleteTimetable()) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
v->lateness_counter = 0;
|
||||
ClrBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
v->timetable_start = start_date;
|
||||
SmallVector<Vehicle *, 8> vehs;
|
||||
|
||||
if (timetable_all) {
|
||||
for (Vehicle *w = v->orders.list->GetFirstSharedVehicle(); w != NULL; w = w->NextShared()) {
|
||||
*vehs.Append() = w;
|
||||
}
|
||||
} else {
|
||||
*vehs.Append() = v;
|
||||
}
|
||||
|
||||
int total_duration = v->orders.list->GetTimetableTotalDuration();
|
||||
int num_vehs = vehs.Length();
|
||||
|
||||
if (num_vehs >= 2) {
|
||||
QSortT(vehs.Begin(), vehs.Length(), &VehicleTimetableSorter);
|
||||
}
|
||||
|
||||
int base = vehs.FindIndex(v);
|
||||
|
||||
for (Vehicle **viter = vehs.Begin(); viter != vehs.End(); viter++) {
|
||||
int idx = (viter - vehs.Begin()) - base;
|
||||
Vehicle *w = *viter;
|
||||
|
||||
w->lateness_counter = 0;
|
||||
ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
/* Do multiplication, then division to reduce rounding errors. */
|
||||
w->timetable_start = start_date + idx * total_duration / num_vehs / DAY_TICKS;
|
||||
SetWindowDirty(WC_VEHICLE_TIMETABLE, w->index);
|
||||
}
|
||||
|
||||
SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
|
|
|
@ -525,7 +525,7 @@ struct TimetableWindow : Window {
|
|||
}
|
||||
|
||||
case WID_VT_START_DATE: // Change the date that the timetable starts.
|
||||
ShowSetDateWindow(this, v->index, _date, _cur_year, _cur_year + 15, ChangeTimetableStartCallback);
|
||||
ShowSetDateWindow(this, v->index | (v->orders.list->IsCompleteTimetable() && _ctrl_pressed ? 1U << 20 : 0), _date, _cur_year, _cur_year + 15, ChangeTimetableStartCallback);
|
||||
break;
|
||||
|
||||
case WID_VT_CHANGE_TIME: { // "Wait For" button.
|
||||
|
|
Loading…
Reference in New Issue