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 "ship.h"
27 #include "station_base.h"
28 #include "waypoint_base.h"
29 #include "company_base.h"
30 #include "order_backup.h"
31 #include "cheat_type.h"
32 
33 #include "table/strings.h"
34 
35 #include "safeguards.h"
36 
37 /* DestinationID must be at least as large as every these below, because it can
38  * be any of them
39  */
40 assert_compile(sizeof(DestinationID) >= sizeof(DepotID));
41 assert_compile(sizeof(DestinationID) >= sizeof(StationID));
42 
43 OrderPool _order_pool("Order");
45 OrderListPool _orderlist_pool("OrderList");
47 
48 
50 {
51  if (CleaningPool()) return;
52 
53  /* We can visit oil rigs and buoys that are not our own. They will be shown in
54  * the list of stations. So, we need to invalidate that window if needed. */
55  if (this->IsType(OT_GOTO_STATION) || this->IsType(OT_GOTO_WAYPOINT)) {
56  BaseStation *bs = BaseStation::GetIfValid(this->GetDestination());
57  if (bs != NULL && bs->owner == OWNER_NONE) InvalidateWindowClassesData(WC_STATION_LIST, 0);
58  }
59 }
60 
66 {
67  this->type = OT_NOTHING;
68  this->flags = 0;
69  this->dest = 0;
70  this->next = NULL;
71 }
72 
77 void Order::MakeGoToStation(StationID destination)
78 {
79  this->type = OT_GOTO_STATION;
80  this->flags = 0;
81  this->dest = destination;
82 }
83 
93 {
94  this->type = OT_GOTO_DEPOT;
95  this->SetDepotOrderType(order);
96  this->SetDepotActionType(action);
97  this->SetNonStopType(non_stop_type);
98  this->dest = destination;
99  this->SetRefit(cargo);
100 }
101 
106 void Order::MakeGoToWaypoint(StationID destination)
107 {
108  this->type = OT_GOTO_WAYPOINT;
109  this->flags = 0;
110  this->dest = destination;
111 }
112 
117 void Order::MakeLoading(bool ordered)
118 {
119  this->type = OT_LOADING;
120  if (!ordered) this->flags = 0;
121 }
122 
127 {
128  this->type = OT_LEAVESTATION;
129  this->flags = 0;
130 }
131 
136 {
137  this->type = OT_DUMMY;
138  this->flags = 0;
139 }
140 
146 {
147  this->type = OT_CONDITIONAL;
148  this->flags = order;
149  this->dest = 0;
150 }
151 
156 void Order::MakeImplicit(StationID destination)
157 {
158  this->type = OT_IMPLICIT;
159  this->dest = destination;
160 }
161 
168 {
169  this->refit_cargo = cargo;
170 }
171 
177 bool Order::Equals(const Order &other) const
178 {
179  /* In case of go to nearest depot orders we need "only" compare the flags
180  * with the other and not the nearest depot order bit or the actual
181  * destination because those get clear/filled in during the order
182  * evaluation. If we do not do this the order will continuously be seen as
183  * a different order and it will try to find a "nearest depot" every tick. */
184  if ((this->IsType(OT_GOTO_DEPOT) && this->type == other.type) &&
185  ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0 ||
186  (other.GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0)) {
187  return this->GetDepotOrderType() == other.GetDepotOrderType() &&
189  }
190 
191  return this->type == other.type && this->flags == other.flags && this->dest == other.dest;
192 }
193 
200 uint32 Order::Pack() const
201 {
202  return this->dest << 16 | this->flags << 8 | this->type;
203 }
204 
210 uint16 Order::MapOldOrder() const
211 {
212  uint16 order = this->GetType();
213  switch (this->type) {
214  case OT_GOTO_STATION:
215  if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
216  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
218  order |= GB(this->GetDestination(), 0, 8) << 8;
219  break;
220  case OT_GOTO_DEPOT:
221  if (!(this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) SetBit(order, 6);
222  SetBit(order, 7);
223  order |= GB(this->GetDestination(), 0, 8) << 8;
224  break;
225  case OT_LOADING:
226  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
227  break;
228  }
229  return order;
230 }
231 
236 Order::Order(uint32 packed)
237 {
238  this->type = (OrderType)GB(packed, 0, 8);
239  this->flags = GB(packed, 8, 8);
240  this->dest = GB(packed, 16, 16);
241  this->next = NULL;
242  this->refit_cargo = CT_NO_REFIT;
243  this->wait_time = 0;
244  this->travel_time = 0;
245  this->max_speed = UINT16_MAX;
246 }
247 
253 void InvalidateVehicleOrder(const Vehicle *v, int data)
254 {
256 
257  if (data != 0) {
258  /* Calls SetDirty() too */
261  return;
262  }
263 
266 }
267 
275 void Order::AssignOrder(const Order &other)
276 {
277  this->type = other.type;
278  this->flags = other.flags;
279  this->dest = other.dest;
280 
281  this->refit_cargo = other.refit_cargo;
282 
283  this->wait_time = other.wait_time;
284  this->travel_time = other.travel_time;
285  this->max_speed = other.max_speed;
286 }
287 
294 {
295  this->first = chain;
296  this->first_shared = v;
297 
298  this->num_orders = 0;
299  this->num_manual_orders = 0;
300  this->num_vehicles = 1;
301  this->timetable_duration = 0;
302  this->total_duration = 0;
303 
304  for (Order *o = this->first; o != NULL; o = o->next) {
305  ++this->num_orders;
306  if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
307  this->timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
308  this->total_duration += o->GetWaitTime() + o->GetTravelTime();
309  }
310 
311  for (Vehicle *u = this->first_shared->PreviousShared(); u != NULL; u = u->PreviousShared()) {
312  ++this->num_vehicles;
313  this->first_shared = u;
314  }
315 
316  for (const Vehicle *u = v->NextShared(); u != NULL; u = u->NextShared()) ++this->num_vehicles;
317 }
318 
324 void OrderList::FreeChain(bool keep_orderlist)
325 {
326  Order *next;
327  for (Order *o = this->first; o != NULL; o = next) {
328  next = o->next;
329  delete o;
330  }
331 
332  if (keep_orderlist) {
333  this->first = NULL;
334  this->num_orders = 0;
335  this->num_manual_orders = 0;
336  this->timetable_duration = 0;
337  } else {
338  delete this;
339  }
340 }
341 
348 {
349  if (index < 0) return NULL;
350 
351  Order *order = this->first;
352 
353  while (order != NULL && index-- > 0) {
354  order = order->next;
355  }
356  return order;
357 }
358 
370 const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops) const
371 {
372  if (hops > this->GetNumOrders() || next == NULL) return NULL;
373 
374  if (next->IsType(OT_CONDITIONAL)) {
375  if (next->GetConditionVariable() != OCV_UNCONDITIONALLY) return next;
376 
377  /* We can evaluate trivial conditions right away. They're conceptually
378  * the same as regular order progression. */
379  return this->GetNextDecisionNode(
380  this->GetOrderAt(next->GetConditionSkipToOrder()),
381  hops + 1);
382  }
383 
384  if (next->IsType(OT_GOTO_DEPOT)) {
385  if (next->GetDepotActionType() == ODATFB_HALT) return NULL;
386  if (next->IsRefit()) return next;
387  }
388 
389  if (!next->CanLoadOrUnload()) {
390  return this->GetNextDecisionNode(this->GetNext(next), hops + 1);
391  }
392 
393  return next;
394 }
395 
405 StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order *first, uint hops) const
406 {
407 
408  const Order *next = first;
409  if (first == NULL) {
410  next = this->GetOrderAt(v->cur_implicit_order_index);
411  if (next == NULL) {
412  next = this->GetFirstOrder();
413  if (next == NULL) return INVALID_STATION;
414  } else {
415  /* GetNext never returns NULL if there is a valid station in the list.
416  * As the given "next" is already valid and a station in the list, we
417  * don't have to check for NULL here. */
418  next = this->GetNext(next);
419  assert(next != NULL);
420  }
421  }
422 
423  do {
424  next = this->GetNextDecisionNode(next, ++hops);
425 
426  /* Resolve possibly nested conditionals by estimation. */
427  while (next != NULL && next->IsType(OT_CONDITIONAL)) {
428  /* We return both options of conditional orders. */
429  const Order *skip_to = this->GetNextDecisionNode(
430  this->GetOrderAt(next->GetConditionSkipToOrder()), hops);
431  const Order *advance = this->GetNextDecisionNode(
432  this->GetNext(next), hops);
433  if (advance == NULL || advance == first || skip_to == advance) {
434  next = (skip_to == first) ? NULL : skip_to;
435  } else if (skip_to == NULL || skip_to == first) {
436  next = (advance == first) ? NULL : advance;
437  } else {
438  StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops);
439  StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops);
440  while (!st2.IsEmpty()) st1.Push(st2.Pop());
441  return st1;
442  }
443  ++hops;
444  }
445 
446  /* Don't return a next stop if the vehicle has to unload everything. */
447  if (next == NULL || ((next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) &&
448  next->GetDestination() == v->last_station_visited &&
449  (next->GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
450  return INVALID_STATION;
451  }
452  } while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);
453 
454  return next->GetDestination();
455 }
456 
462 void OrderList::InsertOrderAt(Order *new_order, int index)
463 {
464  if (this->first == NULL) {
465  this->first = new_order;
466  } else {
467  if (index == 0) {
468  /* Insert as first or only order */
469  new_order->next = this->first;
470  this->first = new_order;
471  } else if (index >= this->num_orders) {
472  /* index is after the last order, add it to the end */
473  this->GetLastOrder()->next = new_order;
474  } else {
475  /* Put the new order in between */
476  Order *order = this->GetOrderAt(index - 1);
477  new_order->next = order->next;
478  order->next = new_order;
479  }
480  }
481  ++this->num_orders;
482  if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
483  this->timetable_duration += new_order->GetTimetabledWait() + new_order->GetTimetabledTravel();
484  this->total_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
485 
486  /* We can visit oil rigs and buoys that are not our own. They will be shown in
487  * the list of stations. So, we need to invalidate that window if needed. */
488  if (new_order->IsType(OT_GOTO_STATION) || new_order->IsType(OT_GOTO_WAYPOINT)) {
489  BaseStation *bs = BaseStation::Get(new_order->GetDestination());
491  }
492 
493 }
494 
495 
501 {
502  if (index >= this->num_orders) return;
503 
504  Order *to_remove;
505 
506  if (index == 0) {
507  to_remove = this->first;
508  this->first = to_remove->next;
509  } else {
510  Order *prev = GetOrderAt(index - 1);
511  to_remove = prev->next;
512  prev->next = to_remove->next;
513  }
514  --this->num_orders;
515  if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
516  this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
517  this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
518  delete to_remove;
519 }
520 
526 void OrderList::MoveOrder(int from, int to)
527 {
528  if (from >= this->num_orders || to >= this->num_orders || from == to) return;
529 
530  Order *moving_one;
531 
532  /* Take the moving order out of the pointer-chain */
533  if (from == 0) {
534  moving_one = this->first;
535  this->first = moving_one->next;
536  } else {
537  Order *one_before = GetOrderAt(from - 1);
538  moving_one = one_before->next;
539  one_before->next = moving_one->next;
540  }
541 
542  /* Insert the moving_order again in the pointer-chain */
543  if (to == 0) {
544  moving_one->next = this->first;
545  this->first = moving_one;
546  } else {
547  Order *one_before = GetOrderAt(to - 1);
548  moving_one->next = one_before->next;
549  one_before->next = moving_one;
550  }
551 }
552 
559 {
560  --this->num_vehicles;
561  if (v == this->first_shared) this->first_shared = v->NextShared();
562 }
563 
569 {
570  for (const Vehicle *v_shared = this->first_shared; v_shared != NULL; v_shared = v_shared->NextShared()) {
571  if (v_shared == v) return true;
572  }
573 
574  return false;
575 }
576 
583 {
584  int count = 0;
585  for (const Vehicle *v_shared = v->PreviousShared(); v_shared != NULL; v_shared = v_shared->PreviousShared()) count++;
586  return count;
587 }
588 
594 {
595  for (Order *o = this->first; o != NULL; o = o->next) {
596  /* Implicit orders are, by definition, not timetabled. */
597  if (o->IsType(OT_IMPLICIT)) continue;
598  if (!o->IsCompletelyTimetabled()) return false;
599  }
600  return true;
601 }
602 
607 {
608  VehicleOrderID check_num_orders = 0;
609  VehicleOrderID check_num_manual_orders = 0;
610  uint check_num_vehicles = 0;
611  Ticks check_timetable_duration = 0;
612  Ticks check_total_duration = 0;
613 
614  DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
615 
616  for (const Order *o = this->first; o != NULL; o = o->next) {
617  ++check_num_orders;
618  if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
619  check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
620  check_total_duration += o->GetWaitTime() + o->GetTravelTime();
621  }
622  assert(this->num_orders == check_num_orders);
623  assert(this->num_manual_orders == check_num_manual_orders);
624  assert(this->timetable_duration == check_timetable_duration);
625  assert(this->total_duration == check_total_duration);
626 
627  for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
628  ++check_num_vehicles;
629  assert(v->orders.list == this);
630  }
631  assert(this->num_vehicles == check_num_vehicles);
632  DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i timetabled, %i total",
633  (uint)this->num_orders, (uint)this->num_manual_orders,
634  this->num_vehicles, this->timetable_duration, this->total_duration);
635 }
636 
644 static inline bool OrderGoesToStation(const Vehicle *v, const Order *o)
645 {
646  return o->IsType(OT_GOTO_STATION) ||
647  (v->type == VEH_AIRCRAFT && o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotActionType() & ODATFB_NEAREST_DEPOT));
648 }
649 
656 static void DeleteOrderWarnings(const Vehicle *v)
657 {
658  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS);
659  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_VOID_ORDER);
660  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY);
661  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_INVALID_ENTRY);
662  DeleteVehicleNews(v->index, STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY);
663 }
664 
671 TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
672 {
673  switch (this->GetType()) {
674  case OT_GOTO_WAYPOINT:
675  case OT_GOTO_STATION:
676  case OT_IMPLICIT:
677  if (airport && v->type == VEH_AIRCRAFT) return Station::Get(this->GetDestination())->airport.tile;
678  return BaseStation::Get(this->GetDestination())->xy;
679 
680  case OT_GOTO_DEPOT:
681  if ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return INVALID_TILE;
682  return (v->type == VEH_AIRCRAFT) ? Station::Get(this->GetDestination())->xy : Depot::Get(this->GetDestination())->xy;
683 
684  default:
685  return INVALID_TILE;
686  }
687 }
688 
698 uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth)
699 {
700  if (cur->IsType(OT_CONDITIONAL)) {
701  if (conditional_depth > v->GetNumOrders()) return 0;
702 
703  conditional_depth++;
704 
705  int dist1 = GetOrderDistance(prev, v->GetOrder(cur->GetConditionSkipToOrder()), v, conditional_depth);
706  int dist2 = GetOrderDistance(prev, cur->next == NULL ? v->orders.list->GetFirstOrder() : cur->next, v, conditional_depth);
707  return max(dist1, dist2);
708  }
709 
710  TileIndex prev_tile = prev->GetLocation(v, true);
711  TileIndex cur_tile = cur->GetLocation(v, true);
712  if (prev_tile == INVALID_TILE || cur_tile == INVALID_TILE) return 0;
713  return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile);
714 }
715 
729 CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
730 {
731  VehicleID veh = GB(p1, 0, 20);
732  VehicleOrderID sel_ord = GB(p1, 20, 8);
733  Order new_order(p2);
734 
735  Vehicle *v = Vehicle::GetIfValid(veh);
736  if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
737 
738  CommandCost ret = CheckOwnership(v->owner);
739  if (ret.Failed()) return ret;
740 
741  /* Check if the inserted order is to the correct destination (owner, type),
742  * and has the correct flags if any */
743  switch (new_order.GetType()) {
744  case OT_GOTO_STATION: {
745  const Station *st = Station::GetIfValid(new_order.GetDestination());
746  if (st == NULL) return CMD_ERROR;
747 
748  if (st->owner != OWNER_NONE) {
749  CommandCost ret = CheckOwnership(st->owner);
750  if (ret.Failed()) return ret;
751  }
752 
753  if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
754  for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
755  if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED);
756  }
757 
758  /* Non stop only allowed for ground vehicles. */
759  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
760 
761  /* Filter invalid load/unload types. */
762  switch (new_order.GetLoadType()) {
764  default: return CMD_ERROR;
765  }
766  switch (new_order.GetUnloadType()) {
767  case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break;
768  default: return CMD_ERROR;
769  }
770 
771  /* Filter invalid stop locations */
772  switch (new_order.GetStopLocation()) {
774  case OSL_PLATFORM_MIDDLE:
775  if (v->type != VEH_TRAIN) return CMD_ERROR;
776  FALLTHROUGH;
777 
779  break;
780 
781  default:
782  return CMD_ERROR;
783  }
784 
785  break;
786  }
787 
788  case OT_GOTO_DEPOT: {
789  if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) {
790  if (v->type == VEH_AIRCRAFT) {
791  const Station *st = Station::GetIfValid(new_order.GetDestination());
792 
793  if (st == NULL) return CMD_ERROR;
794 
795  CommandCost ret = CheckOwnership(st->owner);
796  if (ret.Failed()) return ret;
797 
798  if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
799  return CMD_ERROR;
800  }
801  } else {
802  const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
803 
804  if (dp == NULL) return CMD_ERROR;
805 
806  CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
807  if (ret.Failed()) return ret;
808 
809  switch (v->type) {
810  case VEH_TRAIN:
811  if (!IsRailDepotTile(dp->xy)) return CMD_ERROR;
812  break;
813 
814  case VEH_ROAD:
815  if (!IsRoadDepotTile(dp->xy)) return CMD_ERROR;
816  break;
817 
818  case VEH_SHIP:
819  if (!IsShipDepotTile(dp->xy)) return CMD_ERROR;
820  break;
821 
822  default: return CMD_ERROR;
823  }
824  }
825  }
826 
827  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
828  if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
829  if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
830  if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
831  break;
832  }
833 
834  case OT_GOTO_WAYPOINT: {
835  const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
836  if (wp == NULL) return CMD_ERROR;
837 
838  switch (v->type) {
839  default: return CMD_ERROR;
840 
841  case VEH_TRAIN: {
842  if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
843 
844  CommandCost ret = CheckOwnership(wp->owner);
845  if (ret.Failed()) return ret;
846  break;
847  }
848 
849  case VEH_SHIP:
850  if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
851  if (wp->owner != OWNER_NONE) {
852  CommandCost ret = CheckOwnership(wp->owner);
853  if (ret.Failed()) return ret;
854  }
855  break;
856  }
857 
858  /* Order flags can be any of the following for waypoints:
859  * [non-stop]
860  * non-stop orders (if any) are only valid for trains */
861  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
862  break;
863  }
864 
865  case OT_CONDITIONAL: {
866  VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
867  if (skip_to != 0 && skip_to >= v->GetNumOrders()) return CMD_ERROR; // Always allow jumping to the first (even when there is no order).
868  if (new_order.GetConditionVariable() >= OCV_END) return CMD_ERROR;
869 
871  if (occ >= OCC_END) return CMD_ERROR;
872  switch (new_order.GetConditionVariable()) {
874  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
875  break;
876 
877  case OCV_UNCONDITIONALLY:
878  if (occ != OCC_EQUALS) return CMD_ERROR;
879  if (new_order.GetConditionValue() != 0) return CMD_ERROR;
880  break;
881 
882  case OCV_LOAD_PERCENTAGE:
883  case OCV_RELIABILITY:
884  if (new_order.GetConditionValue() > 100) return CMD_ERROR;
885  FALLTHROUGH;
886 
887  default:
888  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
889  break;
890  }
891  break;
892  }
893 
894  default: return CMD_ERROR;
895  }
896 
897  if (sel_ord > v->GetNumOrders()) return CMD_ERROR;
898 
899  if (v->GetNumOrders() >= MAX_VEH_ORDER_ID) return_cmd_error(STR_ERROR_TOO_MANY_ORDERS);
900  if (!Order::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
901  if (v->orders.list == NULL && !OrderList::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
902 
904  /* Make sure the new destination is not too far away from the previous */
905  const Order *prev = NULL;
906  uint n = 0;
907 
908  /* Find the last goto station or depot order before the insert location.
909  * If the order is to be inserted at the beginning of the order list this
910  * finds the last order in the list. */
911  const Order *o;
912  FOR_VEHICLE_ORDERS(v, o) {
913  switch (o->GetType()) {
914  case OT_GOTO_STATION:
915  case OT_GOTO_DEPOT:
916  case OT_GOTO_WAYPOINT:
917  prev = o;
918  break;
919 
920  default: break;
921  }
922  if (++n == sel_ord && prev != NULL) break;
923  }
924  if (prev != NULL) {
925  uint dist;
926  if (new_order.IsType(OT_CONDITIONAL)) {
927  /* The order is not yet inserted, so we have to do the first iteration here. */
928  dist = GetOrderDistance(prev, v->GetOrder(new_order.GetConditionSkipToOrder()), v);
929  } else {
930  dist = GetOrderDistance(prev, &new_order, v);
931  }
932 
933  if (dist >= SHIP_MAX_ORDER_DISTANCE) {
934  return_cmd_error(STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION);
935  }
936  }
937  }
938 
939  if (flags & DC_EXEC) {
940  Order *new_o = new Order();
941  new_o->AssignOrder(new_order);
942  InsertOrder(v, new_o, sel_ord);
943  }
944 
945  return CommandCost();
946 }
947 
954 void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
955 {
956  /* Create new order and link in list */
957  if (v->orders.list == NULL) {
958  v->orders.list = new OrderList(new_o, v);
959  } else {
960  v->orders.list->InsertOrderAt(new_o, sel_ord);
961  }
962 
963  Vehicle *u = v->FirstShared();
965  for (; u != NULL; u = u->NextShared()) {
966  assert(v->orders.list == u->orders.list);
967 
968  /* If there is added an order before the current one, we need
969  * to update the selected order. We do not change implicit/real order indices though.
970  * If the new order is between the current implicit order and real order, the implicit order will
971  * later skip the inserted order. */
972  if (sel_ord <= u->cur_real_order_index) {
973  uint cur = u->cur_real_order_index + 1;
974  /* Check if we don't go out of bound */
975  if (cur < u->GetNumOrders()) {
976  u->cur_real_order_index = cur;
977  }
978  }
979  if (sel_ord == u->cur_implicit_order_index && u->IsGroundVehicle()) {
980  /* We are inserting an order just before the current implicit order.
981  * We do not know whether we will reach current implicit or the newly inserted order first.
982  * So, disable creation of implicit orders until we are on track again. */
983  uint16 &gv_flags = u->GetGroundVehicleFlags();
985  }
986  if (sel_ord <= u->cur_implicit_order_index) {
987  uint cur = u->cur_implicit_order_index + 1;
988  /* Check if we don't go out of bound */
989  if (cur < u->GetNumOrders()) {
990  u->cur_implicit_order_index = cur;
991  }
992  }
993  /* Update any possible open window of the vehicle */
994  InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
995  }
996 
997  /* As we insert an order, the order to skip to will be 'wrong'. */
998  VehicleOrderID cur_order_id = 0;
999  Order *order;
1000  FOR_VEHICLE_ORDERS(v, order) {
1001  if (order->IsType(OT_CONDITIONAL)) {
1002  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1003  if (order_id >= sel_ord) {
1004  order->SetConditionSkipToOrder(order_id + 1);
1005  }
1006  if (order_id == cur_order_id) {
1007  order->SetConditionSkipToOrder((order_id + 1) % v->GetNumOrders());
1008  }
1009  }
1010  cur_order_id++;
1011  }
1012 
1013  /* Make sure to rebuild the whole list */
1015 }
1016 
1023 {
1024  if (flags & DC_EXEC) {
1025  DeleteVehicleOrders(dst);
1028  }
1029  return CommandCost();
1030 }
1031 
1041 CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1042 {
1043  VehicleID veh_id = GB(p1, 0, 20);
1044  VehicleOrderID sel_ord = GB(p2, 0, 8);
1045 
1046  Vehicle *v = Vehicle::GetIfValid(veh_id);
1047 
1048  if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
1049 
1050  CommandCost ret = CheckOwnership(v->owner);
1051  if (ret.Failed()) return ret;
1052 
1053  /* If we did not select an order, we maybe want to de-clone the orders */
1054  if (sel_ord >= v->GetNumOrders()) return DecloneOrder(v, flags);
1055 
1056  if (v->GetOrder(sel_ord) == NULL) return CMD_ERROR;
1057 
1058  if (flags & DC_EXEC) DeleteOrder(v, sel_ord);
1059  return CommandCost();
1060 }
1061 
1067 {
1068  assert(v->current_order.IsType(OT_LOADING));
1069  /* NON-stop flag is misused to see if a train is in a station that is
1070  * on his order list or not */
1072  /* When full loading, "cancel" that order so the vehicle doesn't
1073  * stay indefinitely at this station anymore. */
1075 }
1076 
1083 {
1084  v->orders.list->DeleteOrderAt(sel_ord);
1085 
1086  Vehicle *u = v->FirstShared();
1088  for (; u != NULL; u = u->NextShared()) {
1089  assert(v->orders.list == u->orders.list);
1090 
1091  if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
1093  }
1094 
1095  if (sel_ord < u->cur_real_order_index) {
1096  u->cur_real_order_index--;
1097  } else if (sel_ord == u->cur_real_order_index) {
1098  u->UpdateRealOrderIndex();
1099  }
1100 
1101  if (sel_ord < u->cur_implicit_order_index) {
1103  } else if (sel_ord == u->cur_implicit_order_index) {
1104  /* Make sure the index is valid */
1106 
1107  /* Skip non-implicit orders for the implicit-order-index (e.g. if the current implicit order was deleted */
1108  while (u->cur_implicit_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_implicit_order_index)->IsType(OT_IMPLICIT)) {
1111  }
1112  }
1113 
1114  /* Update any possible open window of the vehicle */
1115  InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
1116  }
1117 
1118  /* As we delete an order, the order to skip to will be 'wrong'. */
1119  VehicleOrderID cur_order_id = 0;
1120  Order *order = NULL;
1121  FOR_VEHICLE_ORDERS(v, order) {
1122  if (order->IsType(OT_CONDITIONAL)) {
1123  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1124  if (order_id >= sel_ord) {
1125  order_id = max(order_id - 1, 0);
1126  }
1127  if (order_id == cur_order_id) {
1128  order_id = (order_id + 1) % v->GetNumOrders();
1129  }
1130  order->SetConditionSkipToOrder(order_id);
1131  }
1132  cur_order_id++;
1133  }
1134 
1136 }
1137 
1147 CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1148 {
1149  VehicleID veh_id = GB(p1, 0, 20);
1150  VehicleOrderID sel_ord = GB(p2, 0, 8);
1151 
1152  Vehicle *v = Vehicle::GetIfValid(veh_id);
1153 
1154  if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_implicit_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
1155 
1156  CommandCost ret = CheckOwnership(v->owner);
1157  if (ret.Failed()) return ret;
1158 
1159  if (flags & DC_EXEC) {
1160  if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
1161 
1163  v->UpdateRealOrderIndex();
1164 
1166  }
1167 
1168  /* We have an aircraft/ship, they have a mini-schedule, so update them all */
1171 
1172  return CommandCost();
1173 }
1174 
1188 CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1189 {
1190  VehicleID veh = GB(p1, 0, 20);
1191  VehicleOrderID moving_order = GB(p2, 0, 16);
1192  VehicleOrderID target_order = GB(p2, 16, 16);
1193 
1194  Vehicle *v = Vehicle::GetIfValid(veh);
1195  if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
1196 
1197  CommandCost ret = CheckOwnership(v->owner);
1198  if (ret.Failed()) return ret;
1199 
1200  /* Don't make senseless movements */
1201  if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() ||
1202  moving_order == target_order || v->GetNumOrders() <= 1) return CMD_ERROR;
1203 
1204  Order *moving_one = v->GetOrder(moving_order);
1205  /* Don't move an empty order */
1206  if (moving_one == NULL) return CMD_ERROR;
1207 
1208  if (flags & DC_EXEC) {
1209  v->orders.list->MoveOrder(moving_order, target_order);
1210 
1211  /* Update shared list */
1212  Vehicle *u = v->FirstShared();
1213 
1215 
1216  for (; u != NULL; u = u->NextShared()) {
1217  /* Update the current order.
1218  * There are multiple ways to move orders, which result in cur_implicit_order_index
1219  * and cur_real_order_index to not longer make any sense. E.g. moving another
1220  * real order between them.
1221  *
1222  * Basically one could choose to preserve either of them, but not both.
1223  * While both ways are suitable in this or that case from a human point of view, neither
1224  * of them makes really sense.
1225  * However, from an AI point of view, preserving cur_real_order_index is the most
1226  * predictable and transparent behaviour.
1227  *
1228  * With that decision it basically does not matter what we do to cur_implicit_order_index.
1229  * If we change orders between the implicit- and real-index, the implicit orders are mostly likely
1230  * completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well.
1231  * The worst which can happen is that a lot of implicit orders are removed when reaching current_order.
1232  */
1233  if (u->cur_real_order_index == moving_order) {
1234  u->cur_real_order_index = target_order;
1235  } else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) {
1236  u->cur_real_order_index--;
1237  } else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) {
1238  u->cur_real_order_index++;
1239  }
1240 
1241  if (u->cur_implicit_order_index == moving_order) {
1242  u->cur_implicit_order_index = target_order;
1243  } else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) {
1245  } else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
1247  }
1248 
1249  assert(v->orders.list == u->orders.list);
1250  /* Update any possible open window of the vehicle */
1251  InvalidateVehicleOrder(u, moving_order | (target_order << 8));
1252  }
1253 
1254  /* As we move an order, the order to skip to will be 'wrong'. */
1255  Order *order;
1256  FOR_VEHICLE_ORDERS(v, order) {
1257  if (order->IsType(OT_CONDITIONAL)) {
1258  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1259  if (order_id == moving_order) {
1260  order_id = target_order;
1261  } else if (order_id > moving_order && order_id <= target_order) {
1262  order_id--;
1263  } else if (order_id < moving_order && order_id >= target_order) {
1264  order_id++;
1265  }
1266  order->SetConditionSkipToOrder(order_id);
1267  }
1268  }
1269 
1270  /* Make sure to rebuild the whole list */
1272  }
1273 
1274  return CommandCost();
1275 }
1276 
1292 CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1293 {
1294  VehicleOrderID sel_ord = GB(p1, 20, 8);
1295  VehicleID veh = GB(p1, 0, 20);
1296  ModifyOrderFlags mof = Extract<ModifyOrderFlags, 0, 4>(p2);
1297  uint16 data = GB(p2, 4, 11);
1298 
1299  if (mof >= MOF_END) return CMD_ERROR;
1300 
1301  Vehicle *v = Vehicle::GetIfValid(veh);
1302  if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
1303 
1304  CommandCost ret = CheckOwnership(v->owner);
1305  if (ret.Failed()) return ret;
1306 
1307  /* Is it a valid order? */
1308  if (sel_ord >= v->GetNumOrders()) return CMD_ERROR;
1309 
1310  Order *order = v->GetOrder(sel_ord);
1311  switch (order->GetType()) {
1312  case OT_GOTO_STATION:
1313  if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD) return CMD_ERROR;
1314  break;
1315 
1316  case OT_GOTO_DEPOT:
1317  if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
1318  break;
1319 
1320  case OT_GOTO_WAYPOINT:
1321  if (mof != MOF_NON_STOP) return CMD_ERROR;
1322  break;
1323 
1324  case OT_CONDITIONAL:
1325  if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR;
1326  break;
1327 
1328  default:
1329  return CMD_ERROR;
1330  }
1331 
1332  switch (mof) {
1333  default: NOT_REACHED();
1334 
1335  case MOF_NON_STOP:
1336  if (!v->IsGroundVehicle()) return CMD_ERROR;
1337  if (data >= ONSF_END) return CMD_ERROR;
1338  if (data == order->GetNonStopType()) return CMD_ERROR;
1339  break;
1340 
1341  case MOF_STOP_LOCATION:
1342  if (v->type != VEH_TRAIN) return CMD_ERROR;
1343  if (data >= OSL_END) return CMD_ERROR;
1344  break;
1345 
1346  case MOF_UNLOAD:
1348  if ((data & ~(OUFB_UNLOAD | OUFB_TRANSFER | OUFB_NO_UNLOAD)) != 0) return CMD_ERROR;
1349  /* Unload and no-unload are mutual exclusive and so are transfer and no unload. */
1350  if (data != 0 && ((data & (OUFB_UNLOAD | OUFB_TRANSFER)) != 0) == ((data & OUFB_NO_UNLOAD) != 0)) return CMD_ERROR;
1351  if (data == order->GetUnloadType()) return CMD_ERROR;
1352  break;
1353 
1354  case MOF_LOAD:
1356  if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
1357  if (data == order->GetLoadType()) return CMD_ERROR;
1358  break;
1359 
1360  case MOF_DEPOT_ACTION:
1361  if (data >= DA_END) return CMD_ERROR;
1362  break;
1363 
1364  case MOF_COND_VARIABLE:
1365  if (data >= OCV_END) return CMD_ERROR;
1366  break;
1367 
1368  case MOF_COND_COMPARATOR:
1369  if (data >= OCC_END) return CMD_ERROR;
1370  switch (order->GetConditionVariable()) {
1371  case OCV_UNCONDITIONALLY: return CMD_ERROR;
1372 
1373  case OCV_REQUIRES_SERVICE:
1374  if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
1375  break;
1376 
1377  default:
1378  if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
1379  break;
1380  }
1381  break;
1382 
1383  case MOF_COND_VALUE:
1384  switch (order->GetConditionVariable()) {
1385  case OCV_UNCONDITIONALLY:
1386  case OCV_REQUIRES_SERVICE:
1387  return CMD_ERROR;
1388 
1389  case OCV_LOAD_PERCENTAGE:
1390  case OCV_RELIABILITY:
1391  if (data > 100) return CMD_ERROR;
1392  break;
1393 
1394  default:
1395  if (data > 2047) return CMD_ERROR;
1396  break;
1397  }
1398  break;
1399 
1400  case MOF_COND_DESTINATION:
1401  if (data >= v->GetNumOrders()) return CMD_ERROR;
1402  break;
1403  }
1404 
1405  if (flags & DC_EXEC) {
1406  switch (mof) {
1407  case MOF_NON_STOP:
1408  order->SetNonStopType((OrderNonStopFlags)data);
1410  order->SetRefit(CT_NO_REFIT);
1413  }
1414  break;
1415 
1416  case MOF_STOP_LOCATION:
1417  order->SetStopLocation((OrderStopLocation)data);
1418  break;
1419 
1420  case MOF_UNLOAD:
1421  order->SetUnloadType((OrderUnloadFlags)data);
1422  break;
1423 
1424  case MOF_LOAD:
1425  order->SetLoadType((OrderLoadFlags)data);
1426  if (data & OLFB_NO_LOAD) order->SetRefit(CT_NO_REFIT);
1427  break;
1428 
1429  case MOF_DEPOT_ACTION: {
1430  switch (data) {
1431  case DA_ALWAYS_GO:
1434  break;
1435 
1436  case DA_SERVICE:
1439  order->SetRefit(CT_NO_REFIT);
1440  break;
1441 
1442  case DA_STOP:
1445  order->SetRefit(CT_NO_REFIT);
1446  break;
1447 
1448  default:
1449  NOT_REACHED();
1450  }
1451  break;
1452  }
1453 
1454  case MOF_COND_VARIABLE: {
1456 
1458  switch (order->GetConditionVariable()) {
1459  case OCV_UNCONDITIONALLY:
1461  order->SetConditionValue(0);
1462  break;
1463 
1464  case OCV_REQUIRES_SERVICE:
1465  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
1466  order->SetConditionValue(0);
1467  break;
1468 
1469  case OCV_LOAD_PERCENTAGE:
1470  case OCV_RELIABILITY:
1471  if (order->GetConditionValue() > 100) order->SetConditionValue(100);
1472  FALLTHROUGH;
1473 
1474  default:
1475  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
1476  break;
1477  }
1478  break;
1479  }
1480 
1481  case MOF_COND_COMPARATOR:
1483  break;
1484 
1485  case MOF_COND_VALUE:
1486  order->SetConditionValue(data);
1487  break;
1488 
1489  case MOF_COND_DESTINATION:
1490  order->SetConditionSkipToOrder(data);
1491  break;
1492 
1493  default: NOT_REACHED();
1494  }
1495 
1496  /* Update the windows and full load flags, also for vehicles that share the same order list */
1497  Vehicle *u = v->FirstShared();
1499  for (; u != NULL; u = u->NextShared()) {
1500  /* Toggle u->current_order "Full load" flag if it changed.
1501  * However, as the same flag is used for depot orders, check
1502  * whether we are not going to a depot as there are three
1503  * cases where the full load flag can be active and only
1504  * one case where the flag is used for depot orders. In the
1505  * other cases for the OrderTypeByte the flags are not used,
1506  * so do not care and those orders should not be active
1507  * when this function is called.
1508  */
1509  if (sel_ord == u->cur_real_order_index &&
1510  (u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
1511  u->current_order.GetLoadType() != order->GetLoadType()) {
1512  u->current_order.SetLoadType(order->GetLoadType());
1513  }
1515  }
1516  }
1517 
1518  return CommandCost();
1519 }
1520 
1528 static bool CheckAircraftOrderDistance(const Aircraft *v_new, const Vehicle *v_order, const Order *first)
1529 {
1530  if (first == NULL || v_new->acache.cached_max_range == 0) return true;
1531 
1532  /* Iterate over all orders to check the distance between all
1533  * 'goto' orders and their respective next order (of any type). */
1534  for (const Order *o = first; o != NULL; o = o->next) {
1535  switch (o->GetType()) {
1536  case OT_GOTO_STATION:
1537  case OT_GOTO_DEPOT:
1538  case OT_GOTO_WAYPOINT:
1539  /* If we don't have a next order, we've reached the end and must check the first order instead. */
1540  if (GetOrderDistance(o, o->next != NULL ? o->next : first, v_order) > v_new->acache.cached_max_range_sqr) return false;
1541  break;
1542 
1543  default: break;
1544  }
1545  }
1546 
1547  return true;
1548 }
1549 
1561 CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1562 {
1563  VehicleID veh_src = GB(p2, 0, 20);
1564  VehicleID veh_dst = GB(p1, 0, 20);
1565 
1566  Vehicle *dst = Vehicle::GetIfValid(veh_dst);
1567  if (dst == NULL || !dst->IsPrimaryVehicle()) return CMD_ERROR;
1568 
1569  CommandCost ret = CheckOwnership(dst->owner);
1570  if (ret.Failed()) return ret;
1571 
1572  switch (GB(p1, 30, 2)) {
1573  case CO_SHARE: {
1574  Vehicle *src = Vehicle::GetIfValid(veh_src);
1575 
1576  /* Sanity checks */
1577  if (src == NULL || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1578 
1579  CommandCost ret = CheckOwnership(src->owner);
1580  if (ret.Failed()) return ret;
1581 
1582  /* Trucks can't share orders with busses (and visa versa) */
1583  if (src->type == VEH_ROAD && RoadVehicle::From(src)->IsBus() != RoadVehicle::From(dst)->IsBus()) {
1584  return CMD_ERROR;
1585  }
1586 
1587  /* Is the vehicle already in the shared list? */
1588  if (src->FirstShared() == dst->FirstShared()) return CMD_ERROR;
1589 
1590  const Order *order;
1591 
1592  FOR_VEHICLE_ORDERS(src, order) {
1593  if (!OrderGoesToStation(dst, order)) continue;
1594 
1595  /* Allow copying unreachable destinations if they were already unreachable for the source.
1596  * This is basically to allow cloning / autorenewing / autoreplacing vehicles, while the stations
1597  * are temporarily invalid due to reconstruction. */
1598  const Station *st = Station::Get(order->GetDestination());
1599  if (CanVehicleUseStation(src, st) && !CanVehicleUseStation(dst, st)) {
1600  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1601  }
1602  }
1603 
1604  /* Check for aircraft range limits. */
1605  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1606  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1607  }
1608 
1609  if (src->orders.list == NULL && !OrderList::CanAllocateItem()) {
1610  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1611  }
1612 
1613  if (flags & DC_EXEC) {
1614  /* If the destination vehicle had a OrderList, destroy it.
1615  * We only reset the order indices, if the new orders are obviously different.
1616  * (We mainly do this to keep the order indices valid and in range.) */
1617  DeleteVehicleOrders(dst, false, dst->GetNumOrders() != src->GetNumOrders());
1618 
1619  dst->orders.list = src->orders.list;
1620 
1621  /* Link this vehicle in the shared-list */
1622  dst->AddToShared(src);
1623 
1626 
1628  }
1629  break;
1630  }
1631 
1632  case CO_COPY: {
1633  Vehicle *src = Vehicle::GetIfValid(veh_src);
1634 
1635  /* Sanity checks */
1636  if (src == NULL || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1637 
1638  CommandCost ret = CheckOwnership(src->owner);
1639  if (ret.Failed()) return ret;
1640 
1641  /* Trucks can't copy all the orders from busses (and visa versa),
1642  * and neither can helicopters and aircraft. */
1643  const Order *order;
1644  FOR_VEHICLE_ORDERS(src, order) {
1645  if (OrderGoesToStation(dst, order) &&
1647  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1648  }
1649  }
1650 
1651  /* Check for aircraft range limits. */
1652  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1653  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1654  }
1655 
1656  /* make sure there are orders available */
1658  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1659  }
1660 
1661  if (flags & DC_EXEC) {
1662  const Order *order;
1663  Order *first = NULL;
1664  Order **order_dst;
1665 
1666  /* If the destination vehicle had an order list, destroy the chain but keep the OrderList.
1667  * We only reset the order indices, if the new orders are obviously different.
1668  * (We mainly do this to keep the order indices valid and in range.) */
1669  DeleteVehicleOrders(dst, true, dst->GetNumOrders() != src->GetNumOrders());
1670 
1671  order_dst = &first;
1672  FOR_VEHICLE_ORDERS(src, order) {
1673  *order_dst = new Order();
1674  (*order_dst)->AssignOrder(*order);
1675  order_dst = &(*order_dst)->next;
1676  }
1677  if (dst->orders.list == NULL) {
1678  dst->orders.list = new OrderList(first, dst);
1679  } else {
1680  assert(dst->orders.list->GetFirstOrder() == NULL);
1681  assert(!dst->orders.list->IsShared());
1682  delete dst->orders.list;
1683  assert(OrderList::CanAllocateItem());
1684  dst->orders.list = new OrderList(first, dst);
1685  }
1686 
1688 
1690  }
1691  break;
1692  }
1693 
1694  case CO_UNSHARE: return DecloneOrder(dst, flags);
1695  default: return CMD_ERROR;
1696  }
1697 
1698  return CommandCost();
1699 }
1700 
1712 CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1713 {
1714  VehicleID veh = GB(p1, 0, 20);
1715  VehicleOrderID order_number = GB(p2, 16, 8);
1716  CargoID cargo = GB(p2, 0, 8);
1717 
1718  if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT && cargo != CT_AUTO_REFIT) return CMD_ERROR;
1719 
1720  const Vehicle *v = Vehicle::GetIfValid(veh);
1721  if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
1722 
1723  CommandCost ret = CheckOwnership(v->owner);
1724  if (ret.Failed()) return ret;
1725 
1726  Order *order = v->GetOrder(order_number);
1727  if (order == NULL) return CMD_ERROR;
1728 
1729  /* Automatic refit cargo is only supported for goto station orders. */
1730  if (cargo == CT_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
1731 
1732  if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
1733 
1734  if (flags & DC_EXEC) {
1735  order->SetRefit(cargo);
1736 
1737  /* Make the depot order an 'always go' order. */
1738  if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
1741  }
1742 
1743  for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
1744  /* Update any possible open window of the vehicle */
1746 
1747  /* If the vehicle already got the current depot set as current order, then update current order as well */
1748  if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
1749  u->current_order.SetRefit(cargo);
1750  }
1751  }
1752  }
1753 
1754  return CommandCost();
1755 }
1756 
1757 
1763 void CheckOrders(const Vehicle *v)
1764 {
1765  /* Does the user wants us to check things? */
1766  if (_settings_client.gui.order_review_system == 0) return;
1767 
1768  /* Do nothing for crashed vehicles */
1769  if (v->vehstatus & VS_CRASHED) return;
1770 
1771  /* Do nothing for stopped vehicles if setting is '1' */
1772  if (_settings_client.gui.order_review_system == 1 && (v->vehstatus & VS_STOPPED)) return;
1773 
1774  /* do nothing we we're not the first vehicle in a share-chain */
1775  if (v->FirstShared() != v) return;
1776 
1777  /* Only check every 20 days, so that we don't flood the message log */
1778  if (v->owner == _local_company && v->day_counter % 20 == 0) {
1779  const Order *order;
1780  StringID message = INVALID_STRING_ID;
1781 
1782  /* Check the order list */
1783  int n_st = 0;
1784 
1785  FOR_VEHICLE_ORDERS(v, order) {
1786  /* Dummy order? */
1787  if (order->IsType(OT_DUMMY)) {
1788  message = STR_NEWS_VEHICLE_HAS_VOID_ORDER;
1789  break;
1790  }
1791  /* Does station have a load-bay for this vehicle? */
1792  if (order->IsType(OT_GOTO_STATION)) {
1793  const Station *st = Station::Get(order->GetDestination());
1794 
1795  n_st++;
1796  if (!CanVehicleUseStation(v, st)) {
1797  message = STR_NEWS_VEHICLE_HAS_INVALID_ENTRY;
1798  } else if (v->type == VEH_AIRCRAFT &&
1799  (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1802  message == INVALID_STRING_ID) {
1803  message = STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY;
1804  }
1805  }
1806  }
1807 
1808  /* Check if the last and the first order are the same */
1809  if (v->GetNumOrders() > 1) {
1810  const Order *last = v->GetLastOrder();
1811 
1812  if (v->orders.list->GetFirstOrder()->Equals(*last)) {
1813  message = STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY;
1814  }
1815  }
1816 
1817  /* Do we only have 1 station in our order list? */
1818  if (n_st < 2 && message == INVALID_STRING_ID) message = STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS;
1819 
1820 #ifndef NDEBUG
1821  if (v->orders.list != NULL) v->orders.list->DebugCheckSanity();
1822 #endif
1823 
1824  /* We don't have a problem */
1825  if (message == INVALID_STRING_ID) return;
1826 
1827  SetDParam(0, v->index);
1828  AddVehicleAdviceNewsItem(message, v->index);
1829  }
1830 }
1831 
1840 void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
1841 {
1842  Vehicle *v;
1843 
1844  /* Aircraft have StationIDs for depot orders and never use DepotIDs
1845  * This fact is handled specially below
1846  */
1847 
1848  /* Go through all vehicles */
1849  FOR_ALL_VEHICLES(v) {
1850  Order *order;
1851 
1852  order = &v->current_order;
1853  if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
1854  (!hangar || v->type == VEH_AIRCRAFT) && v->current_order.GetDestination() == destination) {
1855  order->MakeDummy();
1857  }
1858 
1859  /* Clear the order from the order-list */
1860  int id = -1;
1861  FOR_VEHICLE_ORDERS(v, order) {
1862  id++;
1863 restart:
1864 
1865  OrderType ot = order->GetType();
1866  if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
1867  if (ot == OT_GOTO_DEPOT && hangar && v->type != VEH_AIRCRAFT) continue; // Not an aircraft? Can't have a hangar order.
1868  if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
1869  if (ot == type && order->GetDestination() == destination) {
1870  /* We want to clear implicit orders, but we don't want to make them
1871  * dummy orders. They should just vanish. Also check the actual order
1872  * type as ot is currently OT_GOTO_STATION. */
1873  if (order->IsType(OT_IMPLICIT)) {
1874  order = order->next; // DeleteOrder() invalidates current order
1875  DeleteOrder(v, id);
1876  if (order != NULL) goto restart;
1877  break;
1878  }
1879 
1880  /* Clear wait time */
1881  v->orders.list->UpdateTotalDuration(-order->GetWaitTime());
1882  if (order->IsWaitTimetabled()) {
1884  order->SetWaitTimetabled(false);
1885  }
1886  order->SetWaitTime(0);
1887 
1888  /* Clear order, preserving travel time */
1889  bool travel_timetabled = order->IsTravelTimetabled();
1890  order->MakeDummy();
1891  order->SetTravelTimetabled(travel_timetabled);
1892 
1893  for (const Vehicle *w = v->FirstShared(); w != NULL; w = w->NextShared()) {
1894  /* In GUI, simulate by removing the order and adding it back */
1897  }
1898  }
1899  }
1900  }
1901 
1902  OrderBackup::RemoveOrder(type, destination, hangar);
1903 }
1904 
1910 {
1911  const Order *order;
1912 
1913  FOR_VEHICLE_ORDERS(this, order) {
1914  if (order->IsType(OT_GOTO_DEPOT)) return true;
1915  }
1916 
1917  return false;
1918 }
1919 
1929 void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
1930 {
1932 
1933  if (v->IsOrderListShared()) {
1934  /* Remove ourself from the shared order list. */
1935  v->RemoveFromShared();
1936  v->orders.list = NULL;
1937  } else if (v->orders.list != NULL) {
1938  /* Remove the orders */
1939  v->orders.list->FreeChain(keep_orderlist);
1940  if (!keep_orderlist) v->orders.list = NULL;
1941  }
1942 
1943  if (reset_order_indices) {
1945  if (v->current_order.IsType(OT_LOADING)) {
1947  }
1948  }
1949 }
1950 
1957 uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
1958 {
1959  return ispercent ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
1960 }
1961 
1970 static bool CheckForValidOrders(const Vehicle *v)
1971 {
1972  const Order *order;
1973 
1974  FOR_VEHICLE_ORDERS(v, order) {
1975  switch (order->GetType()) {
1976  case OT_GOTO_STATION:
1977  case OT_GOTO_DEPOT:
1978  case OT_GOTO_WAYPOINT:
1979  return true;
1980 
1981  default:
1982  break;
1983  }
1984  }
1985 
1986  return false;
1987 }
1988 
1992 static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
1993 {
1994  switch (occ) {
1995  case OCC_EQUALS: return variable == value;
1996  case OCC_NOT_EQUALS: return variable != value;
1997  case OCC_LESS_THAN: return variable < value;
1998  case OCC_LESS_EQUALS: return variable <= value;
1999  case OCC_MORE_THAN: return variable > value;
2000  case OCC_MORE_EQUALS: return variable >= value;
2001  case OCC_IS_TRUE: return variable != 0;
2002  case OCC_IS_FALSE: return variable == 0;
2003  default: NOT_REACHED();
2004  }
2005 }
2006 
2014 {
2015  if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
2016 
2017  bool skip_order = false;
2019  uint16 value = order->GetConditionValue();
2020 
2021  switch (order->GetConditionVariable()) {
2022  case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
2023  case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
2024  case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
2025  case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
2026  case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / DAYS_IN_LEAP_YEAR, value); break;
2027  case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
2028  case OCV_UNCONDITIONALLY: skip_order = true; break;
2029  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;
2030  default: NOT_REACHED();
2031  }
2032 
2033  return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
2034 }
2035 
2043 bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
2044 {
2045  if (conditional_depth > v->GetNumOrders()) {
2046  v->current_order.Free();
2047  v->SetDestTile(0);
2048  return false;
2049  }
2050 
2051  switch (order->GetType()) {
2052  case OT_GOTO_STATION:
2053  v->SetDestTile(v->GetOrderStationLocation(order->GetDestination()));
2054  return true;
2055 
2056  case OT_GOTO_DEPOT:
2057  if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
2058  assert(!pbs_look_ahead);
2059  UpdateVehicleTimetable(v, true);
2061  break;
2062  }
2063 
2065  /* We need to search for the nearest depot (hangar). */
2066  TileIndex location;
2067  DestinationID destination;
2068  bool reverse;
2069 
2070  if (v->FindClosestDepot(&location, &destination, &reverse)) {
2071  /* PBS reservations cannot reverse */
2072  if (pbs_look_ahead && reverse) return false;
2073 
2074  v->SetDestTile(location);
2076 
2077  /* If there is no depot in front, reverse automatically (trains only) */
2078  if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2079 
2080  if (v->type == VEH_AIRCRAFT) {
2081  Aircraft *a = Aircraft::From(v);
2082  if (a->state == FLYING && a->targetairport != destination) {
2083  /* The aircraft is now heading for a different hangar than the next in the orders */
2086  }
2087  }
2088  return true;
2089  }
2090 
2091  /* If there is no depot, we cannot help PBS either. */
2092  if (pbs_look_ahead) return false;
2093 
2094  UpdateVehicleTimetable(v, true);
2096  } else {
2097  if (v->type != VEH_AIRCRAFT) {
2098  v->SetDestTile(Depot::Get(order->GetDestination())->xy);
2099  } else {
2100  Aircraft *a = Aircraft::From(v);
2101  DestinationID destination = a->current_order.GetDestination();
2102  if (a->targetairport != destination) {
2103  /* The aircraft is now heading for a different hangar than the next in the orders */
2104  a->SetDestTile(a->GetOrderStationLocation(destination));
2105  }
2106  }
2107  return true;
2108  }
2109  break;
2110 
2111  case OT_GOTO_WAYPOINT:
2112  v->SetDestTile(Waypoint::Get(order->GetDestination())->xy);
2113  return true;
2114 
2115  case OT_CONDITIONAL: {
2116  assert(!pbs_look_ahead);
2117  VehicleOrderID next_order = ProcessConditionalOrder(order, v);
2118  if (next_order != INVALID_VEH_ORDER_ID) {
2119  /* Jump to next_order. cur_implicit_order_index becomes exactly that order,
2120  * cur_real_order_index might come after next_order. */
2121  UpdateVehicleTimetable(v, false);
2122  v->cur_implicit_order_index = v->cur_real_order_index = next_order;
2123  v->UpdateRealOrderIndex();
2125 
2126  /* Disable creation of implicit orders.
2127  * When inserting them we do not know that we would have to make the conditional orders point to them. */
2128  if (v->IsGroundVehicle()) {
2129  uint16 &gv_flags = v->GetGroundVehicleFlags();
2131  }
2132  } else {
2133  UpdateVehicleTimetable(v, true);
2135  }
2136  break;
2137  }
2138 
2139  default:
2140  v->SetDestTile(0);
2141  return false;
2142  }
2143 
2144  assert(v->cur_implicit_order_index < v->GetNumOrders());
2145  assert(v->cur_real_order_index < v->GetNumOrders());
2146 
2147  /* Get the current order */
2148  order = v->GetOrder(v->cur_real_order_index);
2149  if (order != NULL && order->IsType(OT_IMPLICIT)) {
2150  assert(v->GetNumManualOrders() == 0);
2151  order = NULL;
2152  }
2153 
2154  if (order == NULL) {
2155  v->current_order.Free();
2156  v->SetDestTile(0);
2157  return false;
2158  }
2159 
2160  v->current_order = *order;
2161  return UpdateOrderDest(v, order, conditional_depth + 1, pbs_look_ahead);
2162 }
2163 
2172 {
2173  switch (v->current_order.GetType()) {
2174  case OT_GOTO_DEPOT:
2175  /* Let a depot order in the orderlist interrupt. */
2176  if (!(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return false;
2177  break;
2178 
2179  case OT_LOADING:
2180  return false;
2181 
2182  case OT_LEAVESTATION:
2183  if (v->type != VEH_AIRCRAFT) return false;
2184  break;
2185 
2186  default: break;
2187  }
2188 
2196  bool may_reverse = v->current_order.IsType(OT_NOTHING);
2197 
2198  /* Check if we've reached a 'via' destination. */
2199  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)) &&
2200  IsTileType(v->tile, MP_STATION) &&
2203  /* We set the last visited station here because we do not want
2204  * the train to stop at this 'via' station if the next order
2205  * is a no-non-stop order; in that case not setting the last
2206  * visited station will cause the vehicle to still stop. */
2208  UpdateVehicleTimetable(v, true);
2210  }
2211 
2212  /* Get the current order */
2213  assert(v->cur_implicit_order_index == 0 || v->cur_implicit_order_index < v->GetNumOrders());
2214  v->UpdateRealOrderIndex();
2215 
2216  const Order *order = v->GetOrder(v->cur_real_order_index);
2217  if (order != NULL && order->IsType(OT_IMPLICIT)) {
2218  assert(v->GetNumManualOrders() == 0);
2219  order = NULL;
2220  }
2221 
2222  /* If no order, do nothing. */
2223  if (order == NULL || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
2224  if (v->type == VEH_AIRCRAFT) {
2225  /* Aircraft do something vastly different here, so handle separately */
2226  extern void HandleMissingAircraftOrders(Aircraft *v);
2227  HandleMissingAircraftOrders(Aircraft::From(v));
2228  return false;
2229  }
2230 
2231  v->current_order.Free();
2232  v->SetDestTile(0);
2233  return false;
2234  }
2235 
2236  /* If it is unchanged, keep it. */
2237  if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
2238  (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->dock_tile != INVALID_TILE)) {
2239  return false;
2240  }
2241 
2242  /* Otherwise set it, and determine the destination tile. */
2243  v->current_order = *order;
2244 
2246  switch (v->type) {
2247  default:
2248  NOT_REACHED();
2249 
2250  case VEH_ROAD:
2251  case VEH_TRAIN:
2252  break;
2253 
2254  case VEH_AIRCRAFT:
2255  case VEH_SHIP:
2257  break;
2258  }
2259 
2260  return UpdateOrderDest(v, order) && may_reverse;
2261 }
2262 
2270 bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
2271 {
2272  bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
2273 
2274  return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
2275  v->last_station_visited != station && // Do stop only when we've not just been there
2276  /* Finally do stop when there is no non-stop flag set for this type of station. */
2278 }
2279 
2280 bool Order::CanLoadOrUnload() const
2281 {
2282  return (this->IsType(OT_GOTO_STATION) || this->IsType(OT_IMPLICIT)) &&
2284  ((this->GetLoadType() & OLFB_NO_LOAD) == 0 ||
2285  (this->GetUnloadType() & OUFB_NO_UNLOAD) == 0);
2286 }
2287 
2294 bool Order::CanLeaveWithCargo(bool has_cargo) const
2295 {
2296  return (this->GetLoadType() & OLFB_NO_LOAD) == 0 || (has_cargo &&
2297  (this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0);
2298 }
OrderConditionVariable
Variables (of a vehicle) to &#39;cause&#39; skipping on.
Definition: order_type.h:118
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
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:151
void InsertOrderAt(Order *new_order, int index)
Insert a new order into the order chain.
Definition: order_cmd.cpp:462
bool IsVehicleInSharedOrdersList(const Vehicle *v) const
Checks whether a vehicle is part of the shared vehicle chain.
Definition: order_cmd.cpp:568
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:77
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:1041
uint16 DepotID
Type for the unique identifier of depots.
Definition: depot_type.h:15
Passes an OrderUnloadType.
Definition: order_type.h:152
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:3201
Skip if both values are equal.
Definition: order_type.h:134
Load as long as there is cargo that fits in the train.
Definition: order_type.h:69
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:1957
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:1763
Functions related to time tabling.
bool HasHangar() const
Check if this airport has at least one hangar.
Definition: station_base.h:338
void InvalidateVehicleOrder(const Vehicle *v, int data)
Updates the widgets of a vehicle which contains the order-data.
Definition: order_cmd.cpp:253
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:332
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
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:154
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:140
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:593
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:120
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:954
Stop at the middle of the platform.
Definition: order_type.h:91
A comparator changes.
Definition: order_type.h:156
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
PathfinderSettings pf
settings for all pathfinders
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
Process a conditional order and determine the next order.
Definition: order_cmd.cpp:2013
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:167
Flags flags
Flags for this airport type.
Definition: airport.h:181
Unload all cargo that the station accepts.
Definition: order_type.h:59
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2179
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:1929
OrderNonStopFlags
Non-stop order flags.
Definition: order_type.h:78
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:139
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:210
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:122
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:370
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:671
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:744
bool CanLeaveWithCargo(bool has_cargo) const
A vehicle can leave the current station with cargo if:
Definition: order_cmd.cpp:2294
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:1082
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:81
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:698
Stop at the near end of the platform.
Definition: order_type.h:90
Order * next
Pointer to next order. If NULL, 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:500
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:675
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Order * GetOrderAt(int index) const
Get a certain order of the order chain.
Definition: order_cmd.cpp:347
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:526
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:92
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:79
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:3319
StationIDStack GetNextStoppingStation(const Vehicle *v, const Order *first=NULL, uint hops=0) const
Recursively determine the next deterministic station to stop at.
Definition: order_cmd.cpp:405
void MakeConditional(VehicleOrderID order)
Makes this order an conditional order.
Definition: order_cmd.cpp:145
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:2270
Passes an OrderStopLocation.
Definition: order_type.h:151
void RemoveVehicle(Vehicle *v)
Removes the vehicle from the shared order list.
Definition: order_cmd.cpp:558
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:1022
Vehicle orders; Window numbers:
Definition: window_type.h:207
Aircraft vehicle type.
Definition: vehicle_type.h:29
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
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:440
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition: order_cmd.cpp:156
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:802
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:135
Do not load anything.
Definition: order_type.h:72
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:343
Skip if the value is less or equal to the limit.
Definition: order_type.h:137
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:729
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
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:158
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2171
Always skip.
Definition: order_type.h:124
Base of waypoints.
void MakeLoading(bool ordered)
Makes this order a Loading order.
Definition: order_cmd.cpp:117
static bool IsRoadDepotTile(TileIndex t)
Return whether a tile is a road depot tile.
Definition: road_map.h:99
void FreeChain(bool keep_orderlist=false)
Free a complete order chain.
Definition: order_cmd.cpp:324
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:108
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:1188
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2689
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:293
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
New PathFinder.
Definition: vehicle_type.h:64
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.
The tile has no ownership.
Definition: company_type.h:27
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:2781
OrderConditionComparator
Comparator for the skip reasoning.
Definition: order_type.h:133
Always go to the depot.
Definition: order_type.h:167
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:110
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
StationFacilityByte facilities
The facilities that this station has.
bool Equals(const Order &other) const
Does this order have the same type, flags and destination?
Definition: order_cmd.cpp:177
Road vehicle type.
Definition: vehicle_type.h:27
static bool IsShipDepotTile(TileIndex t)
Is it a ship depot tile?
Definition: water_map.h:226
Service only if needed.
Definition: order_type.h:168
Station with a dock.
Definition: station_type.h:58
Order * GetLastOrder() const
Returns the last order of a vehicle, or NULL 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:1066
CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Goto order of order-list.
Definition: order_cmd.cpp:1147
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:2043
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:1292
The value to set the condition to.
Definition: order_type.h:157
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
Compare the variable and value based on the given comparator.
Definition: order_cmd.cpp:1992
Skip based on the remaining lifetime.
Definition: order_type.h:125
Skip if the value is less than the limit.
Definition: order_type.h:136
OrderType
Order types.
Definition: order_type.h:37
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:656
Transfer all cargo onto the platform.
Definition: order_type.h:61
#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
Ship vehicle type.
Definition: vehicle_type.h:28
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:36
Skip when the vehicle requires service.
Definition: order_type.h:123
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:1909
OwnerByte owner
The owner of this station.
OrderUnloadFlags
Flags related to the unloading order.
Definition: order_type.h:58
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
union Vehicle::@47 orders
The orders currently assigned to the vehicle.
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:2712
execute the given command
Definition: command_type.h:345
A conditional variable changes.
Definition: order_type.h:155
Functions related to companies.
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:29
OrderStopLocation
Where to stop the trains.
Definition: order_type.h:89
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:150
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:106
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:92
static bool CheckForValidOrders(const Vehicle *v)
Check if a vehicle has any valid orders.
Definition: order_cmd.cpp:1970
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.
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:135
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:68
void MakeLeaveStation()
Makes this order a Leave Station order.
Definition: order_cmd.cpp:126
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:644
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:111
int32 Ticks
The type to store ticks in.
Definition: date_type.h:18
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:65
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
turn a train around
Definition: command_type.h:223
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:70
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition: vehicle.cpp:1993
A tile of a station.
Definition: tile_type.h:48
Skip based on the amount of load.
Definition: order_type.h:119
int GetPositionInSharedOrderList(const Vehicle *v) const
Gets the position of the given vehicle within the shared order vehicle list.
Definition: order_cmd.cpp:582
Station with train station.
Definition: station_type.h:54
Totally no unloading will be done.
Definition: order_type.h:62
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:275
The vehicle will not stop at any stations it passes except the destination.
Definition: order_type.h:80
Skip based on the maximum speed.
Definition: order_type.h:121
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:2856
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:1712
uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition: vehicle.cpp:1378
void DebugCheckSanity() const
Checks for internal consistency of order list.
Definition: order_cmd.cpp:606
Passes an OrderLoadType.
Definition: order_type.h:153
ModifyOrderFlags
Enumeration for the data to set in CmdModifyOrder.
Definition: order_type.h:149
Base for ships.
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:85
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:1561
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or NULL 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
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:1528
Airport airport
Tile area the airport covers.
Definition: station_base.h:460
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:106
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:200
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition: order_cmd.cpp:1840
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
Force unloading all cargo onto the platform, possibly not getting paid.
Definition: order_type.h:60
uint8 pathfinder_for_ships
the pathfinder to use for ships
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:3229
This depot order is because of a regular order.
Definition: order_type.h:102
Functions related to news.
Go to the depot and stop there.
Definition: order_type.h:169
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:138
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:71
This depot order is because of the servicing limit.
Definition: order_type.h:101
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:29
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:56
Skip if the variable is false.
Definition: order_type.h:141
Skip based on the maximum reliability.
Definition: order_type.h:126
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:446
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...
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:3301
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:77
OrderDepotTypeFlags
Reasons that could cause us to go to the depot.
Definition: order_type.h:99
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
Train vehicle type.
Definition: vehicle_type.h:26
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.