OpenTTD Source 20260421-master-gc2fbc6fdeb
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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 "vehicle_func.h"
18#include "timetable_cmd.h"
19#include "timetable.h"
20
21#include "table/strings.h"
22
23#include "safeguards.h"
24
31{
32 /* Calculate the offset in ticks from the current date. */
33 TimerGameTick::Ticks tick_offset = (start_date - TimerGameEconomy::date).base() * Ticks::DAY_TICKS;
34
35 /* Compensate for the current date_fract. */
36 tick_offset -= TimerGameEconomy::date_fract;
37
38 /* Return the current tick plus the offset. */
39 return TimerGameTick::counter + tick_offset;
40}
41
48{
49 /* Calculate the offset in ticks from the current counter tick. */
50 TimerGameTick::Ticks tick_offset = start_tick - TimerGameTick::counter;
51
52 /* Compensate for the current date_fract. */
53 tick_offset += TimerGameEconomy::date_fract;
54
55 /* Return the current date plus the offset in days. */
56 return TimerGameEconomy::date + (tick_offset / Ticks::DAY_TICKS);
57}
58
67static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16_t val, ModifyTimetableFlags mtf, bool timetabled)
68{
69 Order *order = v->GetOrder(order_number);
70 assert(order != nullptr);
71 int total_delta = 0;
72 int timetable_delta = 0;
73
74 switch (mtf) {
75 case MTF_WAIT_TIME:
76 total_delta = val - order->GetWaitTime();
77 timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
78 order->SetWaitTime(val);
79 order->SetWaitTimetabled(timetabled);
80 break;
81
82 case MTF_TRAVEL_TIME:
83 total_delta = val - order->GetTravelTime();
84 timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
85 order->SetTravelTime(val);
86 order->SetTravelTimetabled(timetabled);
87 break;
88
90 order->SetMaxSpeed(val);
91 break;
92
93 default:
94 NOT_REACHED();
95 }
96 v->orders->UpdateTotalDuration(total_delta);
97 v->orders->UpdateTimetableDuration(timetable_delta);
98
99 for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
100 if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
101 switch (mtf) {
102 case MTF_WAIT_TIME:
104 v->current_order.SetWaitTimetabled(timetabled);
105 break;
106
107 case MTF_TRAVEL_TIME:
109 v->current_order.SetTravelTimetabled(timetabled);
110 break;
111
112 case MTF_TRAVEL_SPEED:
114 break;
115
116 default:
117 NOT_REACHED();
118 }
119 }
121 }
122}
123
134CommandCost CmdChangeTimetable(DoCommandFlags flags, VehicleID veh, VehicleOrderID order_number, ModifyTimetableFlags mtf, uint16_t data)
135{
137 if (v == nullptr || !IsCompanyBuildableVehicleType(v) || !v->IsPrimaryVehicle()) return CMD_ERROR;
138
140 if (ret.Failed()) return ret;
141
142 Order *order = v->GetOrder(order_number);
143 if (order == nullptr || order->IsType(OT_IMPLICIT)) return CMD_ERROR;
144
145 if (mtf >= MTF_END) return CMD_ERROR;
146
147 int wait_time = order->GetWaitTime();
148 int travel_time = order->GetTravelTime();
149 int max_speed = order->GetMaxSpeed();
150 switch (mtf) {
151 case MTF_WAIT_TIME:
152 wait_time = data;
153 break;
154
155 case MTF_TRAVEL_TIME:
156 travel_time = data;
157 break;
158
159 case MTF_TRAVEL_SPEED:
160 max_speed = data;
161 if (max_speed == 0) max_speed = UINT16_MAX; // Disable speed limit.
162 break;
163
164 default:
165 NOT_REACHED();
166 }
167
168 if (wait_time != order->GetWaitTime()) {
169 switch (order->GetType()) {
170 case OT_GOTO_STATION:
171 if (order->GetNonStopType().Test(OrderNonStopFlag::GoVia)) return CommandCost(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
172 break;
173
174 case OT_CONDITIONAL:
175 break;
176
177 default: return CommandCost(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
178 }
179 }
180
181 if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
182 if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
183
184 if (flags.Test(DoCommandFlag::Execute)) {
185 switch (mtf) {
186 case MTF_WAIT_TIME:
187 /* Set time if changing the value or confirming an estimated time as timetabled. */
188 if (wait_time != order->GetWaitTime() || (wait_time > 0 && !order->IsWaitTimetabled())) {
189 ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0);
190 }
191 break;
192
193 case MTF_TRAVEL_TIME:
194 /* Set time if changing the value or confirming an estimated time as timetabled. */
195 if (travel_time != order->GetTravelTime() || (travel_time > 0 && !order->IsTravelTimetabled())) {
196 ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0);
197 }
198 break;
199
200 case MTF_TRAVEL_SPEED:
201 if (max_speed != order->GetMaxSpeed()) {
202 ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX);
203 }
204 break;
205
206 default:
207 break;
208 }
209
210 /* Unbunching data is no longer valid for any vehicle in this shared order group. */
211 Vehicle *u = v->FirstShared();
212 for (; u != nullptr; u = u->NextShared()) {
214 }
215 }
216
217 return CommandCost();
218}
219
229CommandCost CmdBulkChangeTimetable(DoCommandFlags flags, VehicleID veh, ModifyTimetableFlags mtf, uint16_t data)
230{
232 if (v == nullptr || !IsCompanyBuildableVehicleType(v) || !v->IsPrimaryVehicle()) return CMD_ERROR;
233
235 if (ret.Failed()) return ret;
236
237 if (mtf >= MTF_END) return CMD_ERROR;
238
239 if (v->GetNumOrders() == 0) return CMD_ERROR;
240
241 if (flags.Test(DoCommandFlag::Execute)) {
242 for (VehicleOrderID order_number = 0; order_number < v->GetNumOrders(); order_number++) {
243 Order *order = v->GetOrder(order_number);
244 if (order == nullptr || order->IsType(OT_IMPLICIT)) continue;
245
246 Command<Commands::ChangeTimetable>::Do(DoCommandFlag::Execute, v->index, order_number, mtf, data);
247 }
248 }
249
250 return CommandCost();
251}
252
260CommandCost CmdSetVehicleOnTime(DoCommandFlags flags, VehicleID veh, bool apply_to_group)
261{
263 if (v == nullptr || !IsCompanyBuildableVehicleType(v) || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
264
265 /* A vehicle can't be late if its timetable hasn't started.
266 * If we're setting all vehicles in the group, we handle that below. */
267 if (!apply_to_group && !v->vehicle_flags.Test(VehicleFlag::TimetableStarted)) return CommandCost(STR_ERROR_TIMETABLE_NOT_STARTED);
268
270 if (ret.Failed()) return ret;
271
272 if (flags.Test(DoCommandFlag::Execute)) {
273 if (apply_to_group) {
274 TimerGameTick::Ticks most_late = 0;
275 for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
276 /* A vehicle can't be late if its timetable hasn't started. */
278
279 if (u->lateness_counter > most_late) {
280 most_late = u->lateness_counter;
281 }
282
283 /* Unbunching data is no longer valid. */
284 u->ResetDepotUnbunching();
285 }
286 if (most_late > 0) {
287 for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
288 /* A vehicle can't be late if its timetable hasn't started. */
290
291 u->lateness_counter -= most_late;
293 }
294 }
295 } else {
296 v->lateness_counter = 0;
297 /* Unbunching data is no longer valid. */
300 }
301 }
302
303 return CommandCost();
304}
305
311static bool VehicleTimetableSorter(Vehicle * const &a, Vehicle * const &b)
312{
315 int j = (int)b_order - (int)a_order;
316
317 /* Are we currently at an ordered station (un)loading? */
318 bool a_load = a->current_order.IsType(OT_LOADING) && a->current_order.GetNonStopType().Any();
319 bool b_load = b->current_order.IsType(OT_LOADING) && b->current_order.GetNonStopType().Any();
320
321 /* If the current order is not loading at the ordered station, decrease the order index by one since we have
322 * not yet arrived at the station (and thus the timetable entry; still in the travelling of the previous one).
323 * Since the ?_order variables are unsigned the -1 will flow under and place the vehicles going to order #0 at
324 * the begin of the list with vehicles arriving at #0. */
325 if (!a_load) a_order--;
326 if (!b_load) b_order--;
327
328 /* First check the order index that accounted for loading, then just the raw one. */
329 int i = (int)b_order - (int)a_order;
330 if (i != 0) return i < 0;
331 if (j != 0) return j < 0;
332
333 /* Look at the time we spent in this order; the higher, the closer to its destination. */
335 if (i != 0) return i < 0;
336
337 /* If all else is equal, use some unique index to sort it the same way. */
338 return b->unitnumber < a->unitnumber;
339}
340
349CommandCost CmdSetTimetableStart(DoCommandFlags flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick)
350{
351 Vehicle *v = Vehicle::GetIfValid(veh_id);
352 if (v == nullptr || !IsCompanyBuildableVehicleType(v) || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
353
355 if (ret.Failed()) return ret;
356
358
359 TimerGameEconomy::Date start_date = GetDateFromStartTick(start_tick);
360
361 /* Don't let a timetable start at an invalid date. */
362 if (start_date < 0 || start_date > EconomyTime::MAX_DATE) return CMD_ERROR;
363
364 /* Don't let a timetable start more than 15 years into the future... */
366 /* ...or 1 year in the past. */
368
369 /* If trying to distribute start dates over a shared order group, we need to know the total duration. */
370 if (timetable_all && !v->orders->IsCompleteTimetable()) return CommandCost(STR_ERROR_TIMETABLE_INCOMPLETE);
371
372 /* Don't allow invalid start dates for other vehicles in the shared order group. */
373 if (timetable_all && start_date + (total_duration / Ticks::DAY_TICKS) > EconomyTime::MAX_DATE) return CMD_ERROR;
374
375 if (flags.Test(DoCommandFlag::Execute)) {
376 std::vector<Vehicle *> vehs;
377
378 if (timetable_all) {
379 for (Vehicle *w = v->orders->GetFirstSharedVehicle(); w != nullptr; w = w->NextShared()) {
380 vehs.push_back(w);
381 }
382 } else {
383 vehs.push_back(v);
384 }
385
386 int num_vehs = (uint)vehs.size();
387
388 if (num_vehs >= 2) {
389 std::sort(vehs.begin(), vehs.end(), &VehicleTimetableSorter);
390 }
391
392 int idx = 0;
393
394 for (Vehicle *w : vehs) {
395 w->lateness_counter = 0;
396 w->vehicle_flags.Reset(VehicleFlag::TimetableStarted);
397 /* Do multiplication, then division to reduce rounding errors. */
398 w->timetable_start = start_tick + (idx * total_duration / num_vehs);
399
400 /* Unbunching data is no longer valid. */
402
404 ++idx;
405 }
406
407 }
408
409 return CommandCost();
410}
411
412
423CommandCost CmdAutofillTimetable(DoCommandFlags flags, VehicleID veh, bool autofill, bool preserve_wait_time)
424{
426 if (v == nullptr || !IsCompanyBuildableVehicleType(v) || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
427
429 if (ret.Failed()) return ret;
430
431 if (flags.Test(DoCommandFlag::Execute)) {
432 if (autofill) {
433 /* Start autofilling the timetable, which clears the
434 * "timetable has started" bit. Times are not cleared anymore, but are
435 * overwritten when the order is reached now. */
438
439 /* Overwrite waiting times only if they got longer */
440 if (preserve_wait_time) v->vehicle_flags.Set(VehicleFlag::AutofillPreserveWaitTime);
441
442 v->timetable_start = 0;
443 v->lateness_counter = 0;
444 } else {
447 }
448
449 for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
450 if (v2 != v) {
451 /* Stop autofilling; only one vehicle at a time can perform autofill */
452 v2->vehicle_flags.Reset(VehicleFlag::AutofillTimetable);
453 v2->vehicle_flags.Reset(VehicleFlag::AutofillPreserveWaitTime);
454 }
456 }
457 }
458
459 return CommandCost();
460}
461
467void UpdateVehicleTimetable(Vehicle *v, bool travelling)
468{
470
471 v->current_order_time = 0;
472
473 if (v->current_order.IsType(OT_IMPLICIT)) return; // no timetabling of auto orders
474
475 if (v->cur_real_order_index >= v->GetNumOrders()) return;
476 Order *real_current_order = v->GetOrder(v->cur_real_order_index);
477 assert(real_current_order != nullptr);
478
479 VehicleOrderID first_manual_order = 0;
480 for (const Order &o : v->Orders()) {
481 if (!o.IsType(OT_IMPLICIT)) break;
482 ++first_manual_order;
483 }
484
485 bool just_started = false;
486
487 /* This vehicle is arriving at the first destination in the timetable. */
488 if (v->cur_real_order_index == first_manual_order && travelling) {
489 /* If the start date hasn't been set, or it was set automatically when
490 * the vehicle last arrived at the first destination, update it to the
491 * current time. Otherwise set the late counter appropriately to when
492 * the vehicle should have arrived. */
494
495 if (v->timetable_start != 0) {
497 v->timetable_start = 0;
498 }
499
502 }
503
505
507 bool remeasure_wait_time = !real_current_order->IsWaitTimetabled() ||
509
510 if (travelling && remeasure_wait_time) {
511 /* We just finished travelling and want to remeasure the loading time,
512 * so do not apply any restrictions for the loading to finish. */
514 }
515
516 if (just_started) return;
517
518 /* Before modifying waiting times, check whether we want to preserve bigger ones. */
519 if (!real_current_order->IsType(OT_CONDITIONAL) &&
520 (travelling || time_taken > real_current_order->GetWaitTime() || remeasure_wait_time)) {
521 /* Round up to the smallest unit of time commonly shown in the GUI (seconds) to avoid confusion.
522 * Players timetabling in Ticks can adjust later.
523 * For trains/aircraft multiple movement cycles are done in one
524 * tick. This makes it possible to leave the station and process
525 * e.g. a depot order in the same tick, causing it to not fill
526 * the timetable entry like is done for road vehicles/ships.
527 * Thus always make sure at least one tick is used between the
528 * processing of different orders when filling the timetable. */
529 uint time_to_set = CeilDiv(std::max(time_taken, 1), Ticks::TICKS_PER_SECOND) * Ticks::TICKS_PER_SECOND;
530
531 if (travelling && (autofilling || !real_current_order->IsTravelTimetabled())) {
532 ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_TRAVEL_TIME, autofilling);
533 } else if (!travelling && (autofilling || !real_current_order->IsWaitTimetabled())) {
534 ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_WAIT_TIME, autofilling);
535 }
536 }
537
538 if (v->cur_real_order_index == first_manual_order && travelling) {
539 /* If we just started we would have returned earlier and have not reached
540 * this code. So obviously, we have completed our round: So turn autofill
541 * off again. */
544 }
545
546 if (autofilling) return;
547
548 TimerGameTick::Ticks timetabled = travelling ? real_current_order->GetTimetabledTravel() :
549 real_current_order->GetTimetabledWait();
550
551 /* Vehicles will wait at stations if they arrive early even if they are not
552 * timetabled to wait there, so make sure the lateness counter is updated
553 * when this happens. */
554 if (timetabled == 0 && (travelling || v->lateness_counter >= 0)) return;
555
556 v->lateness_counter -= (timetabled - time_taken);
557
558 /* When we are more late than this timetabled bit takes we (somewhat expensively)
559 * check how many ticks the (fully filled) timetable has. If a timetable cycle is
560 * shorter than the amount of ticks we are late we reduce the lateness by the
561 * length of a full cycle till lateness is less than the length of a timetable
562 * cycle. When the timetable isn't fully filled the cycle will be Ticks::INVALID_TICKS. */
563 if (v->lateness_counter > timetabled) {
565 if (cycle != Ticks::INVALID_TICKS && v->lateness_counter > cycle) {
566 v->lateness_counter %= cycle;
567 }
568 }
569
570 for (v = v->FirstShared(); v != nullptr; v = v->NextShared()) {
572 }
573}
@ AutofillTimetable
Whether the vehicle should fill in the timetable automatically.
@ TimetableStarted
Whether the vehicle has started running on the timetable yet.
@ AutofillPreserveWaitTime
Whether non-destructive auto-fill should preserve waiting times.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
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
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)
StrongType::Typedef< int32_t, DateTag< struct Economy >, StrongType::Compare, StrongType::Integer > Date
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
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.
@ GoVia
The vehicle will stop at any station it passes except the destination, aka via.
Definition order_type.h:89
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related).
Definition order_type.h:18
ModifyTimetableFlags
Enumeration for the data to set in CmdChangeTimetable.
Definition order_type.h:187
@ MTF_TRAVEL_TIME
Set travel time.
Definition order_type.h:189
@ MTF_WAIT_TIME
Set wait time.
Definition order_type.h:188
@ MTF_TRAVEL_SPEED
Set max travel speed.
Definition order_type.h:190
A number of safeguards to prevent using unsafe methods.
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.
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
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.
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
VehicleType type
Type of vehicle.
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:559
Vehicle * GetFirstSharedVehicle() const
Get the first vehicle of this vehicle chain.
Definition order_base.h:511
void UpdateTimetableDuration(TimerGameTick::Ticks delta)
Must be called if an order's timetable is changed to update internal book keeping.
Definition order_base.h:553
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:535
If you change this, keep in mind that it is also saved in 2 other places:
Definition order_base.h:34
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:288
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:307
void SetTravelTimetabled(bool timetabled)
Set if the travel time is explicitly timetabled (unless the order is conditional).
Definition order_base.h:319
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
uint16_t GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not).
Definition order_base.h:294
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:73
void SetWaitTime(uint16_t time)
Set the time in ticks to wait at the destination.
Definition order_base.h:325
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition order_base.h:271
void SetTravelTime(uint16_t time)
Set the time in ticks to take for travelling to the destination.
Definition order_base.h:331
void SetWaitTimetabled(bool timetabled)
Set if the wait time is explicitly timetabled (unless the order is conditional).
Definition order_base.h:313
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition order_base.h:277
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:283
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:300
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition order_base.h:158
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:338
static Vehicle * GetIfValid(auto 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 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:18
CommandCost CmdSetVehicleOnTime(DoCommandFlags flags, VehicleID veh, bool apply_to_group)
Clear the lateness counter to make the vehicle on time.
CommandCost CmdAutofillTimetable(DoCommandFlags 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...
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
CommandCost CmdSetTimetableStart(DoCommandFlags flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick)
Set the start date of the timetable.
static bool VehicleTimetableSorter(Vehicle *const &a, Vehicle *const &b)
Order vehicles based on their timetable.
CommandCost CmdBulkChangeTimetable(DoCommandFlags flags, VehicleID veh, ModifyTimetableFlags mtf, uint16_t data)
Change timetable data of all orders of a vehicle.
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16_t val, ModifyTimetableFlags mtf, bool timetabled)
Change/update a particular timetable entry.
CommandCost CmdChangeTimetable(DoCommandFlags flags, VehicleID veh, VehicleOrderID order_number, ModifyTimetableFlags mtf, uint16_t data)
Change timetable data of an order.
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.
Command definitions related to timetables.
Base class for all vehicles.
Functions related to vehicles.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
@ VEH_AIRCRAFT
Aircraft vehicle type.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting).
Definition window.cpp:3200
Window functions not directly related to making/drawing windows.
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers: