OpenTTD Source 20241222-master-gc72542431a
timetable_cmd.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "command_func.h"
12#include "company_func.h"
15#include "window_func.h"
16#include "vehicle_base.h"
17#include "timetable_cmd.h"
18#include "timetable.h"
19
20#include "table/strings.h"
21
22#include "safeguards.h"
23
29TimerGameTick::TickCounter GetStartTickFromDate(TimerGameEconomy::Date start_date)
30{
31 /* Calculate the offset in ticks from the current date. */
32 TimerGameTick::Ticks tick_offset = (start_date - TimerGameEconomy::date).base() * Ticks::DAY_TICKS;
33
34 /* Compensate for the current date_fract. */
35 tick_offset -= TimerGameEconomy::date_fract;
36
37 /* Return the current tick plus the offset. */
38 return TimerGameTick::counter + tick_offset;
39}
40
46TimerGameEconomy::Date GetDateFromStartTick(TimerGameTick::TickCounter start_tick)
47{
48 /* Calculate the offset in ticks from the current counter tick. */
49 TimerGameTick::Ticks tick_offset = start_tick - TimerGameTick::counter;
50
51 /* Compensate for the current date_fract. */
52 tick_offset += TimerGameEconomy::date_fract;
53
54 /* Return the current date plus the offset in days. */
55 return TimerGameEconomy::date + (tick_offset / Ticks::DAY_TICKS);
56}
57
66static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16_t val, ModifyTimetableFlags mtf, bool timetabled)
67{
68 Order *order = v->GetOrder(order_number);
69 assert(order != nullptr);
70 int total_delta = 0;
71 int timetable_delta = 0;
72
73 switch (mtf) {
74 case MTF_WAIT_TIME:
75 total_delta = val - order->GetWaitTime();
76 timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
77 order->SetWaitTime(val);
78 order->SetWaitTimetabled(timetabled);
79 break;
80
81 case MTF_TRAVEL_TIME:
82 total_delta = val - order->GetTravelTime();
83 timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
84 order->SetTravelTime(val);
85 order->SetTravelTimetabled(timetabled);
86 break;
87
89 order->SetMaxSpeed(val);
90 break;
91
92 default:
93 NOT_REACHED();
94 }
95 v->orders->UpdateTotalDuration(total_delta);
96 v->orders->UpdateTimetableDuration(timetable_delta);
97
98 for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
99 if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
100 switch (mtf) {
101 case MTF_WAIT_TIME:
103 v->current_order.SetWaitTimetabled(timetabled);
104 break;
105
106 case MTF_TRAVEL_TIME:
108 v->current_order.SetTravelTimetabled(timetabled);
109 break;
110
111 case MTF_TRAVEL_SPEED:
113 break;
114
115 default:
116 NOT_REACHED();
117 }
118 }
120 }
121}
122
134{
136 if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
137
139 if (ret.Failed()) return ret;
140
141 Order *order = v->GetOrder(order_number);
142 if (order == nullptr || order->IsType(OT_IMPLICIT)) return CMD_ERROR;
143
144 if (mtf >= MTF_END) return CMD_ERROR;
145
146 int wait_time = order->GetWaitTime();
147 int travel_time = order->GetTravelTime();
148 int max_speed = order->GetMaxSpeed();
149 switch (mtf) {
150 case MTF_WAIT_TIME:
151 wait_time = data;
152 break;
153
154 case MTF_TRAVEL_TIME:
155 travel_time = data;
156 break;
157
158 case MTF_TRAVEL_SPEED:
159 max_speed = data;
160 if (max_speed == 0) max_speed = UINT16_MAX; // Disable speed limit.
161 break;
162
163 default:
164 NOT_REACHED();
165 }
166
167 if (wait_time != order->GetWaitTime()) {
168 switch (order->GetType()) {
169 case OT_GOTO_STATION:
170 if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return CommandCost(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
171 break;
172
173 case OT_CONDITIONAL:
174 break;
175
176 default: return CommandCost(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
177 }
178 }
179
180 if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
181 if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
182
183 if (flags & DC_EXEC) {
184 switch (mtf) {
185 case MTF_WAIT_TIME:
186 /* Set time if changing the value or confirming an estimated time as timetabled. */
187 if (wait_time != order->GetWaitTime() || (wait_time > 0 && !order->IsWaitTimetabled())) {
188 ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0);
189 }
190 break;
191
192 case MTF_TRAVEL_TIME:
193 /* Set time if changing the value or confirming an estimated time as timetabled. */
194 if (travel_time != order->GetTravelTime() || (travel_time > 0 && !order->IsTravelTimetabled())) {
195 ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0);
196 }
197 break;
198
199 case MTF_TRAVEL_SPEED:
200 if (max_speed != order->GetMaxSpeed()) {
201 ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX);
202 }
203 break;
204
205 default:
206 break;
207 }
208
209 /* Unbunching data is no longer valid for any vehicle in this shared order group. */
210 Vehicle *u = v->FirstShared();
211 for (; u != nullptr; u = u->NextShared()) {
213 }
214 }
215
216 return CommandCost();
217}
218
229{
231 if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
232
234 if (ret.Failed()) return ret;
235
236 if (mtf >= MTF_END) return CMD_ERROR;
237
238 if (v->GetNumOrders() == 0) return CMD_ERROR;
239
240 if (flags & DC_EXEC) {
241 for (VehicleOrderID order_number = 0; order_number < v->GetNumOrders(); order_number++) {
242 Order *order = v->GetOrder(order_number);
243 if (order == nullptr || order->IsType(OT_IMPLICIT)) continue;
244
245 Command<CMD_CHANGE_TIMETABLE>::Do(DC_EXEC, v->index, order_number, mtf, data);
246 }
247 }
248
249 return CommandCost();
250}
251
260{
262 if (v == nullptr || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
263
264 /* A vehicle can't be late if its timetable hasn't started.
265 * If we're setting all vehicles in the group, we handle that below. */
266 if (!apply_to_group && !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return CommandCost(STR_ERROR_TIMETABLE_NOT_STARTED);
267
269 if (ret.Failed()) return ret;
270
271 if (flags & DC_EXEC) {
272 if (apply_to_group) {
273 TimerGameTick::Ticks most_late = 0;
274 for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
275 /* A vehicle can't be late if its timetable hasn't started. */
276 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) continue;
277
278 if (u->lateness_counter > most_late) {
279 most_late = u->lateness_counter;
280 }
281
282 /* Unbunching data is no longer valid. */
283 u->ResetDepotUnbunching();
284 }
285 if (most_late > 0) {
286 for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
287 /* A vehicle can't be late if its timetable hasn't started. */
288 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) continue;
289
290 u->lateness_counter -= most_late;
292 }
293 }
294 } else {
295 v->lateness_counter = 0;
296 /* Unbunching data is no longer valid. */
299 }
300 }
301
302 return CommandCost();
303}
304
313static bool VehicleTimetableSorter(Vehicle * const &a, Vehicle * const &b)
314{
317 int j = (int)b_order - (int)a_order;
318
319 /* Are we currently at an ordered station (un)loading? */
320 bool a_load = a->current_order.IsType(OT_LOADING) && a->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
321 bool b_load = b->current_order.IsType(OT_LOADING) && b->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
322
323 /* If the current order is not loading at the ordered station, decrease the order index by one since we have
324 * not yet arrived at the station (and thus the timetable entry; still in the travelling of the previous one).
325 * Since the ?_order variables are unsigned the -1 will flow under and place the vehicles going to order #0 at
326 * the begin of the list with vehicles arriving at #0. */
327 if (!a_load) a_order--;
328 if (!b_load) b_order--;
329
330 /* First check the order index that accounted for loading, then just the raw one. */
331 int i = (int)b_order - (int)a_order;
332 if (i != 0) return i < 0;
333 if (j != 0) return j < 0;
334
335 /* Look at the time we spent in this order; the higher, the closer to its destination. */
337 if (i != 0) return i < 0;
338
339 /* If all else is equal, use some unique index to sort it the same way. */
340 return b->unitnumber < a->unitnumber;
341}
342
352{
353 Vehicle *v = Vehicle::GetIfValid(veh_id);
354 if (v == nullptr || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
355
357 if (ret.Failed()) return ret;
358
360
361 TimerGameEconomy::Date start_date = GetDateFromStartTick(start_tick);
362
363 /* Don't let a timetable start at an invalid date. */
364 if (start_date < 0 || start_date > EconomyTime::MAX_DATE) return CMD_ERROR;
365
366 /* Don't let a timetable start more than 15 years into the future... */
368 /* ...or 1 year in the past. */
370
371 /* If trying to distribute start dates over a shared order group, we need to know the total duration. */
372 if (timetable_all && !v->orders->IsCompleteTimetable()) return CommandCost(STR_ERROR_TIMETABLE_INCOMPLETE);
373
374 /* Don't allow invalid start dates for other vehicles in the shared order group. */
375 if (timetable_all && start_date + (total_duration / Ticks::DAY_TICKS) > EconomyTime::MAX_DATE) return CMD_ERROR;
376
377 if (flags & DC_EXEC) {
378 std::vector<Vehicle *> vehs;
379
380 if (timetable_all) {
381 for (Vehicle *w = v->orders->GetFirstSharedVehicle(); w != nullptr; w = w->NextShared()) {
382 vehs.push_back(w);
383 }
384 } else {
385 vehs.push_back(v);
386 }
387
388 int num_vehs = (uint)vehs.size();
389
390 if (num_vehs >= 2) {
391 std::sort(vehs.begin(), vehs.end(), &VehicleTimetableSorter);
392 }
393
394 int idx = 0;
395
396 for (Vehicle *w : vehs) {
397 w->lateness_counter = 0;
398 ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
399 /* Do multiplication, then division to reduce rounding errors. */
400 w->timetable_start = start_tick + (idx * total_duration / num_vehs);
401
402 /* Unbunching data is no longer valid. */
404
406 ++idx;
407 }
408
409 }
410
411 return CommandCost();
412}
413
414
425CommandCost CmdAutofillTimetable(DoCommandFlag flags, VehicleID veh, bool autofill, bool preserve_wait_time)
426{
428 if (v == nullptr || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
429
431 if (ret.Failed()) return ret;
432
433 if (flags & DC_EXEC) {
434 if (autofill) {
435 /* Start autofilling the timetable, which clears the
436 * "timetable has started" bit. Times are not cleared anymore, but are
437 * overwritten when the order is reached now. */
440
441 /* Overwrite waiting times only if they got longer */
442 if (preserve_wait_time) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
443
444 v->timetable_start = 0;
445 v->lateness_counter = 0;
446 } else {
449 }
450
451 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
452 if (v2 != v) {
453 /* Stop autofilling; only one vehicle at a time can perform autofill */
454 ClrBit(v2->vehicle_flags, VF_AUTOFILL_TIMETABLE);
455 ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
456 }
458 }
459 }
460
461 return CommandCost();
462}
463
469void UpdateVehicleTimetable(Vehicle *v, bool travelling)
470{
472
473 v->current_order_time = 0;
474
475 if (v->current_order.IsType(OT_IMPLICIT)) return; // no timetabling of auto orders
476
477 if (v->cur_real_order_index >= v->GetNumOrders()) return;
478 Order *real_current_order = v->GetOrder(v->cur_real_order_index);
479 assert(real_current_order != nullptr);
480
481 VehicleOrderID first_manual_order = 0;
482 for (Order *o = v->GetFirstOrder(); o != nullptr && o->IsType(OT_IMPLICIT); o = o->next) {
483 ++first_manual_order;
484 }
485
486 bool just_started = false;
487
488 /* This vehicle is arriving at the first destination in the timetable. */
489 if (v->cur_real_order_index == first_manual_order && travelling) {
490 /* If the start date hasn't been set, or it was set automatically when
491 * the vehicle last arrived at the first destination, update it to the
492 * current time. Otherwise set the late counter appropriately to when
493 * the vehicle should have arrived. */
494 just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
495
496 if (v->timetable_start != 0) {
498 v->timetable_start = 0;
499 }
500
503 }
504
505 if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
506
507 bool autofilling = HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
508 bool remeasure_wait_time = !real_current_order->IsWaitTimetabled() ||
509 (autofilling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME));
510
511 if (travelling && remeasure_wait_time) {
512 /* We just finished travelling and want to remeasure the loading time,
513 * so do not apply any restrictions for the loading to finish. */
515 }
516
517 if (just_started) return;
518
519 /* Before modifying waiting times, check whether we want to preserve bigger ones. */
520 if (!real_current_order->IsType(OT_CONDITIONAL) &&
521 (travelling || time_taken > real_current_order->GetWaitTime() || remeasure_wait_time)) {
522 /* Round up to the unit currently shown in the GUI for days and seconds.
523 * Round up to seconds if currently used display style is ticks.
524 * Players timetabling in Ticks can adjust later.
525 * For trains/aircraft multiple movement cycles are done in one
526 * tick. This makes it possible to leave the station and process
527 * e.g. a depot order in the same tick, causing it to not fill
528 * the timetable entry like is done for road vehicles/ships.
529 * Thus always make sure at least one tick is used between the
530 * processing of different orders when filling the timetable. */
531 uint factor = _settings_client.gui.timetable_mode == TimetableMode::Days ? Ticks::DAY_TICKS : Ticks::TICKS_PER_SECOND;
532 uint time_to_set = CeilDiv(std::max(time_taken, 1), factor) * factor;
533
534 if (travelling && (autofilling || !real_current_order->IsTravelTimetabled())) {
535 ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_TRAVEL_TIME, autofilling);
536 } else if (!travelling && (autofilling || !real_current_order->IsWaitTimetabled())) {
537 ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_WAIT_TIME, autofilling);
538 }
539 }
540
541 if (v->cur_real_order_index == first_manual_order && travelling) {
542 /* If we just started we would have returned earlier and have not reached
543 * this code. So obviously, we have completed our round: So turn autofill
544 * off again. */
547 }
548
549 if (autofilling) return;
550
551 TimerGameTick::Ticks timetabled = travelling ? real_current_order->GetTimetabledTravel() :
552 real_current_order->GetTimetabledWait();
553
554 /* Vehicles will wait at stations if they arrive early even if they are not
555 * timetabled to wait there, so make sure the lateness counter is updated
556 * when this happens. */
557 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
558
559 v->lateness_counter -= (timetabled - time_taken);
560
561 /* When we are more late than this timetabled bit takes we (somewhat expensively)
562 * check how many ticks the (fully filled) timetable has. If a timetable cycle is
563 * shorter than the amount of ticks we are late we reduce the lateness by the
564 * length of a full cycle till lateness is less than the length of a timetable
565 * cycle. When the timetable isn't fully filled the cycle will be Ticks::INVALID_TICKS. */
566 if (v->lateness_counter > timetabled) {
568 if (cycle != Ticks::INVALID_TICKS && v->lateness_counter > cycle) {
569 v->lateness_counter %= cycle;
570 }
571 }
572
573 for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
575 }
576}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Common return value for all commands.
bool Failed() const
Did this command fail?
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
static constexpr TimerGameTick::Ticks INVALID_TICKS
Representation of an invalid number of ticks.
static constexpr TimerGameTick::Ticks TICKS_PER_SECOND
Estimation of how many ticks fit in a single second.
static constexpr TimerGame< struct Economy >::Date MAX_DATE
The date of the last day of the max year.
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
static Date date
Current date in days (day counter).
static DateFract date_fract
Fractional part of the day.
uint64_t TickCounter
The type that the tick counter is stored in.
static TickCounter counter
Monotonic counter, in ticks, since start of game.
int32_t Ticks
The type to store ticks in.
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_EXEC
execute the given command
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
Functions related to companies.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition order_type.h:15
@ ONSF_NO_STOP_AT_DESTINATION_STATION
The vehicle will stop at any station it passes except the destination.
Definition order_type.h:75
@ ONSF_STOP_EVERYWHERE
The vehicle will stop at any station it passes and the destination.
Definition order_type.h:73
ModifyTimetableFlags
Enumeration for the data to set in CmdChangeTimetable.
Definition order_type.h:171
@ MTF_TRAVEL_TIME
Set travel time.
Definition order_type.h:173
@ MTF_WAIT_TIME
Set wait time.
Definition order_type.h:172
@ MTF_TRAVEL_SPEED
Set max travel speed.
Definition order_type.h:174
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
Definition of base types and functions in a cross-platform compatible way.
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
TimerGameTick::TickCounter timetable_start
At what tick of TimerGameTick::counter the vehicle should start its timetable.
TimerGameTick::Ticks lateness_counter
How many ticks late (or early if negative) this vehicle is.
uint16_t vehicle_flags
Used for gradual loading and other miscellaneous things (.
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
VehicleType type
Type of vehicle.
GUISettings gui
settings related to the GUI
TimetableMode timetable_mode
Time units for timetables: days, seconds, or ticks.
bool IsCompleteTimetable() const
Checks whether all orders of the list have a filled timetable.
void UpdateTotalDuration(TimerGameTick::Ticks delta)
Must be called if an order's timetable is changed to update internal book keeping.
Definition order_base.h:392
Vehicle * GetFirstSharedVehicle() const
Get the first vehicle of this vehicle chain.
Definition order_base.h:344
void UpdateTimetableDuration(TimerGameTick::Ticks delta)
Must be called if an order's timetable is changed to update internal book keeping.
Definition order_base.h:386
TimerGameTick::Ticks GetTimetableTotalDuration() const
Gets the total duration of the vehicles timetable or Ticks::INVALID_TICKS is the timetable is not com...
Definition order_base.h:368
uint16_t GetTimetabledTravel() const
Get the time in ticks a vehicle should take to reach the destination or 0 if it's not timetabled.
Definition order_base.h:190
bool Equals(const Order &other) const
Does this order have the same type, flags and destination?
uint16_t GetMaxSpeed() const
Get the maxmimum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition order_base.h:201
void SetTravelTimetabled(bool timetabled)
Set if the travel time is explicitly timetabled (unless the order is conditional).
Definition order_base.h:206
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:70
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:192
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:76
void SetWaitTime(uint16_t time)
Set the time in ticks to wait at the destination.
Definition order_base.h:212
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:183
void SetTravelTime(uint16_t time)
Set the time in ticks to take for travelling to the destination.
Definition order_base.h:218
void SetWaitTimetabled(bool timetabled)
Set if the wait time is explicitly timetabled (unless the order is conditional).
Definition order_base.h:204
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition order_base.h:185
uint16_t GetTimetabledWait() const
Get the time in ticks a vehicle should wait at the destination or 0 if it's not timetabled.
Definition order_base.h:188
uint16_t GetTravelTime() const
Get the time in ticks a vehicle will probably take to reach the destination (timetabled or not).
Definition order_base.h:194
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:140
void SetMaxSpeed(uint16_t speed)
Set the maxmimum speed in km-ish/h a vehicle is allowed to reach on the way to the destination.
Definition order_base.h:225
Tindex index
Index of this pool item.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Vehicle data structure.
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Order * GetFirstOrder() const
Get the first order of the vehicles order list.
Order current_order
The current order (+ status, like: loading)
OrderList * orders
Pointer to the order list for this vehicle.
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Owner owner
Which company owns the vehicle?
UnitID unitnumber
unit number, for display purposes only
Definition of the game-economy-timer.
Definition of the tick-based game-timer.
Functions related to time tabling.
static const TimerGameEconomy::Year MAX_TIMETABLE_START_YEARS
The maximum start date offset, in economy years.
Definition timetable.h:17
CommandCost CmdSetVehicleOnTime(DoCommandFlag flags, VehicleID veh, bool apply_to_group)
Clear the lateness counter to make the vehicle on time.
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
static bool VehicleTimetableSorter(Vehicle *const &a, Vehicle *const &b)
Order vehicles based on their timetable.
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16_t val, ModifyTimetableFlags mtf, bool timetabled)
Change/update a particular timetable entry.
CommandCost CmdAutofillTimetable(DoCommandFlag flags, VehicleID veh, bool autofill, bool preserve_wait_time)
Start or stop filling the timetable automatically from the time the vehicle actually takes to complet...
TimerGameTick::TickCounter GetStartTickFromDate(TimerGameEconomy::Date start_date)
Get the TimerGameTick::TickCounter tick of a given date.
TimerGameEconomy::Date GetDateFromStartTick(TimerGameTick::TickCounter start_tick)
Get a date from a given start tick of timetable.
CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick)
Set the start date of the timetable.
CommandCost CmdChangeTimetable(DoCommandFlag flags, VehicleID veh, VehicleOrderID order_number, ModifyTimetableFlags mtf, uint16_t data)
Change timetable data of an order.
CommandCost CmdBulkChangeTimetable(DoCommandFlag flags, VehicleID veh, ModifyTimetableFlags mtf, uint16_t data)
Change timetable data of all orders of a vehicle.
Command definitions related to timetables.
Base class for all vehicles.
@ VF_AUTOFILL_TIMETABLE
Whether the vehicle should fill in the timetable automatically.
@ VF_AUTOFILL_PRES_WAIT_TIME
Whether non-destructive auto-fill should preserve waiting times.
@ VF_TIMETABLE_STARTED
Whether the vehicle has started running on the timetable yet.
@ VEH_AIRCRAFT
Aircraft vehicle type.
uint32_t VehicleID
The type all our vehicle IDs have.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3101
Window functions not directly related to making/drawing windows.
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers: