OpenTTD
order_cmd.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "cmd_helper.h"
15 #include "command_func.h"
16 #include "company_func.h"
17 #include "news_func.h"
18 #include "strings_func.h"
19 #include "timetable.h"
20 #include "vehicle_func.h"
21 #include "depot_base.h"
22 #include "core/pool_func.hpp"
23 #include "core/random_func.hpp"
24 #include "aircraft.h"
25 #include "roadveh.h"
26 #include "station_base.h"
27 #include "waypoint_base.h"
28 #include "company_base.h"
29 #include "order_backup.h"
30 #include "cheat_type.h"
31 
32 #include "table/strings.h"
33 
34 #include "safeguards.h"
35 
36 /* DestinationID must be at least as large as every these below, because it can
37  * be any of them
38  */
39 assert_compile(sizeof(DestinationID) >= sizeof(DepotID));
40 assert_compile(sizeof(DestinationID) >= sizeof(StationID));
41 
42 OrderPool _order_pool("Order");
44 OrderListPool _orderlist_pool("OrderList");
46 
47 
49 {
50  if (CleaningPool()) return;
51 
52  /* We can visit oil rigs and buoys that are not our own. They will be shown in
53  * the list of stations. So, we need to invalidate that window if needed. */
54  if (this->IsType(OT_GOTO_STATION) || this->IsType(OT_GOTO_WAYPOINT)) {
55  BaseStation *bs = BaseStation::GetIfValid(this->GetDestination());
56  if (bs != nullptr && bs->owner == OWNER_NONE) InvalidateWindowClassesData(WC_STATION_LIST, 0);
57  }
58 }
59 
65 {
66  this->type = OT_NOTHING;
67  this->flags = 0;
68  this->dest = 0;
69  this->next = nullptr;
70 }
71 
76 void Order::MakeGoToStation(StationID destination)
77 {
78  this->type = OT_GOTO_STATION;
79  this->flags = 0;
80  this->dest = destination;
81 }
82 
92 {
93  this->type = OT_GOTO_DEPOT;
94  this->SetDepotOrderType(order);
95  this->SetDepotActionType(action);
96  this->SetNonStopType(non_stop_type);
97  this->dest = destination;
98  this->SetRefit(cargo);
99 }
100 
105 void Order::MakeGoToWaypoint(StationID destination)
106 {
107  this->type = OT_GOTO_WAYPOINT;
108  this->flags = 0;
109  this->dest = destination;
110 }
111 
116 void Order::MakeLoading(bool ordered)
117 {
118  this->type = OT_LOADING;
119  if (!ordered) this->flags = 0;
120 }
121 
126 {
127  this->type = OT_LEAVESTATION;
128  this->flags = 0;
129 }
130 
135 {
136  this->type = OT_DUMMY;
137  this->flags = 0;
138 }
139 
145 {
146  this->type = OT_CONDITIONAL;
147  this->flags = order;
148  this->dest = 0;
149 }
150 
155 void Order::MakeImplicit(StationID destination)
156 {
157  this->type = OT_IMPLICIT;
158  this->dest = destination;
159 }
160 
167 {
168  this->refit_cargo = cargo;
169 }
170 
176 bool Order::Equals(const Order &other) const
177 {
178  /* In case of go to nearest depot orders we need "only" compare the flags
179  * with the other and not the nearest depot order bit or the actual
180  * destination because those get clear/filled in during the order
181  * evaluation. If we do not do this the order will continuously be seen as
182  * a different order and it will try to find a "nearest depot" every tick. */
183  if ((this->IsType(OT_GOTO_DEPOT) && this->type == other.type) &&
184  ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0 ||
185  (other.GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0)) {
186  return this->GetDepotOrderType() == other.GetDepotOrderType() &&
188  }
189 
190  return this->type == other.type && this->flags == other.flags && this->dest == other.dest;
191 }
192 
199 uint32 Order::Pack() const
200 {
201  return this->dest << 16 | this->flags << 8 | this->type;
202 }
203 
209 uint16 Order::MapOldOrder() const
210 {
211  uint16 order = this->GetType();
212  switch (this->type) {
213  case OT_GOTO_STATION:
214  if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
215  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
217  order |= GB(this->GetDestination(), 0, 8) << 8;
218  break;
219  case OT_GOTO_DEPOT:
220  if (!(this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) SetBit(order, 6);
221  SetBit(order, 7);
222  order |= GB(this->GetDestination(), 0, 8) << 8;
223  break;
224  case OT_LOADING:
225  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
226  break;
227  }
228  return order;
229 }
230 
235 Order::Order(uint32 packed)
236 {
237  this->type = (OrderType)GB(packed, 0, 8);
238  this->flags = GB(packed, 8, 8);
239  this->dest = GB(packed, 16, 16);
240  this->next = nullptr;
241  this->refit_cargo = CT_NO_REFIT;
242  this->wait_time = 0;
243  this->travel_time = 0;
244  this->max_speed = UINT16_MAX;
245 }
246 
252 void InvalidateVehicleOrder(const Vehicle *v, int data)
253 {
255 
256  if (data != 0) {
257  /* Calls SetDirty() too */
260  return;
261  }
262 
265 }
266 
274 void Order::AssignOrder(const Order &other)
275 {
276  this->type = other.type;
277  this->flags = other.flags;
278  this->dest = other.dest;
279 
280  this->refit_cargo = other.refit_cargo;
281 
282  this->wait_time = other.wait_time;
283  this->travel_time = other.travel_time;
284  this->max_speed = other.max_speed;
285 }
286 
293 {
294  this->first = chain;
295  this->first_shared = v;
296 
297  this->num_orders = 0;
298  this->num_manual_orders = 0;
299  this->num_vehicles = 1;
300  this->timetable_duration = 0;
301  this->total_duration = 0;
302 
303  for (Order *o = this->first; o != nullptr; o = o->next) {
304  ++this->num_orders;
305  if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
306  this->timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
307  this->total_duration += o->GetWaitTime() + o->GetTravelTime();
308  }
309 
310  for (Vehicle *u = this->first_shared->PreviousShared(); u != nullptr; u = u->PreviousShared()) {
311  ++this->num_vehicles;
312  this->first_shared = u;
313  }
314 
315  for (const Vehicle *u = v->NextShared(); u != nullptr; u = u->NextShared()) ++this->num_vehicles;
316 }
317 
323 void OrderList::FreeChain(bool keep_orderlist)
324 {
325  Order *next;
326  for (Order *o = this->first; o != nullptr; o = next) {
327  next = o->next;
328  delete o;
329  }
330 
331  if (keep_orderlist) {
332  this->first = nullptr;
333  this->num_orders = 0;
334  this->num_manual_orders = 0;
335  this->timetable_duration = 0;
336  } else {
337  delete this;
338  }
339 }
340 
347 {
348  if (index < 0) return nullptr;
349 
350  Order *order = this->first;
351 
352  while (order != nullptr && index-- > 0) {
353  order = order->next;
354  }
355  return order;
356 }
357 
369 const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops) const
370 {
371  if (hops > this->GetNumOrders() || next == nullptr) return nullptr;
372 
373  if (next->IsType(OT_CONDITIONAL)) {
374  if (next->GetConditionVariable() != OCV_UNCONDITIONALLY) return next;
375 
376  /* We can evaluate trivial conditions right away. They're conceptually
377  * the same as regular order progression. */
378  return this->GetNextDecisionNode(
379  this->GetOrderAt(next->GetConditionSkipToOrder()),
380  hops + 1);
381  }
382 
383  if (next->IsType(OT_GOTO_DEPOT)) {
384  if (next->GetDepotActionType() == ODATFB_HALT) return nullptr;
385  if (next->IsRefit()) return next;
386  }
387 
388  if (!next->CanLoadOrUnload()) {
389  return this->GetNextDecisionNode(this->GetNext(next), hops + 1);
390  }
391 
392  return next;
393 }
394 
404 StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order *first, uint hops) const
405 {
406 
407  const Order *next = first;
408  if (first == nullptr) {
409  next = this->GetOrderAt(v->cur_implicit_order_index);
410  if (next == nullptr) {
411  next = this->GetFirstOrder();
412  if (next == nullptr) return INVALID_STATION;
413  } else {
414  /* GetNext never returns nullptr if there is a valid station in the list.
415  * As the given "next" is already valid and a station in the list, we
416  * don't have to check for nullptr here. */
417  next = this->GetNext(next);
418  assert(next != nullptr);
419  }
420  }
421 
422  do {
423  next = this->GetNextDecisionNode(next, ++hops);
424 
425  /* Resolve possibly nested conditionals by estimation. */
426  while (next != nullptr && next->IsType(OT_CONDITIONAL)) {
427  /* We return both options of conditional orders. */
428  const Order *skip_to = this->GetNextDecisionNode(
429  this->GetOrderAt(next->GetConditionSkipToOrder()), hops);
430  const Order *advance = this->GetNextDecisionNode(
431  this->GetNext(next), hops);
432  if (advance == nullptr || advance == first || skip_to == advance) {
433  next = (skip_to == first) ? nullptr : skip_to;
434  } else if (skip_to == nullptr || skip_to == first) {
435  next = (advance == first) ? nullptr : advance;
436  } else {
437  StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops);
438  StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops);
439  while (!st2.IsEmpty()) st1.Push(st2.Pop());
440  return st1;
441  }
442  ++hops;
443  }
444 
445  /* Don't return a next stop if the vehicle has to unload everything. */
446  if (next == nullptr || ((next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) &&
447  next->GetDestination() == v->last_station_visited &&
448  (next->GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
449  return INVALID_STATION;
450  }
451  } while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);
452 
453  return next->GetDestination();
454 }
455 
461 void OrderList::InsertOrderAt(Order *new_order, int index)
462 {
463  if (this->first == nullptr) {
464  this->first = new_order;
465  } else {
466  if (index == 0) {
467  /* Insert as first or only order */
468  new_order->next = this->first;
469  this->first = new_order;
470  } else if (index >= this->num_orders) {
471  /* index is after the last order, add it to the end */
472  this->GetLastOrder()->next = new_order;
473  } else {
474  /* Put the new order in between */
475  Order *order = this->GetOrderAt(index - 1);
476  new_order->next = order->next;
477  order->next = new_order;
478  }
479  }
480  ++this->num_orders;
481  if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
482  this->timetable_duration += new_order->GetTimetabledWait() + new_order->GetTimetabledTravel();
483  this->total_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
484 
485  /* We can visit oil rigs and buoys that are not our own. They will be shown in
486  * the list of stations. So, we need to invalidate that window if needed. */
487  if (new_order->IsType(OT_GOTO_STATION) || new_order->IsType(OT_GOTO_WAYPOINT)) {
488  BaseStation *bs = BaseStation::Get(new_order->GetDestination());
490  }
491 
492 }
493 
494 
500 {
501  if (index >= this->num_orders) return;
502 
503  Order *to_remove;
504 
505  if (index == 0) {
506  to_remove = this->first;
507  this->first = to_remove->next;
508  } else {
509  Order *prev = GetOrderAt(index - 1);
510  to_remove = prev->next;
511  prev->next = to_remove->next;
512  }
513  --this->num_orders;
514  if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
515  this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
516  this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
517  delete to_remove;
518 }
519 
525 void OrderList::MoveOrder(int from, int to)
526 {
527  if (from >= this->num_orders || to >= this->num_orders || from == to) return;
528 
529  Order *moving_one;
530 
531  /* Take the moving order out of the pointer-chain */
532  if (from == 0) {
533  moving_one = this->first;
534  this->first = moving_one->next;
535  } else {
536  Order *one_before = GetOrderAt(from - 1);
537  moving_one = one_before->next;
538  one_before->next = moving_one->next;
539  }
540 
541  /* Insert the moving_order again in the pointer-chain */
542  if (to == 0) {
543  moving_one->next = this->first;
544  this->first = moving_one;
545  } else {
546  Order *one_before = GetOrderAt(to - 1);
547  moving_one->next = one_before->next;
548  one_before->next = moving_one;
549  }
550 }
551 
558 {
559  --this->num_vehicles;
560  if (v == this->first_shared) this->first_shared = v->NextShared();
561 }
562 
568 {
569  for (const Vehicle *v_shared = this->first_shared; v_shared != nullptr; v_shared = v_shared->NextShared()) {
570  if (v_shared == v) return true;
571  }
572 
573  return false;
574 }
575 
582 {
583  int count = 0;
584  for (const Vehicle *v_shared = v->PreviousShared(); v_shared != nullptr; v_shared = v_shared->PreviousShared()) count++;
585  return count;
586 }
587 
593 {
594  for (Order *o = this->first; o != nullptr; o = o->next) {
595  /* Implicit orders are, by definition, not timetabled. */
596  if (o->IsType(OT_IMPLICIT)) continue;
597  if (!o->IsCompletelyTimetabled()) return false;
598  }
599  return true;
600 }
601 
606 {
607  VehicleOrderID check_num_orders = 0;
608  VehicleOrderID check_num_manual_orders = 0;
609  uint check_num_vehicles = 0;
610  Ticks check_timetable_duration = 0;
611  Ticks check_total_duration = 0;
612 
613  DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
614 
615  for (const Order *o = this->first; o != nullptr; o = o->next) {
616  ++check_num_orders;
617  if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
618  check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
619  check_total_duration += o->GetWaitTime() + o->GetTravelTime();
620  }
621  assert(this->num_orders == check_num_orders);
622  assert(this->num_manual_orders == check_num_manual_orders);
623  assert(this->timetable_duration == check_timetable_duration);
624  assert(this->total_duration == check_total_duration);
625 
626  for (const Vehicle *v = this->first_shared; v != nullptr; v = v->NextShared()) {
627  ++check_num_vehicles;
628  assert(v->orders.list == this);
629  }
630  assert(this->num_vehicles == check_num_vehicles);
631  DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i timetabled, %i total",
632  (uint)this->num_orders, (uint)this->num_manual_orders,
633  this->num_vehicles, this->timetable_duration, this->total_duration);
634 }
635 
643 static inline bool OrderGoesToStation(const Vehicle *v, const Order *o)
644 {
645  return o->IsType(OT_GOTO_STATION) ||
646  (v->type == VEH_AIRCRAFT && o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotActionType() & ODATFB_NEAREST_DEPOT));
647 }
648 
655 static void DeleteOrderWarnings(const Vehicle *v)
656 {
657  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS);
658  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_VOID_ORDER);
659  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY);
660  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_INVALID_ENTRY);
661  DeleteVehicleNews(v->index, STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY);
662 }
663 
670 TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
671 {
672  switch (this->GetType()) {
673  case OT_GOTO_WAYPOINT:
674  case OT_GOTO_STATION:
675  case OT_IMPLICIT:
676  if (airport && v->type == VEH_AIRCRAFT) return Station::Get(this->GetDestination())->airport.tile;
677  return BaseStation::Get(this->GetDestination())->xy;
678 
679  case OT_GOTO_DEPOT:
680  if ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return INVALID_TILE;
681  return (v->type == VEH_AIRCRAFT) ? Station::Get(this->GetDestination())->xy : Depot::Get(this->GetDestination())->xy;
682 
683  default:
684  return INVALID_TILE;
685  }
686 }
687 
697 uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth)
698 {
699  if (cur->IsType(OT_CONDITIONAL)) {
700  if (conditional_depth > v->GetNumOrders()) return 0;
701 
702  conditional_depth++;
703 
704  int dist1 = GetOrderDistance(prev, v->GetOrder(cur->GetConditionSkipToOrder()), v, conditional_depth);
705  int dist2 = GetOrderDistance(prev, cur->next == nullptr ? v->orders.list->GetFirstOrder() : cur->next, v, conditional_depth);
706  return max(dist1, dist2);
707  }
708 
709  TileIndex prev_tile = prev->GetLocation(v, true);
710  TileIndex cur_tile = cur->GetLocation(v, true);
711  if (prev_tile == INVALID_TILE || cur_tile == INVALID_TILE) return 0;
712  return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile);
713 }
714 
728 CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
729 {
730  VehicleID veh = GB(p1, 0, 20);
731  VehicleOrderID sel_ord = GB(p1, 20, 8);
732  Order new_order(p2);
733 
734  Vehicle *v = Vehicle::GetIfValid(veh);
735  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
736 
737  CommandCost ret = CheckOwnership(v->owner);
738  if (ret.Failed()) return ret;
739 
740  /* Check if the inserted order is to the correct destination (owner, type),
741  * and has the correct flags if any */
742  switch (new_order.GetType()) {
743  case OT_GOTO_STATION: {
744  const Station *st = Station::GetIfValid(new_order.GetDestination());
745  if (st == nullptr) return CMD_ERROR;
746 
747  if (st->owner != OWNER_NONE) {
748  CommandCost ret = CheckOwnership(st->owner);
749  if (ret.Failed()) return ret;
750  }
751 
752  if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
753  for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
754  if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED);
755  }
756 
757  /* Non stop only allowed for ground vehicles. */
758  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
759 
760  /* Filter invalid load/unload types. */
761  switch (new_order.GetLoadType()) {
763  default: return CMD_ERROR;
764  }
765  switch (new_order.GetUnloadType()) {
766  case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break;
767  default: return CMD_ERROR;
768  }
769 
770  /* Filter invalid stop locations */
771  switch (new_order.GetStopLocation()) {
773  case OSL_PLATFORM_MIDDLE:
774  if (v->type != VEH_TRAIN) return CMD_ERROR;
775  FALLTHROUGH;
776 
778  break;
779 
780  default:
781  return CMD_ERROR;
782  }
783 
784  break;
785  }
786 
787  case OT_GOTO_DEPOT: {
788  if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) {
789  if (v->type == VEH_AIRCRAFT) {
790  const Station *st = Station::GetIfValid(new_order.GetDestination());
791 
792  if (st == nullptr) return CMD_ERROR;
793 
794  CommandCost ret = CheckOwnership(st->owner);
795  if (ret.Failed()) return ret;
796 
797  if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
798  return CMD_ERROR;
799  }
800  } else {
801  const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
802 
803  if (dp == nullptr) return CMD_ERROR;
804 
805  CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
806  if (ret.Failed()) return ret;
807 
808  switch (v->type) {
809  case VEH_TRAIN:
810  if (!IsRailDepotTile(dp->xy)) return CMD_ERROR;
811  break;
812 
813  case VEH_ROAD:
814  if (!IsRoadDepotTile(dp->xy)) return CMD_ERROR;
815  break;
816 
817  case VEH_SHIP:
818  if (!IsShipDepotTile(dp->xy)) return CMD_ERROR;
819  break;
820 
821  default: return CMD_ERROR;
822  }
823  }
824  }
825 
826  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
827  if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
828  if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
829  if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
830  break;
831  }
832 
833  case OT_GOTO_WAYPOINT: {
834  const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
835  if (wp == nullptr) return CMD_ERROR;
836 
837  switch (v->type) {
838  default: return CMD_ERROR;
839 
840  case VEH_TRAIN: {
841  if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
842 
843  CommandCost ret = CheckOwnership(wp->owner);
844  if (ret.Failed()) return ret;
845  break;
846  }
847 
848  case VEH_SHIP:
849  if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
850  if (wp->owner != OWNER_NONE) {
851  CommandCost ret = CheckOwnership(wp->owner);
852  if (ret.Failed()) return ret;
853  }
854  break;
855  }
856 
857  /* Order flags can be any of the following for waypoints:
858  * [non-stop]
859  * non-stop orders (if any) are only valid for trains */
860  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
861  break;
862  }
863 
864  case OT_CONDITIONAL: {
865  VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
866  if (skip_to != 0 && skip_to >= v->GetNumOrders()) return CMD_ERROR; // Always allow jumping to the first (even when there is no order).
867  if (new_order.GetConditionVariable() >= OCV_END) return CMD_ERROR;
868 
870  if (occ >= OCC_END) return CMD_ERROR;
871  switch (new_order.GetConditionVariable()) {
873  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
874  break;
875 
876  case OCV_UNCONDITIONALLY:
877  if (occ != OCC_EQUALS) return CMD_ERROR;
878  if (new_order.GetConditionValue() != 0) return CMD_ERROR;
879  break;
880 
881  case OCV_LOAD_PERCENTAGE:
882  case OCV_RELIABILITY:
883  if (new_order.GetConditionValue() > 100) return CMD_ERROR;
884  FALLTHROUGH;
885 
886  default:
887  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
888  break;
889  }
890  break;
891  }
892 
893  default: return CMD_ERROR;
894  }
895 
896  if (sel_ord > v->GetNumOrders()) return CMD_ERROR;
897 
898  if (v->GetNumOrders() >= MAX_VEH_ORDER_ID) return_cmd_error(STR_ERROR_TOO_MANY_ORDERS);
899  if (!Order::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
900  if (v->orders.list == nullptr && !OrderList::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
901 
902  if (flags & DC_EXEC) {
903  Order *new_o = new Order();
904  new_o->AssignOrder(new_order);
905  InsertOrder(v, new_o, sel_ord);
906  }
907 
908  return CommandCost();
909 }
910 
917 void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
918 {
919  /* Create new order and link in list */
920  if (v->orders.list == nullptr) {
921  v->orders.list = new OrderList(new_o, v);
922  } else {
923  v->orders.list->InsertOrderAt(new_o, sel_ord);
924  }
925 
926  Vehicle *u = v->FirstShared();
928  for (; u != nullptr; u = u->NextShared()) {
929  assert(v->orders.list == u->orders.list);
930 
931  /* If there is added an order before the current one, we need
932  * to update the selected order. We do not change implicit/real order indices though.
933  * If the new order is between the current implicit order and real order, the implicit order will
934  * later skip the inserted order. */
935  if (sel_ord <= u->cur_real_order_index) {
936  uint cur = u->cur_real_order_index + 1;
937  /* Check if we don't go out of bound */
938  if (cur < u->GetNumOrders()) {
939  u->cur_real_order_index = cur;
940  }
941  }
942  if (sel_ord == u->cur_implicit_order_index && u->IsGroundVehicle()) {
943  /* We are inserting an order just before the current implicit order.
944  * We do not know whether we will reach current implicit or the newly inserted order first.
945  * So, disable creation of implicit orders until we are on track again. */
946  uint16 &gv_flags = u->GetGroundVehicleFlags();
948  }
949  if (sel_ord <= u->cur_implicit_order_index) {
950  uint cur = u->cur_implicit_order_index + 1;
951  /* Check if we don't go out of bound */
952  if (cur < u->GetNumOrders()) {
953  u->cur_implicit_order_index = cur;
954  }
955  }
956  /* Update any possible open window of the vehicle */
957  InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
958  }
959 
960  /* As we insert an order, the order to skip to will be 'wrong'. */
961  VehicleOrderID cur_order_id = 0;
962  Order *order;
963  FOR_VEHICLE_ORDERS(v, order) {
964  if (order->IsType(OT_CONDITIONAL)) {
965  VehicleOrderID order_id = order->GetConditionSkipToOrder();
966  if (order_id >= sel_ord) {
967  order->SetConditionSkipToOrder(order_id + 1);
968  }
969  if (order_id == cur_order_id) {
970  order->SetConditionSkipToOrder((order_id + 1) % v->GetNumOrders());
971  }
972  }
973  cur_order_id++;
974  }
975 
976  /* Make sure to rebuild the whole list */
978 }
979 
986 {
987  if (flags & DC_EXEC) {
988  DeleteVehicleOrders(dst);
991  }
992  return CommandCost();
993 }
994 
1004 CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1005 {
1006  VehicleID veh_id = GB(p1, 0, 20);
1007  VehicleOrderID sel_ord = GB(p2, 0, 8);
1008 
1009  Vehicle *v = Vehicle::GetIfValid(veh_id);
1010 
1011  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1012 
1013  CommandCost ret = CheckOwnership(v->owner);
1014  if (ret.Failed()) return ret;
1015 
1016  /* If we did not select an order, we maybe want to de-clone the orders */
1017  if (sel_ord >= v->GetNumOrders()) return DecloneOrder(v, flags);
1018 
1019  if (v->GetOrder(sel_ord) == nullptr) return CMD_ERROR;
1020 
1021  if (flags & DC_EXEC) DeleteOrder(v, sel_ord);
1022  return CommandCost();
1023 }
1024 
1030 {
1031  assert(v->current_order.IsType(OT_LOADING));
1032  /* NON-stop flag is misused to see if a train is in a station that is
1033  * on his order list or not */
1035  /* When full loading, "cancel" that order so the vehicle doesn't
1036  * stay indefinitely at this station anymore. */
1038 }
1039 
1046 {
1047  v->orders.list->DeleteOrderAt(sel_ord);
1048 
1049  Vehicle *u = v->FirstShared();
1051  for (; u != nullptr; u = u->NextShared()) {
1052  assert(v->orders.list == u->orders.list);
1053 
1054  if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
1056  }
1057 
1058  if (sel_ord < u->cur_real_order_index) {
1059  u->cur_real_order_index--;
1060  } else if (sel_ord == u->cur_real_order_index) {
1061  u->UpdateRealOrderIndex();
1062  }
1063 
1064  if (sel_ord < u->cur_implicit_order_index) {
1066  } else if (sel_ord == u->cur_implicit_order_index) {
1067  /* Make sure the index is valid */
1069 
1070  /* Skip non-implicit orders for the implicit-order-index (e.g. if the current implicit order was deleted */
1071  while (u->cur_implicit_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_implicit_order_index)->IsType(OT_IMPLICIT)) {
1074  }
1075  }
1076 
1077  /* Update any possible open window of the vehicle */
1078  InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
1079  }
1080 
1081  /* As we delete an order, the order to skip to will be 'wrong'. */
1082  VehicleOrderID cur_order_id = 0;
1083  Order *order = nullptr;
1084  FOR_VEHICLE_ORDERS(v, order) {
1085  if (order->IsType(OT_CONDITIONAL)) {
1086  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1087  if (order_id >= sel_ord) {
1088  order_id = max(order_id - 1, 0);
1089  }
1090  if (order_id == cur_order_id) {
1091  order_id = (order_id + 1) % v->GetNumOrders();
1092  }
1093  order->SetConditionSkipToOrder(order_id);
1094  }
1095  cur_order_id++;
1096  }
1097 
1099 }
1100 
1110 CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1111 {
1112  VehicleID veh_id = GB(p1, 0, 20);
1113  VehicleOrderID sel_ord = GB(p2, 0, 8);
1114 
1115  Vehicle *v = Vehicle::GetIfValid(veh_id);
1116 
1117  if (v == nullptr || !v->IsPrimaryVehicle() || sel_ord == v->cur_implicit_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
1118 
1119  CommandCost ret = CheckOwnership(v->owner);
1120  if (ret.Failed()) return ret;
1121 
1122  if (flags & DC_EXEC) {
1123  if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
1124 
1126  v->UpdateRealOrderIndex();
1127 
1129  }
1130 
1131  /* We have an aircraft/ship, they have a mini-schedule, so update them all */
1134 
1135  return CommandCost();
1136 }
1137 
1151 CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1152 {
1153  VehicleID veh = GB(p1, 0, 20);
1154  VehicleOrderID moving_order = GB(p2, 0, 16);
1155  VehicleOrderID target_order = GB(p2, 16, 16);
1156 
1157  Vehicle *v = Vehicle::GetIfValid(veh);
1158  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1159 
1160  CommandCost ret = CheckOwnership(v->owner);
1161  if (ret.Failed()) return ret;
1162 
1163  /* Don't make senseless movements */
1164  if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() ||
1165  moving_order == target_order || v->GetNumOrders() <= 1) return CMD_ERROR;
1166 
1167  Order *moving_one = v->GetOrder(moving_order);
1168  /* Don't move an empty order */
1169  if (moving_one == nullptr) return CMD_ERROR;
1170 
1171  if (flags & DC_EXEC) {
1172  v->orders.list->MoveOrder(moving_order, target_order);
1173 
1174  /* Update shared list */
1175  Vehicle *u = v->FirstShared();
1176 
1178 
1179  for (; u != nullptr; u = u->NextShared()) {
1180  /* Update the current order.
1181  * There are multiple ways to move orders, which result in cur_implicit_order_index
1182  * and cur_real_order_index to not longer make any sense. E.g. moving another
1183  * real order between them.
1184  *
1185  * Basically one could choose to preserve either of them, but not both.
1186  * While both ways are suitable in this or that case from a human point of view, neither
1187  * of them makes really sense.
1188  * However, from an AI point of view, preserving cur_real_order_index is the most
1189  * predictable and transparent behaviour.
1190  *
1191  * With that decision it basically does not matter what we do to cur_implicit_order_index.
1192  * If we change orders between the implicit- and real-index, the implicit orders are mostly likely
1193  * completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well.
1194  * The worst which can happen is that a lot of implicit orders are removed when reaching current_order.
1195  */
1196  if (u->cur_real_order_index == moving_order) {
1197  u->cur_real_order_index = target_order;
1198  } else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) {
1199  u->cur_real_order_index--;
1200  } else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) {
1201  u->cur_real_order_index++;
1202  }
1203 
1204  if (u->cur_implicit_order_index == moving_order) {
1205  u->cur_implicit_order_index = target_order;
1206  } else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) {
1208  } else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
1210  }
1211 
1212  assert(v->orders.list == u->orders.list);
1213  /* Update any possible open window of the vehicle */
1214  InvalidateVehicleOrder(u, moving_order | (target_order << 8));
1215  }
1216 
1217  /* As we move an order, the order to skip to will be 'wrong'. */
1218  Order *order;
1219  FOR_VEHICLE_ORDERS(v, order) {
1220  if (order->IsType(OT_CONDITIONAL)) {
1221  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1222  if (order_id == moving_order) {
1223  order_id = target_order;
1224  } else if (order_id > moving_order && order_id <= target_order) {
1225  order_id--;
1226  } else if (order_id < moving_order && order_id >= target_order) {
1227  order_id++;
1228  }
1229  order->SetConditionSkipToOrder(order_id);
1230  }
1231  }
1232 
1233  /* Make sure to rebuild the whole list */
1235  }
1236 
1237  return CommandCost();
1238 }
1239 
1255 CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1256 {
1257  VehicleOrderID sel_ord = GB(p1, 20, 8);
1258  VehicleID veh = GB(p1, 0, 20);
1259  ModifyOrderFlags mof = Extract<ModifyOrderFlags, 0, 4>(p2);
1260  uint16 data = GB(p2, 4, 11);
1261 
1262  if (mof >= MOF_END) return CMD_ERROR;
1263 
1264  Vehicle *v = Vehicle::GetIfValid(veh);
1265  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1266 
1267  CommandCost ret = CheckOwnership(v->owner);
1268  if (ret.Failed()) return ret;
1269 
1270  /* Is it a valid order? */
1271  if (sel_ord >= v->GetNumOrders()) return CMD_ERROR;
1272 
1273  Order *order = v->GetOrder(sel_ord);
1274  switch (order->GetType()) {
1275  case OT_GOTO_STATION:
1276  if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD) return CMD_ERROR;
1277  break;
1278 
1279  case OT_GOTO_DEPOT:
1280  if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
1281  break;
1282 
1283  case OT_GOTO_WAYPOINT:
1284  if (mof != MOF_NON_STOP) return CMD_ERROR;
1285  break;
1286 
1287  case OT_CONDITIONAL:
1288  if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR;
1289  break;
1290 
1291  default:
1292  return CMD_ERROR;
1293  }
1294 
1295  switch (mof) {
1296  default: NOT_REACHED();
1297 
1298  case MOF_NON_STOP:
1299  if (!v->IsGroundVehicle()) return CMD_ERROR;
1300  if (data >= ONSF_END) return CMD_ERROR;
1301  if (data == order->GetNonStopType()) return CMD_ERROR;
1302  break;
1303 
1304  case MOF_STOP_LOCATION:
1305  if (v->type != VEH_TRAIN) return CMD_ERROR;
1306  if (data >= OSL_END) return CMD_ERROR;
1307  break;
1308 
1309  case MOF_UNLOAD:
1311  if ((data & ~(OUFB_UNLOAD | OUFB_TRANSFER | OUFB_NO_UNLOAD)) != 0) return CMD_ERROR;
1312  /* Unload and no-unload are mutual exclusive and so are transfer and no unload. */
1313  if (data != 0 && ((data & (OUFB_UNLOAD | OUFB_TRANSFER)) != 0) == ((data & OUFB_NO_UNLOAD) != 0)) return CMD_ERROR;
1314  if (data == order->GetUnloadType()) return CMD_ERROR;
1315  break;
1316 
1317  case MOF_LOAD:
1319  if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
1320  if (data == order->GetLoadType()) return CMD_ERROR;
1321  break;
1322 
1323  case MOF_DEPOT_ACTION:
1324  if (data >= DA_END) return CMD_ERROR;
1325  break;
1326 
1327  case MOF_COND_VARIABLE:
1328  if (data >= OCV_END) return CMD_ERROR;
1329  break;
1330 
1331  case MOF_COND_COMPARATOR:
1332  if (data >= OCC_END) return CMD_ERROR;
1333  switch (order->GetConditionVariable()) {
1334  case OCV_UNCONDITIONALLY: return CMD_ERROR;
1335 
1336  case OCV_REQUIRES_SERVICE:
1337  if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
1338  break;
1339 
1340  default:
1341  if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
1342  break;
1343  }
1344  break;
1345 
1346  case MOF_COND_VALUE:
1347  switch (order->GetConditionVariable()) {
1348  case OCV_UNCONDITIONALLY:
1349  case OCV_REQUIRES_SERVICE:
1350  return CMD_ERROR;
1351 
1352  case OCV_LOAD_PERCENTAGE:
1353  case OCV_RELIABILITY:
1354  if (data > 100) return CMD_ERROR;
1355  break;
1356 
1357  default:
1358  if (data > 2047) return CMD_ERROR;
1359  break;
1360  }
1361  break;
1362 
1363  case MOF_COND_DESTINATION:
1364  if (data >= v->GetNumOrders()) return CMD_ERROR;
1365  break;
1366  }
1367 
1368  if (flags & DC_EXEC) {
1369  switch (mof) {
1370  case MOF_NON_STOP:
1371  order->SetNonStopType((OrderNonStopFlags)data);
1373  order->SetRefit(CT_NO_REFIT);
1376  }
1377  break;
1378 
1379  case MOF_STOP_LOCATION:
1380  order->SetStopLocation((OrderStopLocation)data);
1381  break;
1382 
1383  case MOF_UNLOAD:
1384  order->SetUnloadType((OrderUnloadFlags)data);
1385  break;
1386 
1387  case MOF_LOAD:
1388  order->SetLoadType((OrderLoadFlags)data);
1389  if (data & OLFB_NO_LOAD) order->SetRefit(CT_NO_REFIT);
1390  break;
1391 
1392  case MOF_DEPOT_ACTION: {
1393  switch (data) {
1394  case DA_ALWAYS_GO:
1397  break;
1398 
1399  case DA_SERVICE:
1402  order->SetRefit(CT_NO_REFIT);
1403  break;
1404 
1405  case DA_STOP:
1408  order->SetRefit(CT_NO_REFIT);
1409  break;
1410 
1411  default:
1412  NOT_REACHED();
1413  }
1414  break;
1415  }
1416 
1417  case MOF_COND_VARIABLE: {
1419 
1421  switch (order->GetConditionVariable()) {
1422  case OCV_UNCONDITIONALLY:
1424  order->SetConditionValue(0);
1425  break;
1426 
1427  case OCV_REQUIRES_SERVICE:
1428  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
1429  order->SetConditionValue(0);
1430  break;
1431 
1432  case OCV_LOAD_PERCENTAGE:
1433  case OCV_RELIABILITY:
1434  if (order->GetConditionValue() > 100) order->SetConditionValue(100);
1435  FALLTHROUGH;
1436 
1437  default:
1438  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
1439  break;
1440  }
1441  break;
1442  }
1443 
1444  case MOF_COND_COMPARATOR:
1446  break;
1447 
1448  case MOF_COND_VALUE:
1449  order->SetConditionValue(data);
1450  break;
1451 
1452  case MOF_COND_DESTINATION:
1453  order->SetConditionSkipToOrder(data);
1454  break;
1455 
1456  default: NOT_REACHED();
1457  }
1458 
1459  /* Update the windows and full load flags, also for vehicles that share the same order list */
1460  Vehicle *u = v->FirstShared();
1462  for (; u != nullptr; u = u->NextShared()) {
1463  /* Toggle u->current_order "Full load" flag if it changed.
1464  * However, as the same flag is used for depot orders, check
1465  * whether we are not going to a depot as there are three
1466  * cases where the full load flag can be active and only
1467  * one case where the flag is used for depot orders. In the
1468  * other cases for the OrderType the flags are not used,
1469  * so do not care and those orders should not be active
1470  * when this function is called.
1471  */
1472  if (sel_ord == u->cur_real_order_index &&
1473  (u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
1474  u->current_order.GetLoadType() != order->GetLoadType()) {
1475  u->current_order.SetLoadType(order->GetLoadType());
1476  }
1478  }
1479  }
1480 
1481  return CommandCost();
1482 }
1483 
1491 static bool CheckAircraftOrderDistance(const Aircraft *v_new, const Vehicle *v_order, const Order *first)
1492 {
1493  if (first == nullptr || v_new->acache.cached_max_range == 0) return true;
1494 
1495  /* Iterate over all orders to check the distance between all
1496  * 'goto' orders and their respective next order (of any type). */
1497  for (const Order *o = first; o != nullptr; o = o->next) {
1498  switch (o->GetType()) {
1499  case OT_GOTO_STATION:
1500  case OT_GOTO_DEPOT:
1501  case OT_GOTO_WAYPOINT:
1502  /* If we don't have a next order, we've reached the end and must check the first order instead. */
1503  if (GetOrderDistance(o, o->next != nullptr ? o->next : first, v_order) > v_new->acache.cached_max_range_sqr) return false;
1504  break;
1505 
1506  default: break;
1507  }
1508  }
1509 
1510  return true;
1511 }
1512 
1524 CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1525 {
1526  VehicleID veh_src = GB(p2, 0, 20);
1527  VehicleID veh_dst = GB(p1, 0, 20);
1528 
1529  Vehicle *dst = Vehicle::GetIfValid(veh_dst);
1530  if (dst == nullptr || !dst->IsPrimaryVehicle()) return CMD_ERROR;
1531 
1532  CommandCost ret = CheckOwnership(dst->owner);
1533  if (ret.Failed()) return ret;
1534 
1535  switch (GB(p1, 30, 2)) {
1536  case CO_SHARE: {
1537  Vehicle *src = Vehicle::GetIfValid(veh_src);
1538 
1539  /* Sanity checks */
1540  if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1541 
1542  CommandCost ret = CheckOwnership(src->owner);
1543  if (ret.Failed()) return ret;
1544 
1545  /* Trucks can't share orders with busses (and visa versa) */
1546  if (src->type == VEH_ROAD && RoadVehicle::From(src)->IsBus() != RoadVehicle::From(dst)->IsBus()) {
1547  return CMD_ERROR;
1548  }
1549 
1550  /* Is the vehicle already in the shared list? */
1551  if (src->FirstShared() == dst->FirstShared()) return CMD_ERROR;
1552 
1553  const Order *order;
1554 
1555  FOR_VEHICLE_ORDERS(src, order) {
1556  if (!OrderGoesToStation(dst, order)) continue;
1557 
1558  /* Allow copying unreachable destinations if they were already unreachable for the source.
1559  * This is basically to allow cloning / autorenewing / autoreplacing vehicles, while the stations
1560  * are temporarily invalid due to reconstruction. */
1561  const Station *st = Station::Get(order->GetDestination());
1562  if (CanVehicleUseStation(src, st) && !CanVehicleUseStation(dst, st)) {
1563  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1564  }
1565  }
1566 
1567  /* Check for aircraft range limits. */
1568  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1569  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1570  }
1571 
1572  if (src->orders.list == nullptr && !OrderList::CanAllocateItem()) {
1573  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1574  }
1575 
1576  if (flags & DC_EXEC) {
1577  /* If the destination vehicle had a OrderList, destroy it.
1578  * We only reset the order indices, if the new orders are obviously different.
1579  * (We mainly do this to keep the order indices valid and in range.) */
1580  DeleteVehicleOrders(dst, false, dst->GetNumOrders() != src->GetNumOrders());
1581 
1582  dst->orders.list = src->orders.list;
1583 
1584  /* Link this vehicle in the shared-list */
1585  dst->AddToShared(src);
1586 
1589 
1591  }
1592  break;
1593  }
1594 
1595  case CO_COPY: {
1596  Vehicle *src = Vehicle::GetIfValid(veh_src);
1597 
1598  /* Sanity checks */
1599  if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1600 
1601  CommandCost ret = CheckOwnership(src->owner);
1602  if (ret.Failed()) return ret;
1603 
1604  /* Trucks can't copy all the orders from busses (and visa versa),
1605  * and neither can helicopters and aircraft. */
1606  const Order *order;
1607  FOR_VEHICLE_ORDERS(src, order) {
1608  if (OrderGoesToStation(dst, order) &&
1610  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1611  }
1612  }
1613 
1614  /* Check for aircraft range limits. */
1615  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1616  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1617  }
1618 
1619  /* make sure there are orders available */
1621  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1622  }
1623 
1624  if (flags & DC_EXEC) {
1625  const Order *order;
1626  Order *first = nullptr;
1627  Order **order_dst;
1628 
1629  /* If the destination vehicle had an order list, destroy the chain but keep the OrderList.
1630  * We only reset the order indices, if the new orders are obviously different.
1631  * (We mainly do this to keep the order indices valid and in range.) */
1632  DeleteVehicleOrders(dst, true, dst->GetNumOrders() != src->GetNumOrders());
1633 
1634  order_dst = &first;
1635  FOR_VEHICLE_ORDERS(src, order) {
1636  *order_dst = new Order();
1637  (*order_dst)->AssignOrder(*order);
1638  order_dst = &(*order_dst)->next;
1639  }
1640  if (dst->orders.list == nullptr) {
1641  dst->orders.list = new OrderList(first, dst);
1642  } else {
1643  assert(dst->orders.list->GetFirstOrder() == nullptr);
1644  assert(!dst->orders.list->IsShared());
1645  delete dst->orders.list;
1646  assert(OrderList::CanAllocateItem());
1647  dst->orders.list = new OrderList(first, dst);
1648  }
1649 
1651 
1653  }
1654  break;
1655  }
1656 
1657  case CO_UNSHARE: return DecloneOrder(dst, flags);
1658  default: return CMD_ERROR;
1659  }
1660 
1661  return CommandCost();
1662 }
1663 
1675 CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1676 {
1677  VehicleID veh = GB(p1, 0, 20);
1678  VehicleOrderID order_number = GB(p2, 16, 8);
1679  CargoID cargo = GB(p2, 0, 8);
1680 
1681  if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT && cargo != CT_AUTO_REFIT) return CMD_ERROR;
1682 
1683  const Vehicle *v = Vehicle::GetIfValid(veh);
1684  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1685 
1686  CommandCost ret = CheckOwnership(v->owner);
1687  if (ret.Failed()) return ret;
1688 
1689  Order *order = v->GetOrder(order_number);
1690  if (order == nullptr) return CMD_ERROR;
1691 
1692  /* Automatic refit cargo is only supported for goto station orders. */
1693  if (cargo == CT_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
1694 
1695  if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
1696 
1697  if (flags & DC_EXEC) {
1698  order->SetRefit(cargo);
1699 
1700  /* Make the depot order an 'always go' order. */
1701  if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
1704  }
1705 
1706  for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
1707  /* Update any possible open window of the vehicle */
1709 
1710  /* If the vehicle already got the current depot set as current order, then update current order as well */
1711  if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
1712  u->current_order.SetRefit(cargo);
1713  }
1714  }
1715  }
1716 
1717  return CommandCost();
1718 }
1719 
1720 
1726 void CheckOrders(const Vehicle *v)
1727 {
1728  /* Does the user wants us to check things? */
1729  if (_settings_client.gui.order_review_system == 0) return;
1730 
1731  /* Do nothing for crashed vehicles */
1732  if (v->vehstatus & VS_CRASHED) return;
1733 
1734  /* Do nothing for stopped vehicles if setting is '1' */
1735  if (_settings_client.gui.order_review_system == 1 && (v->vehstatus & VS_STOPPED)) return;
1736 
1737  /* do nothing we we're not the first vehicle in a share-chain */
1738  if (v->FirstShared() != v) return;
1739 
1740  /* Only check every 20 days, so that we don't flood the message log */
1741  if (v->owner == _local_company && v->day_counter % 20 == 0) {
1742  const Order *order;
1743  StringID message = INVALID_STRING_ID;
1744 
1745  /* Check the order list */
1746  int n_st = 0;
1747 
1748  FOR_VEHICLE_ORDERS(v, order) {
1749  /* Dummy order? */
1750  if (order->IsType(OT_DUMMY)) {
1751  message = STR_NEWS_VEHICLE_HAS_VOID_ORDER;
1752  break;
1753  }
1754  /* Does station have a load-bay for this vehicle? */
1755  if (order->IsType(OT_GOTO_STATION)) {
1756  const Station *st = Station::Get(order->GetDestination());
1757 
1758  n_st++;
1759  if (!CanVehicleUseStation(v, st)) {
1760  message = STR_NEWS_VEHICLE_HAS_INVALID_ENTRY;
1761  } else if (v->type == VEH_AIRCRAFT &&
1762  (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1765  message == INVALID_STRING_ID) {
1766  message = STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY;
1767  }
1768  }
1769  }
1770 
1771  /* Check if the last and the first order are the same */
1772  if (v->GetNumOrders() > 1) {
1773  const Order *last = v->GetLastOrder();
1774 
1775  if (v->orders.list->GetFirstOrder()->Equals(*last)) {
1776  message = STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY;
1777  }
1778  }
1779 
1780  /* Do we only have 1 station in our order list? */
1781  if (n_st < 2 && message == INVALID_STRING_ID) message = STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS;
1782 
1783 #ifndef NDEBUG
1784  if (v->orders.list != nullptr) v->orders.list->DebugCheckSanity();
1785 #endif
1786 
1787  /* We don't have a problem */
1788  if (message == INVALID_STRING_ID) return;
1789 
1790  SetDParam(0, v->index);
1791  AddVehicleAdviceNewsItem(message, v->index);
1792  }
1793 }
1794 
1803 void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
1804 {
1805  Vehicle *v;
1806 
1807  /* Aircraft have StationIDs for depot orders and never use DepotIDs
1808  * This fact is handled specially below
1809  */
1810 
1811  /* Go through all vehicles */
1812  FOR_ALL_VEHICLES(v) {
1813  Order *order;
1814 
1815  order = &v->current_order;
1816  if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
1817  (!hangar || v->type == VEH_AIRCRAFT) && v->current_order.GetDestination() == destination) {
1818  order->MakeDummy();
1820  }
1821 
1822  /* Clear the order from the order-list */
1823  int id = -1;
1824  FOR_VEHICLE_ORDERS(v, order) {
1825  id++;
1826 restart:
1827 
1828  OrderType ot = order->GetType();
1829  if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
1830  if (ot == OT_GOTO_DEPOT && hangar && v->type != VEH_AIRCRAFT) continue; // Not an aircraft? Can't have a hangar order.
1831  if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
1832  if (ot == type && order->GetDestination() == destination) {
1833  /* We want to clear implicit orders, but we don't want to make them
1834  * dummy orders. They should just vanish. Also check the actual order
1835  * type as ot is currently OT_GOTO_STATION. */
1836  if (order->IsType(OT_IMPLICIT)) {
1837  order = order->next; // DeleteOrder() invalidates current order
1838  DeleteOrder(v, id);
1839  if (order != nullptr) goto restart;
1840  break;
1841  }
1842 
1843  /* Clear wait time */
1844  v->orders.list->UpdateTotalDuration(-order->GetWaitTime());
1845  if (order->IsWaitTimetabled()) {
1847  order->SetWaitTimetabled(false);
1848  }
1849  order->SetWaitTime(0);
1850 
1851  /* Clear order, preserving travel time */
1852  bool travel_timetabled = order->IsTravelTimetabled();
1853  order->MakeDummy();
1854  order->SetTravelTimetabled(travel_timetabled);
1855 
1856  for (const Vehicle *w = v->FirstShared(); w != nullptr; w = w->NextShared()) {
1857  /* In GUI, simulate by removing the order and adding it back */
1860  }
1861  }
1862  }
1863  }
1864 
1865  OrderBackup::RemoveOrder(type, destination, hangar);
1866 }
1867 
1873 {
1874  const Order *order;
1875 
1876  FOR_VEHICLE_ORDERS(this, order) {
1877  if (order->IsType(OT_GOTO_DEPOT)) return true;
1878  }
1879 
1880  return false;
1881 }
1882 
1892 void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
1893 {
1895 
1896  if (v->IsOrderListShared()) {
1897  /* Remove ourself from the shared order list. */
1898  v->RemoveFromShared();
1899  v->orders.list = nullptr;
1900  } else if (v->orders.list != nullptr) {
1901  /* Remove the orders */
1902  v->orders.list->FreeChain(keep_orderlist);
1903  if (!keep_orderlist) v->orders.list = nullptr;
1904  }
1905 
1906  if (reset_order_indices) {
1908  if (v->current_order.IsType(OT_LOADING)) {
1910  }
1911  }
1912 }
1913 
1920 uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
1921 {
1922  return ispercent ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
1923 }
1924 
1933 static bool CheckForValidOrders(const Vehicle *v)
1934 {
1935  const Order *order;
1936 
1937  FOR_VEHICLE_ORDERS(v, order) {
1938  switch (order->GetType()) {
1939  case OT_GOTO_STATION:
1940  case OT_GOTO_DEPOT:
1941  case OT_GOTO_WAYPOINT:
1942  return true;
1943 
1944  default:
1945  break;
1946  }
1947  }
1948 
1949  return false;
1950 }
1951 
1955 static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
1956 {
1957  switch (occ) {
1958  case OCC_EQUALS: return variable == value;
1959  case OCC_NOT_EQUALS: return variable != value;
1960  case OCC_LESS_THAN: return variable < value;
1961  case OCC_LESS_EQUALS: return variable <= value;
1962  case OCC_MORE_THAN: return variable > value;
1963  case OCC_MORE_EQUALS: return variable >= value;
1964  case OCC_IS_TRUE: return variable != 0;
1965  case OCC_IS_FALSE: return variable == 0;
1966  default: NOT_REACHED();
1967  }
1968 }
1969 
1977 {
1978  if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
1979 
1980  bool skip_order = false;
1982  uint16 value = order->GetConditionValue();
1983 
1984  switch (order->GetConditionVariable()) {
1985  case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, nullptr), value); break;
1986  case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
1987  case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
1988  case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
1989  case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / DAYS_IN_LEAP_YEAR, value); break;
1990  case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
1991  case OCV_UNCONDITIONALLY: skip_order = true; break;
1992  case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, max(v->max_age - v->age + DAYS_IN_LEAP_YEAR - 1, 0) / DAYS_IN_LEAP_YEAR, value); break;
1993  default: NOT_REACHED();
1994  }
1995 
1996  return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
1997 }
1998 
2006 bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
2007 {
2008  if (conditional_depth > v->GetNumOrders()) {
2009  v->current_order.Free();
2010  v->SetDestTile(0);
2011  return false;
2012  }
2013 
2014  switch (order->GetType()) {
2015  case OT_GOTO_STATION:
2016  v->SetDestTile(v->GetOrderStationLocation(order->GetDestination()));
2017  return true;
2018 
2019  case OT_GOTO_DEPOT:
2020  if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
2021  assert(!pbs_look_ahead);
2022  UpdateVehicleTimetable(v, true);
2024  break;
2025  }
2026 
2028  /* We need to search for the nearest depot (hangar). */
2029  TileIndex location;
2030  DestinationID destination;
2031  bool reverse;
2032 
2033  if (v->FindClosestDepot(&location, &destination, &reverse)) {
2034  /* PBS reservations cannot reverse */
2035  if (pbs_look_ahead && reverse) return false;
2036 
2037  v->SetDestTile(location);
2039 
2040  /* If there is no depot in front, reverse automatically (trains only) */
2041  if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2042 
2043  if (v->type == VEH_AIRCRAFT) {
2044  Aircraft *a = Aircraft::From(v);
2045  if (a->state == FLYING && a->targetairport != destination) {
2046  /* The aircraft is now heading for a different hangar than the next in the orders */
2049  }
2050  }
2051  return true;
2052  }
2053 
2054  /* If there is no depot, we cannot help PBS either. */
2055  if (pbs_look_ahead) return false;
2056 
2057  UpdateVehicleTimetable(v, true);
2059  } else {
2060  if (v->type != VEH_AIRCRAFT) {
2061  v->SetDestTile(Depot::Get(order->GetDestination())->xy);
2062  } else {
2063  Aircraft *a = Aircraft::From(v);
2064  DestinationID destination = a->current_order.GetDestination();
2065  if (a->targetairport != destination) {
2066  /* The aircraft is now heading for a different hangar than the next in the orders */
2067  a->SetDestTile(a->GetOrderStationLocation(destination));
2068  }
2069  }
2070  return true;
2071  }
2072  break;
2073 
2074  case OT_GOTO_WAYPOINT:
2075  v->SetDestTile(Waypoint::Get(order->GetDestination())->xy);
2076  return true;
2077 
2078  case OT_CONDITIONAL: {
2079  assert(!pbs_look_ahead);
2080  VehicleOrderID next_order = ProcessConditionalOrder(order, v);
2081  if (next_order != INVALID_VEH_ORDER_ID) {
2082  /* Jump to next_order. cur_implicit_order_index becomes exactly that order,
2083  * cur_real_order_index might come after next_order. */
2084  UpdateVehicleTimetable(v, false);
2085  v->cur_implicit_order_index = v->cur_real_order_index = next_order;
2086  v->UpdateRealOrderIndex();
2088 
2089  /* Disable creation of implicit orders.
2090  * When inserting them we do not know that we would have to make the conditional orders point to them. */
2091  if (v->IsGroundVehicle()) {
2092  uint16 &gv_flags = v->GetGroundVehicleFlags();
2094  }
2095  } else {
2096  UpdateVehicleTimetable(v, true);
2098  }
2099  break;
2100  }
2101 
2102  default:
2103  v->SetDestTile(0);
2104  return false;
2105  }
2106 
2107  assert(v->cur_implicit_order_index < v->GetNumOrders());
2108  assert(v->cur_real_order_index < v->GetNumOrders());
2109 
2110  /* Get the current order */
2111  order = v->GetOrder(v->cur_real_order_index);
2112  if (order != nullptr && order->IsType(OT_IMPLICIT)) {
2113  assert(v->GetNumManualOrders() == 0);
2114  order = nullptr;
2115  }
2116 
2117  if (order == nullptr) {
2118  v->current_order.Free();
2119  v->SetDestTile(0);
2120  return false;
2121  }
2122 
2123  v->current_order = *order;
2124  return UpdateOrderDest(v, order, conditional_depth + 1, pbs_look_ahead);
2125 }
2126 
2135 {
2136  switch (v->current_order.GetType()) {
2137  case OT_GOTO_DEPOT:
2138  /* Let a depot order in the orderlist interrupt. */
2139  if (!(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return false;
2140  break;
2141 
2142  case OT_LOADING:
2143  return false;
2144 
2145  case OT_LEAVESTATION:
2146  if (v->type != VEH_AIRCRAFT) return false;
2147  break;
2148 
2149  default: break;
2150  }
2151 
2159  bool may_reverse = v->current_order.IsType(OT_NOTHING);
2160 
2161  /* Check if we've reached a 'via' destination. */
2162  if (((v->current_order.IsType(OT_GOTO_STATION) && (v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) || v->current_order.IsType(OT_GOTO_WAYPOINT)) &&
2163  IsTileType(v->tile, MP_STATION) &&
2166  /* We set the last visited station here because we do not want
2167  * the train to stop at this 'via' station if the next order
2168  * is a no-non-stop order; in that case not setting the last
2169  * visited station will cause the vehicle to still stop. */
2171  UpdateVehicleTimetable(v, true);
2173  }
2174 
2175  /* Get the current order */
2176  assert(v->cur_implicit_order_index == 0 || v->cur_implicit_order_index < v->GetNumOrders());
2177  v->UpdateRealOrderIndex();
2178 
2179  const Order *order = v->GetOrder(v->cur_real_order_index);
2180  if (order != nullptr && order->IsType(OT_IMPLICIT)) {
2181  assert(v->GetNumManualOrders() == 0);
2182  order = nullptr;
2183  }
2184 
2185  /* If no order, do nothing. */
2186  if (order == nullptr || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
2187  if (v->type == VEH_AIRCRAFT) {
2188  /* Aircraft do something vastly different here, so handle separately */
2189  extern void HandleMissingAircraftOrders(Aircraft *v);
2190  HandleMissingAircraftOrders(Aircraft::From(v));
2191  return false;
2192  }
2193 
2194  v->current_order.Free();
2195  v->SetDestTile(0);
2196  return false;
2197  }
2198 
2199  /* If it is unchanged, keep it. */
2200  if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
2201  (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->ship_station.tile != INVALID_TILE)) {
2202  return false;
2203  }
2204 
2205  /* Otherwise set it, and determine the destination tile. */
2206  v->current_order = *order;
2207 
2209  switch (v->type) {
2210  default:
2211  NOT_REACHED();
2212 
2213  case VEH_ROAD:
2214  case VEH_TRAIN:
2215  break;
2216 
2217  case VEH_AIRCRAFT:
2218  case VEH_SHIP:
2220  break;
2221  }
2222 
2223  return UpdateOrderDest(v, order) && may_reverse;
2224 }
2225 
2233 bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
2234 {
2235  bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
2236 
2237  return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
2238  v->last_station_visited != station && // Do stop only when we've not just been there
2239  /* Finally do stop when there is no non-stop flag set for this type of station. */
2241 }
2242 
2243 bool Order::CanLoadOrUnload() const
2244 {
2245  return (this->IsType(OT_GOTO_STATION) || this->IsType(OT_IMPLICIT)) &&
2247  ((this->GetLoadType() & OLFB_NO_LOAD) == 0 ||
2248  (this->GetUnloadType() & OUFB_NO_UNLOAD) == 0);
2249 }
2250 
2257 bool Order::CanLeaveWithCargo(bool has_cargo) const
2258 {
2259  return (this->GetLoadType() & OLFB_NO_LOAD) == 0 || (has_cargo &&
2260  (this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0);
2261 }
OrderConditionVariable
Variables (of a vehicle) to &#39;cause&#39; skipping on.
Definition: order_type.h:114
Functions related to OTTD&#39;s strings.
Road vehicle states.
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:27
Date max_age
Maximum age.
Definition: vehicle_base.h:259
StationFacility facilities
The facilities that this station has.
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
This airport has a short landing strip, dangerous for fast aircraft.
Definition: airport.h:152
void InsertOrderAt(Order *new_order, int index)
Insert a new order into the order chain.
Definition: order_cmd.cpp:461
bool IsVehicleInSharedOrdersList(const Vehicle *v) const
Checks whether a vehicle is part of the shared vehicle chain.
Definition: order_cmd.cpp:567
Definition of stuff that is very close to a company, like the company struct itself.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:257
CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Delete an order from the orderlist of a vehicle.
Definition: order_cmd.cpp:1004
uint16 DepotID
Type for the unique identifier of depots.
Definition: depot_type.h:15
Passes an OrderUnloadType.
Definition: order_type.h:148
uint16 GetTravelTime() const
Get the time in ticks a vehicle will probably take to reach the destination (timetabled or not)...
Definition: order_base.h:187
StationID targetairport
Airport to go to next.
Definition: aircraft.h:80
Minimal stack that uses a pool to avoid pointers.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
Skip if both values are equal.
Definition: order_type.h:130
Load as long as there is cargo that fits in the train.
Definition: order_type.h:65
OrderConditionComparator GetConditionComparator() const
What is the comparator to use?
Definition: order_base.h:143
uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1920
void SetConditionValue(uint16 value)
Set the value to base the skip on.
Definition: order_base.h:168
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1726
Functions related to time tabling.
bool HasHangar() const
Check if this airport has at least one hangar.
Definition: station_base.h:340
void InvalidateVehicleOrder(const Vehicle *v, int data)
Updates the widgets of a vehicle which contains the order-data.
Definition: order_cmd.cpp:252
Train vehicle type.
Definition: vehicle_type.h:26
union Vehicle::@49 orders
The orders currently assigned to the vehicle.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
void UpdateTimetableDuration(Ticks delta)
Must be called if an order&#39;s timetable is changed to update internal book keeping.
Definition: order_base.h:382
const AirportFTAClass * GetFTA() const
Get the finite-state machine for this airport or the finite-state machine for the dummy airport in ca...
Definition: station_base.h:334
VehicleOrderID GetConditionSkipToOrder() const
Get the order to skip to.
Definition: order_base.h:145
void SetWaitTime(uint16 time)
Set the time in ticks to wait at the destination.
Definition: order_base.h:205
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:23
Other order modifications.
Definition: vehicle_gui.h:35
Functions related to debugging.
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
void SetDepotOrderType(OrderDepotTypeFlags depot_order_type)
Set the cause to go to the depot.
Definition: order_base.h:158
static void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:42
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
Ship vehicle type.
Definition: vehicle_type.h:28
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
void SetDepotActionType(OrderDepotActionFlags depot_service_type)
Set what we are going to do in the depot.
Definition: order_base.h:160
Selects the OrderDepotAction.
Definition: order_type.h:150
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:321
Skip if the variable is true.
Definition: order_type.h:136
static void RemoveOrder(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:237
bool IsCompleteTimetable() const
Checks whether all orders of the list have a filled timetable.
Definition: order_cmd.cpp:592
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition: order_base.h:178
Skip based on the reliability.
Definition: order_type.h:116
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:76
void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
Insert a new order but skip the validation.
Definition: order_cmd.cpp:917
Stop at the middle of the platform.
Definition: order_type.h:87
A comparator changes.
Definition: order_type.h:152
void IncrementImplicitOrderIndex()
Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI...
Definition: vehicle_base.h:800
void IncrementRealOrderIndex()
Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates t...
Definition: vehicle_base.h:824
uint32 current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:23
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
Process a conditional order and determine the next order.
Definition: order_cmd.cpp:1976
Vehicle data structure.
Definition: vehicle_base.h:212
Base for all depots (except hangars)
void SetRefit(CargoID cargo)
Make this depot/station order also a refit order.
Definition: order_cmd.cpp:166
Flags flags
Flags for this airport type.
Definition: airport.h:182
Unload all cargo that the station accepts.
Definition: order_type.h:55
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2188
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Vehicle is flying in the air.
Definition: airport.h:77
Helper functions to extract data from command parameters.
CargoID refit_cargo
Refit CargoID.
Definition: order_base.h:44
Base for aircraft.
Representation of a waypoint.
Definition: waypoint_base.h:18
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:302
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1892
OrderNonStopFlags
Non-stop order flags.
Definition: order_type.h:74
void SetUnloadType(OrderUnloadFlags unload_type)
Set how the consist must be unloaded.
Definition: order_base.h:152
Skip if the value is more or equal to the limit.
Definition: order_type.h:135
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
void SetConditionComparator(OrderConditionComparator condition_comparator)
Set the comparator to use.
Definition: order_base.h:164
Automatically choose cargo type when doing auto refitting.
Definition: cargo_type.h:68
Common return value for all commands.
Definition: command_type.h:25
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
uint16 MapOldOrder() const
Pack this order into a 16 bits integer as close to the TTD representation as possible.
Definition: order_cmd.cpp:209
void SetConditionVariable(OrderConditionVariable condition_variable)
Set variable we have to compare.
Definition: order_base.h:162
byte vehstatus
Status.
Definition: vehicle_base.h:317
Skip based on the age.
Definition: order_type.h:118
const Order * GetNextDecisionNode(const Order *next, uint hops) const
Get the next order which will make the given vehicle stop at a station or refit at a depot or evaluat...
Definition: order_cmd.cpp:369
TileIndex GetLocation(const Vehicle *v, bool airport=false) const
Returns a tile somewhat representing the order destination (not suitable for pathfinding).
Definition: order_cmd.cpp:670
static RoadVehicle * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:745
bool CanLeaveWithCargo(bool has_cargo) const
A vehicle can leave the current station with cargo if:
Definition: order_cmd.cpp:2257
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new).
Definition: cargo_type.h:69
void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
Delete an order but skip the parameter validation.
Definition: order_cmd.cpp:1045
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:139
The vehicle will stop at any station it passes except the destination.
Definition: order_type.h:77
uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth)
Get the distance between two orders of a vehicle.
Definition: order_cmd.cpp:697
Stop at the near end of the platform.
Definition: order_type.h:86
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:51
void DeleteOrderAt(int index)
Remove an order from the order list and delete it.
Definition: order_cmd.cpp:499
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:675
Order * GetOrderAt(int index) const
Get a certain order of the order chain.
Definition: order_cmd.cpp:346
Cheat no_jetcrash
no jet will crash on small airports anymore
Definition: cheat_type.h:34
Pseudo random number generator.
void MoveOrder(int from, int to)
Move an order to another position within the order list.
Definition: order_cmd.cpp:525
void SetConditionSkipToOrder(VehicleOrderID order_id)
Get the order to skip to.
Definition: order_base.h:166
Stop at the far end of the platform.
Definition: order_type.h:88
DestinationID dest
The destination of the order.
Definition: order_base.h:42
uint16 travel_time
How long in ticks the journey to this destination should take.
Definition: order_base.h:47
The vehicle will stop at any station it passes and the destination.
Definition: order_type.h:75
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3318
void MakeConditional(VehicleOrderID order)
Makes this order an conditional order.
Definition: order_cmd.cpp:144
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
Definition: order_cmd.cpp:2233
Passes an OrderStopLocation.
Definition: order_type.h:147
void RemoveVehicle(Vehicle *v)
Removes the vehicle from the shared order list.
Definition: order_cmd.cpp:557
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:252
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:137
static CommandCost DecloneOrder(Vehicle *dst, DoCommandFlag flags)
Declone an order-list.
Definition: order_cmd.cpp:985
Vehicle orders; Window numbers:
Definition: window_type.h:207
virtual int GetDisplayMaxSpeed() const
Gets the maximum speed in km-ish/h that can be sent into SetDParam for string processing.
Definition: vehicle_base.h:486
bool IsEmpty() const
Check if the stack is empty.
Some methods of Pool are placed here in order to reduce compilation time and binary size...
OrderConditionVariable GetConditionVariable() const
What variable do we have to compare?
Definition: order_base.h:141
Vehicle is crashed.
Definition: vehicle_base.h:39
The tile has no ownership.
Definition: company_type.h:27
Types related to cheating.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:433
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:152
uint8 type
The type of order + non-stop flags.
Definition: order_base.h:40
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition: order_base.h:154
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:443
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition: order_cmd.cpp:155
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:850
bool IsRefit() const
Is this order a refit order.
Definition: order_base.h:110
virtual bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
Definition: vehicle_base.h:750
bool NeedsServicing() const
Check if the vehicle needs to go to a depot in near future (if a opportunity presents itself) for ser...
Definition: vehicle.cpp:185
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:134
Do not load anything.
Definition: order_type.h:68
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:18
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:63
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:180
DoCommandFlag
List of flags for a command.
Definition: command_type.h:344
Skip if the value is less or equal to the limit.
Definition: order_type.h:133
CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Add an order to the orderlist of a vehicle.
Definition: order_cmd.cpp:728
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:80
Definition of base types and functions in a cross-platform compatible way.
Removed / replaced all orders (after deleting / sharing).
Definition: vehicle_gui.h:34
A number of safeguards to prevent using unsafe methods.
bool value
tells if the bool cheat is active or not
Definition: cheat_type.h:20
Change the destination of a conditional order.
Definition: order_type.h:154
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2134
Always skip.
Definition: order_type.h:120
Base of waypoints.
void MakeLoading(bool ordered)
Makes this order a Loading order.
Definition: order_cmd.cpp:116
static bool IsRoadDepotTile(TileIndex t)
Return whether a tile is a road depot tile.
Definition: road_map.h:117
void FreeChain(bool keep_orderlist=false)
Free a complete order chain.
Definition: order_cmd.cpp:323
Titem Pop()
Pop an item from the stack.
void UpdateRealOrderIndex()
Skip implicit orders until cur_real_order_index is a non-implicit order.
Definition: vehicle_base.h:839
OrderDepotActionFlags
Actions that can be performed when the vehicle enters the depot.
Definition: order_type.h:104
uint8 flags
Load/unload types, depot order/action types.
Definition: order_base.h:41
CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Move an order inside the orderlist.
Definition: order_cmd.cpp:1151
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2696
Vehicle view; Window numbers:
Definition: window_type.h:334
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition: order_base.h:176
Functions related to order backups.
uint16 GetTimetabledTravel() const
Get the time in ticks a vehicle should take to reach the destination or 0 if it&#39;s not timetabled...
Definition: order_base.h:183
bool IsShared() const
Is this a shared order list?
Definition: order_base.h:331
Order * GetFirstOrder() const
Get the first order of the order chain.
Definition: order_base.h:290
void Initialize(Order *chain, Vehicle *v)
Recomputes everything.
Definition: order_cmd.cpp:292
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
void Push(const Titem &item)
Pushes a new item onto the stack if there is still space in the underlying pool.
Vehicle timetable; Window numbers:
Definition: window_type.h:219
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:2788
OrderConditionComparator
Comparator for the skip reasoning.
Definition: order_type.h:129
Always go to the depot.
Definition: order_type.h:163
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition: order_base.h:129
Service the vehicle and then halt it.
Definition: order_type.h:106
virtual TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
Definition: vehicle_base.h:740
void SetWaitTimetabled(bool timetabled)
Set if the wait time is explicitly timetabled (unless the order is conditional).
Definition: order_base.h:197
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
bool Equals(const Order &other) const
Does this order have the same type, flags and destination?
Definition: order_cmd.cpp:176
static bool IsShipDepotTile(TileIndex t)
Is it a ship depot tile?
Definition: water_map.h:228
Service only if needed.
Definition: order_type.h:164
Order * GetLastOrder() const
Returns the last order of a vehicle, or nullptr if it doesn&#39;t exists.
Definition: vehicle_base.h:869
uint16 reliability
Reliability.
Definition: vehicle_base.h:261
static void CancelLoadingDueToDeletedOrder(Vehicle *v)
Cancel the current loading order of the vehicle as the order was deleted.
Definition: order_cmd.cpp:1029
CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Goto order of order-list.
Definition: order_cmd.cpp:1110
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
bool Failed() const
Did this command fail?
Definition: command_type.h:161
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
Update the vehicle&#39;s destination tile from an order.
Definition: order_cmd.cpp:2006
Order * GetFirstOrder() const
Get the first order of the vehicles order list.
Definition: vehicle_base.h:654
CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Modify an order in the orderlist of a vehicle.
Definition: order_cmd.cpp:1255
The value to set the condition to.
Definition: order_type.h:153
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
Compare the variable and value based on the given comparator.
Definition: order_cmd.cpp:1955
Skip based on the remaining lifetime.
Definition: order_type.h:121
Skip if the value is less than the limit.
Definition: order_type.h:132
static void DeleteOrderWarnings(const Vehicle *v)
Delete all news items regarding defective orders about a vehicle This could kill still valid warnings...
Definition: order_cmd.cpp:655
Transfer all cargo onto the platform.
Definition: order_type.h:57
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:35
byte state
State of the airport.
Definition: aircraft.h:81
Base class for all pools.
Definition: pool_type.hpp:83
Station list; Window numbers:
Definition: window_type.h:297
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
OrderUnloadFlags GetUnloadType() const
How must the consist be unloaded?
Definition: order_base.h:131
void SetLoadType(OrderLoadFlags load_type)
Set how the consist must be loaded.
Definition: order_base.h:150
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:37
Skip when the vehicle requires service.
Definition: order_type.h:119
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
bool HasDepotOrder() const
Checks if a vehicle has a depot in its order list.
Definition: order_cmd.cpp:1872
OrderUnloadFlags
Flags related to the unloading order.
Definition: order_type.h:54
uint16 GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not)...
Definition: order_base.h:185
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:226
TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
void RemoveFromShared()
Removes the vehicle from the shared order list.
Definition: vehicle.cpp:2719
execute the given command
Definition: command_type.h:346
A conditional variable changes.
Definition: order_type.h:151
Functions related to companies.
Station with a dock.
Definition: station_type.h:58
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:30
OrderStopLocation
Where to stop the trains.
Definition: order_type.h:85
uint16 GetTimetabledWait() const
Get the time in ticks a vehicle should wait at the destination or 0 if it&#39;s not timetabled.
Definition: order_base.h:181
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:81
Passes an OrderNonStopFlags.
Definition: order_type.h:146
uint16 cached_max_range
Cached maximum range.
Definition: aircraft.h:70
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:471
GUISettings gui
settings related to the GUI
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:96
static bool IsRailDepotTile(TileIndex t)
Is this tile rail tile and a rail depot?
Definition: rail_map.h:107
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CT_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:91
static bool CheckForValidOrders(const Vehicle *v)
Check if a vehicle has any valid orders.
Definition: order_cmd.cpp:1933
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition: order_base.h:135
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
StationIDStack GetNextStoppingStation(const Vehicle *v, const Order *first=nullptr, uint hops=0) const
Recursively determine the next deterministic station to stop at.
Definition: order_cmd.cpp:404
Ships list; Window numbers:
Definition: window_type.h:315
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
Skip if both values are not equal.
Definition: order_type.h:131
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:159
OrderLoadFlags
Flags related to the loading order.
Definition: order_type.h:64
void MakeLeaveStation()
Makes this order a Leave Station order.
Definition: order_cmd.cpp:125
static bool OrderGoesToStation(const Vehicle *v, const Order *o)
Checks whether the order goes to a station or not, i.e.
Definition: order_cmd.cpp:643
Vehicle * PreviousShared() const
Get the previous vehicle of the shared vehicle chain.
Definition: vehicle_base.h:669
uint16 wait_time
How long in ticks to wait at the destination.
Definition: order_base.h:46
Send the vehicle to the nearest depot.
Definition: order_type.h:107
int32 Ticks
The type to store ticks in.
Definition: date_type.h:18
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:64
turn a train around
Definition: command_type.h:224
uint16 GetConditionValue() const
Get the value to base the skip on.
Definition: order_base.h:147
TileIndex xy
Base tile of the station.
void SetTravelTimetabled(bool timetabled)
Set if the travel time is explicitly timetabled (unless the order is conditional).
Definition: order_base.h:199
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint32 cached_max_range_sqr
Cached squared maximum range.
Definition: aircraft.h:69
Full load all cargoes of the consist.
Definition: order_type.h:66
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:54
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition: vehicle.cpp:2002
A tile of a station.
Definition: tile_type.h:48
Skip based on the amount of load.
Definition: order_type.h:115
OrderType
Order types.
Definition: order_type.h:37
int GetPositionInSharedOrderList(const Vehicle *v) const
Gets the position of the given vehicle within the shared order vehicle list.
Definition: order_cmd.cpp:581
Totally no unloading will be done.
Definition: order_type.h:58
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:216
static uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:300
void AssignOrder(const Order &other)
Assign data to an order (from another order) This function makes sure that the index is maintained co...
Definition: order_cmd.cpp:274
The vehicle will not stop at any stations it passes except the destination.
Definition: order_type.h:76
Skip based on the maximum speed.
Definition: order_type.h:117
void UpdateTotalDuration(Ticks delta)
Must be called if an order&#39;s timetable is changed to update internal book keeping.
Definition: order_base.h:388
Aircraft list; Window numbers:
Definition: window_type.h:321
uint16 & GetGroundVehicleFlags()
Access the ground vehicle flags of the vehicle.
Definition: vehicle.cpp:2863
Functions related to commands.
CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Add/remove refit orders from an order.
Definition: order_cmd.cpp:1675
uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition: vehicle.cpp:1382
void DebugCheckSanity() const
Checks for internal consistency of order list.
Definition: order_cmd.cpp:605
Passes an OrderLoadType.
Definition: order_type.h:149
Owner owner
The owner of this station.
ModifyOrderFlags
Enumeration for the data to set in CmdModifyOrder.
Definition: order_type.h:145
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:93
CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Clone/share/copy an order-list of another vehicle.
Definition: order_cmd.cpp:1524
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or nullptr when it doesn&#39;t exists.
Definition: vehicle_base.h:860
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Definition: vehicle_base.h:687
Aircraft vehicle type.
Definition: vehicle_type.h:29
static bool CheckAircraftOrderDistance(const Aircraft *v_new, const Vehicle *v_order, const Order *first)
Check if an aircraft has enough range for an order list.
Definition: order_cmd.cpp:1491
Airport airport
Tile area the airport covers.
Definition: station_base.h:466
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Definition: vehicle_base.h:681
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
Definition: order_cmd.cpp:105
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:288
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:17
#define FOR_ALL_VEHICLES(var)
Iterate over all vehicles.
Definition: vehicle_base.h:987
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
uint32 Pack() const
Pack this order into a 32 bits integer, or actually only the type, flags and destination.
Definition: order_cmd.cpp:199
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition: order_cmd.cpp:1803
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:69
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
uint8 order_review_system
perform order reviews on vehicles
Definition: settings_type.h:87
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the &#39;Square&#39; distance between the two given tiles.
Definition: map.cpp:176
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:663
Station with train station.
Definition: station_type.h:54
Force unloading all cargo onto the platform, possibly not getting paid.
Definition: order_type.h:56
static const VehicleOrderID MAX_VEH_ORDER_ID
Last valid VehicleOrderID.
Definition: order_type.h:25
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3227
This depot order is because of a regular order.
Definition: order_type.h:98
Functions related to news.
Go to the depot and stop there.
Definition: order_type.h:165
Base classes/functions for stations.
static Station * Get(size_t index)
Gets station with given index.
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
Definition: base_consist.h:30
Skip if the value is more than the limit.
Definition: order_type.h:134
uint16 max_speed
How fast the vehicle may go on the way to the destination.
Definition: order_base.h:48
Date age
Age in days.
Definition: vehicle_base.h:258
Full load a single cargo of the consist.
Definition: order_type.h:67
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
This depot order is because of the servicing limit.
Definition: order_type.h:97
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:29
Skip if the variable is false.
Definition: order_type.h:137
Skip based on the maximum reliability.
Definition: order_type.h:122
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition: order_base.h:156
Base class for all station-ish types.
Station data structure.
Definition: station_base.h:452
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition: order_base.h:133
Disable insertion and removal of automatic orders until the vehicle completes the real order...
Road vehicle type.
Definition: vehicle_type.h:27
byte day_counter
Increased by one for each day.
Definition: vehicle_base.h:313
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:318
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3300
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:32
void MakeGoToStation(StationID destination)
Makes this order a Go To Station order.
Definition: order_cmd.cpp:76
OrderDepotTypeFlags
Reasons that could cause us to go to the depot.
Definition: order_type.h:95
CargoID GetRefitCargo() const
Get the cargo to to refit to.
Definition: order_base.h:124
Cheats _cheats
All the cheats.
Definition: cheat.cpp:18
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:693
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.