OpenTTD Source  1.10.0-RC1
order_cmd.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "debug.h"
12 #include "cmd_helper.h"
13 #include "command_func.h"
14 #include "company_func.h"
15 #include "news_func.h"
16 #include "strings_func.h"
17 #include "timetable.h"
18 #include "vehicle_func.h"
19 #include "depot_base.h"
20 #include "core/pool_func.hpp"
21 #include "core/random_func.hpp"
22 #include "aircraft.h"
23 #include "roadveh.h"
24 #include "station_base.h"
25 #include "waypoint_base.h"
26 #include "company_base.h"
27 #include "order_backup.h"
28 #include "cheat_type.h"
29 
30 #include "table/strings.h"
31 
32 #include "safeguards.h"
33 
34 /* DestinationID must be at least as large as every these below, because it can
35  * be any of them
36  */
37 assert_compile(sizeof(DestinationID) >= sizeof(DepotID));
38 assert_compile(sizeof(DestinationID) >= sizeof(StationID));
39 
40 OrderPool _order_pool("Order");
42 OrderListPool _orderlist_pool("OrderList");
44 
45 
47 {
48  if (CleaningPool()) return;
49 
50  /* We can visit oil rigs and buoys that are not our own. They will be shown in
51  * the list of stations. So, we need to invalidate that window if needed. */
52  if (this->IsType(OT_GOTO_STATION) || this->IsType(OT_GOTO_WAYPOINT)) {
53  BaseStation *bs = BaseStation::GetIfValid(this->GetDestination());
54  if (bs != nullptr && bs->owner == OWNER_NONE) InvalidateWindowClassesData(WC_STATION_LIST, 0);
55  }
56 }
57 
63 {
64  this->type = OT_NOTHING;
65  this->flags = 0;
66  this->dest = 0;
67  this->next = nullptr;
68 }
69 
74 void Order::MakeGoToStation(StationID destination)
75 {
76  this->type = OT_GOTO_STATION;
77  this->flags = 0;
78  this->dest = destination;
79 }
80 
90 {
91  this->type = OT_GOTO_DEPOT;
92  this->SetDepotOrderType(order);
93  this->SetDepotActionType(action);
94  this->SetNonStopType(non_stop_type);
95  this->dest = destination;
96  this->SetRefit(cargo);
97 }
98 
103 void Order::MakeGoToWaypoint(StationID destination)
104 {
105  this->type = OT_GOTO_WAYPOINT;
106  this->flags = 0;
107  this->dest = destination;
108 }
109 
114 void Order::MakeLoading(bool ordered)
115 {
116  this->type = OT_LOADING;
117  if (!ordered) this->flags = 0;
118 }
119 
124 {
125  this->type = OT_LEAVESTATION;
126  this->flags = 0;
127 }
128 
133 {
134  this->type = OT_DUMMY;
135  this->flags = 0;
136 }
137 
143 {
144  this->type = OT_CONDITIONAL;
145  this->flags = order;
146  this->dest = 0;
147 }
148 
153 void Order::MakeImplicit(StationID destination)
154 {
155  this->type = OT_IMPLICIT;
156  this->dest = destination;
157 }
158 
165 {
166  this->refit_cargo = cargo;
167 }
168 
174 bool Order::Equals(const Order &other) const
175 {
176  /* In case of go to nearest depot orders we need "only" compare the flags
177  * with the other and not the nearest depot order bit or the actual
178  * destination because those get clear/filled in during the order
179  * evaluation. If we do not do this the order will continuously be seen as
180  * a different order and it will try to find a "nearest depot" every tick. */
181  if ((this->IsType(OT_GOTO_DEPOT) && this->type == other.type) &&
182  ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0 ||
183  (other.GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0)) {
184  return this->GetDepotOrderType() == other.GetDepotOrderType() &&
186  }
187 
188  return this->type == other.type && this->flags == other.flags && this->dest == other.dest;
189 }
190 
197 uint32 Order::Pack() const
198 {
199  return this->dest << 16 | this->flags << 8 | this->type;
200 }
201 
207 uint16 Order::MapOldOrder() const
208 {
209  uint16 order = this->GetType();
210  switch (this->type) {
211  case OT_GOTO_STATION:
212  if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
213  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
215  order |= GB(this->GetDestination(), 0, 8) << 8;
216  break;
217  case OT_GOTO_DEPOT:
218  if (!(this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) SetBit(order, 6);
219  SetBit(order, 7);
220  order |= GB(this->GetDestination(), 0, 8) << 8;
221  break;
222  case OT_LOADING:
223  if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
224  break;
225  }
226  return order;
227 }
228 
233 Order::Order(uint32 packed)
234 {
235  this->type = (OrderType)GB(packed, 0, 8);
236  this->flags = GB(packed, 8, 8);
237  this->dest = GB(packed, 16, 16);
238  this->next = nullptr;
239  this->refit_cargo = CT_NO_REFIT;
240  this->wait_time = 0;
241  this->travel_time = 0;
242  this->max_speed = UINT16_MAX;
243 }
244 
250 void InvalidateVehicleOrder(const Vehicle *v, int data)
251 {
253 
254  if (data != 0) {
255  /* Calls SetDirty() too */
258  return;
259  }
260 
263 }
264 
272 void Order::AssignOrder(const Order &other)
273 {
274  this->type = other.type;
275  this->flags = other.flags;
276  this->dest = other.dest;
277 
278  this->refit_cargo = other.refit_cargo;
279 
280  this->wait_time = other.wait_time;
281  this->travel_time = other.travel_time;
282  this->max_speed = other.max_speed;
283 }
284 
291 {
292  this->first = chain;
293  this->first_shared = v;
294 
295  this->num_orders = 0;
296  this->num_manual_orders = 0;
297  this->num_vehicles = 1;
298  this->timetable_duration = 0;
299 
300  for (Order *o = this->first; o != nullptr; o = o->next) {
301  ++this->num_orders;
302  if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
303  this->total_duration += o->GetWaitTime() + o->GetTravelTime();
304  }
305 
306  this->RecalculateTimetableDuration();
307 
308  for (Vehicle *u = this->first_shared->PreviousShared(); u != nullptr; u = u->PreviousShared()) {
309  ++this->num_vehicles;
310  this->first_shared = u;
311  }
312 
313  for (const Vehicle *u = v->NextShared(); u != nullptr; u = u->NextShared()) ++this->num_vehicles;
314 }
315 
321 {
322  this->timetable_duration = 0;
323  for (Order *o = this->first; o != nullptr; o = o->next) {
324  this->timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
325  }
326 }
327 
333 void OrderList::FreeChain(bool keep_orderlist)
334 {
335  Order *next;
336  for (Order *o = this->first; o != nullptr; o = next) {
337  next = o->next;
338  delete o;
339  }
340 
341  if (keep_orderlist) {
342  this->first = nullptr;
343  this->num_orders = 0;
344  this->num_manual_orders = 0;
345  this->timetable_duration = 0;
346  } else {
347  delete this;
348  }
349 }
350 
357 {
358  if (index < 0) return nullptr;
359 
360  Order *order = this->first;
361 
362  while (order != nullptr && index-- > 0) {
363  order = order->next;
364  }
365  return order;
366 }
367 
379 const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops) const
380 {
381  if (hops > this->GetNumOrders() || next == nullptr) return nullptr;
382 
383  if (next->IsType(OT_CONDITIONAL)) {
384  if (next->GetConditionVariable() != OCV_UNCONDITIONALLY) return next;
385 
386  /* We can evaluate trivial conditions right away. They're conceptually
387  * the same as regular order progression. */
388  return this->GetNextDecisionNode(
389  this->GetOrderAt(next->GetConditionSkipToOrder()),
390  hops + 1);
391  }
392 
393  if (next->IsType(OT_GOTO_DEPOT)) {
394  if (next->GetDepotActionType() == ODATFB_HALT) return nullptr;
395  if (next->IsRefit()) return next;
396  }
397 
398  if (!next->CanLoadOrUnload()) {
399  return this->GetNextDecisionNode(this->GetNext(next), hops + 1);
400  }
401 
402  return next;
403 }
404 
414 StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, const Order *first, uint hops) const
415 {
416 
417  const Order *next = first;
418  if (first == nullptr) {
419  next = this->GetOrderAt(v->cur_implicit_order_index);
420  if (next == nullptr) {
421  next = this->GetFirstOrder();
422  if (next == nullptr) return INVALID_STATION;
423  } else {
424  /* GetNext never returns nullptr if there is a valid station in the list.
425  * As the given "next" is already valid and a station in the list, we
426  * don't have to check for nullptr here. */
427  next = this->GetNext(next);
428  assert(next != nullptr);
429  }
430  }
431 
432  do {
433  next = this->GetNextDecisionNode(next, ++hops);
434 
435  /* Resolve possibly nested conditionals by estimation. */
436  while (next != nullptr && next->IsType(OT_CONDITIONAL)) {
437  /* We return both options of conditional orders. */
438  const Order *skip_to = this->GetNextDecisionNode(
439  this->GetOrderAt(next->GetConditionSkipToOrder()), hops);
440  const Order *advance = this->GetNextDecisionNode(
441  this->GetNext(next), hops);
442  if (advance == nullptr || advance == first || skip_to == advance) {
443  next = (skip_to == first) ? nullptr : skip_to;
444  } else if (skip_to == nullptr || skip_to == first) {
445  next = (advance == first) ? nullptr : advance;
446  } else {
447  StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops);
448  StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops);
449  while (!st2.IsEmpty()) st1.Push(st2.Pop());
450  return st1;
451  }
452  ++hops;
453  }
454 
455  /* Don't return a next stop if the vehicle has to unload everything. */
456  if (next == nullptr || ((next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) &&
457  next->GetDestination() == v->last_station_visited &&
458  (next->GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) {
459  return INVALID_STATION;
460  }
461  } while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);
462 
463  return next->GetDestination();
464 }
465 
471 void OrderList::InsertOrderAt(Order *new_order, int index)
472 {
473  if (this->first == nullptr) {
474  this->first = new_order;
475  } else {
476  if (index == 0) {
477  /* Insert as first or only order */
478  new_order->next = this->first;
479  this->first = new_order;
480  } else if (index >= this->num_orders) {
481  /* index is after the last order, add it to the end */
482  this->GetLastOrder()->next = new_order;
483  } else {
484  /* Put the new order in between */
485  Order *order = this->GetOrderAt(index - 1);
486  new_order->next = order->next;
487  order->next = new_order;
488  }
489  }
490  ++this->num_orders;
491  if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
492  this->timetable_duration += new_order->GetTimetabledWait() + new_order->GetTimetabledTravel();
493  this->total_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
494 
495  /* We can visit oil rigs and buoys that are not our own. They will be shown in
496  * the list of stations. So, we need to invalidate that window if needed. */
497  if (new_order->IsType(OT_GOTO_STATION) || new_order->IsType(OT_GOTO_WAYPOINT)) {
498  BaseStation *bs = BaseStation::Get(new_order->GetDestination());
500  }
501 
502 }
503 
504 
510 {
511  if (index >= this->num_orders) return;
512 
513  Order *to_remove;
514 
515  if (index == 0) {
516  to_remove = this->first;
517  this->first = to_remove->next;
518  } else {
519  Order *prev = GetOrderAt(index - 1);
520  to_remove = prev->next;
521  prev->next = to_remove->next;
522  }
523  --this->num_orders;
524  if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
525  this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
526  this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
527  delete to_remove;
528 }
529 
535 void OrderList::MoveOrder(int from, int to)
536 {
537  if (from >= this->num_orders || to >= this->num_orders || from == to) return;
538 
539  Order *moving_one;
540 
541  /* Take the moving order out of the pointer-chain */
542  if (from == 0) {
543  moving_one = this->first;
544  this->first = moving_one->next;
545  } else {
546  Order *one_before = GetOrderAt(from - 1);
547  moving_one = one_before->next;
548  one_before->next = moving_one->next;
549  }
550 
551  /* Insert the moving_order again in the pointer-chain */
552  if (to == 0) {
553  moving_one->next = this->first;
554  this->first = moving_one;
555  } else {
556  Order *one_before = GetOrderAt(to - 1);
557  moving_one->next = one_before->next;
558  one_before->next = moving_one;
559  }
560 }
561 
568 {
569  --this->num_vehicles;
570  if (v == this->first_shared) this->first_shared = v->NextShared();
571 }
572 
578 {
579  for (const Vehicle *v_shared = this->first_shared; v_shared != nullptr; v_shared = v_shared->NextShared()) {
580  if (v_shared == v) return true;
581  }
582 
583  return false;
584 }
585 
592 {
593  int count = 0;
594  for (const Vehicle *v_shared = v->PreviousShared(); v_shared != nullptr; v_shared = v_shared->PreviousShared()) count++;
595  return count;
596 }
597 
603 {
604  for (Order *o = this->first; o != nullptr; o = o->next) {
605  /* Implicit orders are, by definition, not timetabled. */
606  if (o->IsType(OT_IMPLICIT)) continue;
607  if (!o->IsCompletelyTimetabled()) return false;
608  }
609  return true;
610 }
611 
616 {
617  VehicleOrderID check_num_orders = 0;
618  VehicleOrderID check_num_manual_orders = 0;
619  uint check_num_vehicles = 0;
620  Ticks check_timetable_duration = 0;
621  Ticks check_total_duration = 0;
622 
623  DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
624 
625  for (const Order *o = this->first; o != nullptr; o = o->next) {
626  ++check_num_orders;
627  if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
628  check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
629  check_total_duration += o->GetWaitTime() + o->GetTravelTime();
630  }
631  assert(this->num_orders == check_num_orders);
632  assert(this->num_manual_orders == check_num_manual_orders);
633  assert(this->timetable_duration == check_timetable_duration);
634  assert(this->total_duration == check_total_duration);
635 
636  for (const Vehicle *v = this->first_shared; v != nullptr; v = v->NextShared()) {
637  ++check_num_vehicles;
638  assert(v->orders.list == this);
639  }
640  assert(this->num_vehicles == check_num_vehicles);
641  DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i timetabled, %i total",
642  (uint)this->num_orders, (uint)this->num_manual_orders,
643  this->num_vehicles, this->timetable_duration, this->total_duration);
644 }
645 
653 static inline bool OrderGoesToStation(const Vehicle *v, const Order *o)
654 {
655  return o->IsType(OT_GOTO_STATION) ||
656  (v->type == VEH_AIRCRAFT && o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotActionType() & ODATFB_NEAREST_DEPOT));
657 }
658 
665 static void DeleteOrderWarnings(const Vehicle *v)
666 {
667  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS);
668  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_VOID_ORDER);
669  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY);
670  DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_INVALID_ENTRY);
671  DeleteVehicleNews(v->index, STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY);
672 }
673 
680 TileIndex Order::GetLocation(const Vehicle *v, bool airport) const
681 {
682  switch (this->GetType()) {
683  case OT_GOTO_WAYPOINT:
684  case OT_GOTO_STATION:
685  case OT_IMPLICIT:
686  if (airport && v->type == VEH_AIRCRAFT) return Station::Get(this->GetDestination())->airport.tile;
687  return BaseStation::Get(this->GetDestination())->xy;
688 
689  case OT_GOTO_DEPOT:
690  if ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return INVALID_TILE;
691  return (v->type == VEH_AIRCRAFT) ? Station::Get(this->GetDestination())->xy : Depot::Get(this->GetDestination())->xy;
692 
693  default:
694  return INVALID_TILE;
695  }
696 }
697 
707 uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth)
708 {
709  if (cur->IsType(OT_CONDITIONAL)) {
710  if (conditional_depth > v->GetNumOrders()) return 0;
711 
712  conditional_depth++;
713 
714  int dist1 = GetOrderDistance(prev, v->GetOrder(cur->GetConditionSkipToOrder()), v, conditional_depth);
715  int dist2 = GetOrderDistance(prev, cur->next == nullptr ? v->orders.list->GetFirstOrder() : cur->next, v, conditional_depth);
716  return max(dist1, dist2);
717  }
718 
719  TileIndex prev_tile = prev->GetLocation(v, true);
720  TileIndex cur_tile = cur->GetLocation(v, true);
721  if (prev_tile == INVALID_TILE || cur_tile == INVALID_TILE) return 0;
722  return v->type == VEH_AIRCRAFT ? DistanceSquare(prev_tile, cur_tile) : DistanceManhattan(prev_tile, cur_tile);
723 }
724 
738 CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
739 {
740  VehicleID veh = GB(p1, 0, 20);
741  VehicleOrderID sel_ord = GB(p1, 20, 8);
742  Order new_order(p2);
743 
744  Vehicle *v = Vehicle::GetIfValid(veh);
745  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
746 
747  CommandCost ret = CheckOwnership(v->owner);
748  if (ret.Failed()) return ret;
749 
750  /* Check if the inserted order is to the correct destination (owner, type),
751  * and has the correct flags if any */
752  switch (new_order.GetType()) {
753  case OT_GOTO_STATION: {
754  const Station *st = Station::GetIfValid(new_order.GetDestination());
755  if (st == nullptr) return CMD_ERROR;
756 
757  if (st->owner != OWNER_NONE) {
758  CommandCost ret = CheckOwnership(st->owner);
759  if (ret.Failed()) return ret;
760  }
761 
762  if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
763  for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
764  if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED);
765  }
766 
767  /* Non stop only allowed for ground vehicles. */
768  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
769 
770  /* Filter invalid load/unload types. */
771  switch (new_order.GetLoadType()) {
773  default: return CMD_ERROR;
774  }
775  switch (new_order.GetUnloadType()) {
776  case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break;
777  default: return CMD_ERROR;
778  }
779 
780  /* Filter invalid stop locations */
781  switch (new_order.GetStopLocation()) {
783  case OSL_PLATFORM_MIDDLE:
784  if (v->type != VEH_TRAIN) return CMD_ERROR;
785  FALLTHROUGH;
786 
788  break;
789 
790  default:
791  return CMD_ERROR;
792  }
793 
794  break;
795  }
796 
797  case OT_GOTO_DEPOT: {
798  if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) {
799  if (v->type == VEH_AIRCRAFT) {
800  const Station *st = Station::GetIfValid(new_order.GetDestination());
801 
802  if (st == nullptr) return CMD_ERROR;
803 
804  CommandCost ret = CheckOwnership(st->owner);
805  if (ret.Failed()) return ret;
806 
807  if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
808  return CMD_ERROR;
809  }
810  } else {
811  const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
812 
813  if (dp == nullptr) return CMD_ERROR;
814 
815  CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
816  if (ret.Failed()) return ret;
817 
818  switch (v->type) {
819  case VEH_TRAIN:
820  if (!IsRailDepotTile(dp->xy)) return CMD_ERROR;
821  break;
822 
823  case VEH_ROAD:
824  if (!IsRoadDepotTile(dp->xy)) return CMD_ERROR;
825  break;
826 
827  case VEH_SHIP:
828  if (!IsShipDepotTile(dp->xy)) return CMD_ERROR;
829  break;
830 
831  default: return CMD_ERROR;
832  }
833  }
834  }
835 
836  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
837  if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
838  if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
839  if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
840  break;
841  }
842 
843  case OT_GOTO_WAYPOINT: {
844  const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
845  if (wp == nullptr) return CMD_ERROR;
846 
847  switch (v->type) {
848  default: return CMD_ERROR;
849 
850  case VEH_TRAIN: {
851  if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
852 
853  CommandCost ret = CheckOwnership(wp->owner);
854  if (ret.Failed()) return ret;
855  break;
856  }
857 
858  case VEH_SHIP:
859  if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
860  if (wp->owner != OWNER_NONE) {
861  CommandCost ret = CheckOwnership(wp->owner);
862  if (ret.Failed()) return ret;
863  }
864  break;
865  }
866 
867  /* Order flags can be any of the following for waypoints:
868  * [non-stop]
869  * non-stop orders (if any) are only valid for trains */
870  if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
871  break;
872  }
873 
874  case OT_CONDITIONAL: {
875  VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
876  if (skip_to != 0 && skip_to >= v->GetNumOrders()) return CMD_ERROR; // Always allow jumping to the first (even when there is no order).
877  if (new_order.GetConditionVariable() >= OCV_END) return CMD_ERROR;
878 
880  if (occ >= OCC_END) return CMD_ERROR;
881  switch (new_order.GetConditionVariable()) {
883  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
884  break;
885 
886  case OCV_UNCONDITIONALLY:
887  if (occ != OCC_EQUALS) return CMD_ERROR;
888  if (new_order.GetConditionValue() != 0) return CMD_ERROR;
889  break;
890 
891  case OCV_LOAD_PERCENTAGE:
892  case OCV_RELIABILITY:
893  if (new_order.GetConditionValue() > 100) return CMD_ERROR;
894  FALLTHROUGH;
895 
896  default:
897  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
898  break;
899  }
900  break;
901  }
902 
903  default: return CMD_ERROR;
904  }
905 
906  if (sel_ord > v->GetNumOrders()) return CMD_ERROR;
907 
908  if (v->GetNumOrders() >= MAX_VEH_ORDER_ID) return_cmd_error(STR_ERROR_TOO_MANY_ORDERS);
909  if (!Order::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
910  if (v->orders.list == nullptr && !OrderList::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
911 
912  if (flags & DC_EXEC) {
913  Order *new_o = new Order();
914  new_o->AssignOrder(new_order);
915  InsertOrder(v, new_o, sel_ord);
916  }
917 
918  return CommandCost();
919 }
920 
927 void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
928 {
929  /* Create new order and link in list */
930  if (v->orders.list == nullptr) {
931  v->orders.list = new OrderList(new_o, v);
932  } else {
933  v->orders.list->InsertOrderAt(new_o, sel_ord);
934  }
935 
936  Vehicle *u = v->FirstShared();
938  for (; u != nullptr; u = u->NextShared()) {
939  assert(v->orders.list == u->orders.list);
940 
941  /* If there is added an order before the current one, we need
942  * to update the selected order. We do not change implicit/real order indices though.
943  * If the new order is between the current implicit order and real order, the implicit order will
944  * later skip the inserted order. */
945  if (sel_ord <= u->cur_real_order_index) {
946  uint cur = u->cur_real_order_index + 1;
947  /* Check if we don't go out of bound */
948  if (cur < u->GetNumOrders()) {
949  u->cur_real_order_index = cur;
950  }
951  }
952  if (sel_ord == u->cur_implicit_order_index && u->IsGroundVehicle()) {
953  /* We are inserting an order just before the current implicit order.
954  * We do not know whether we will reach current implicit or the newly inserted order first.
955  * So, disable creation of implicit orders until we are on track again. */
956  uint16 &gv_flags = u->GetGroundVehicleFlags();
958  }
959  if (sel_ord <= u->cur_implicit_order_index) {
960  uint cur = u->cur_implicit_order_index + 1;
961  /* Check if we don't go out of bound */
962  if (cur < u->GetNumOrders()) {
963  u->cur_implicit_order_index = cur;
964  }
965  }
966  /* Update any possible open window of the vehicle */
967  InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
968  }
969 
970  /* As we insert an order, the order to skip to will be 'wrong'. */
971  VehicleOrderID cur_order_id = 0;
972  Order *order;
973  FOR_VEHICLE_ORDERS(v, order) {
974  if (order->IsType(OT_CONDITIONAL)) {
975  VehicleOrderID order_id = order->GetConditionSkipToOrder();
976  if (order_id >= sel_ord) {
977  order->SetConditionSkipToOrder(order_id + 1);
978  }
979  if (order_id == cur_order_id) {
980  order->SetConditionSkipToOrder((order_id + 1) % v->GetNumOrders());
981  }
982  }
983  cur_order_id++;
984  }
985 
986  /* Make sure to rebuild the whole list */
988 }
989 
996 {
997  if (flags & DC_EXEC) {
998  DeleteVehicleOrders(dst);
1001  }
1002  return CommandCost();
1003 }
1004 
1014 CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1015 {
1016  VehicleID veh_id = GB(p1, 0, 20);
1017  VehicleOrderID sel_ord = GB(p2, 0, 8);
1018 
1019  Vehicle *v = Vehicle::GetIfValid(veh_id);
1020 
1021  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1022 
1023  CommandCost ret = CheckOwnership(v->owner);
1024  if (ret.Failed()) return ret;
1025 
1026  /* If we did not select an order, we maybe want to de-clone the orders */
1027  if (sel_ord >= v->GetNumOrders()) return DecloneOrder(v, flags);
1028 
1029  if (v->GetOrder(sel_ord) == nullptr) return CMD_ERROR;
1030 
1031  if (flags & DC_EXEC) DeleteOrder(v, sel_ord);
1032  return CommandCost();
1033 }
1034 
1040 {
1041  assert(v->current_order.IsType(OT_LOADING));
1042  /* NON-stop flag is misused to see if a train is in a station that is
1043  * on his order list or not */
1045  /* When full loading, "cancel" that order so the vehicle doesn't
1046  * stay indefinitely at this station anymore. */
1048 }
1049 
1056 {
1057  v->orders.list->DeleteOrderAt(sel_ord);
1058 
1059  Vehicle *u = v->FirstShared();
1061  for (; u != nullptr; u = u->NextShared()) {
1062  assert(v->orders.list == u->orders.list);
1063 
1064  if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
1066  }
1067 
1068  if (sel_ord < u->cur_real_order_index) {
1069  u->cur_real_order_index--;
1070  } else if (sel_ord == u->cur_real_order_index) {
1071  u->UpdateRealOrderIndex();
1072  }
1073 
1074  if (sel_ord < u->cur_implicit_order_index) {
1076  } else if (sel_ord == u->cur_implicit_order_index) {
1077  /* Make sure the index is valid */
1079 
1080  /* Skip non-implicit orders for the implicit-order-index (e.g. if the current implicit order was deleted */
1081  while (u->cur_implicit_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_implicit_order_index)->IsType(OT_IMPLICIT)) {
1084  }
1085  }
1086 
1087  /* Update any possible open window of the vehicle */
1088  InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
1089  }
1090 
1091  /* As we delete an order, the order to skip to will be 'wrong'. */
1092  VehicleOrderID cur_order_id = 0;
1093  Order *order = nullptr;
1094  FOR_VEHICLE_ORDERS(v, order) {
1095  if (order->IsType(OT_CONDITIONAL)) {
1096  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1097  if (order_id >= sel_ord) {
1098  order_id = max(order_id - 1, 0);
1099  }
1100  if (order_id == cur_order_id) {
1101  order_id = (order_id + 1) % v->GetNumOrders();
1102  }
1103  order->SetConditionSkipToOrder(order_id);
1104  }
1105  cur_order_id++;
1106  }
1107 
1109 }
1110 
1120 CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1121 {
1122  VehicleID veh_id = GB(p1, 0, 20);
1123  VehicleOrderID sel_ord = GB(p2, 0, 8);
1124 
1125  Vehicle *v = Vehicle::GetIfValid(veh_id);
1126 
1127  if (v == nullptr || !v->IsPrimaryVehicle() || sel_ord == v->cur_implicit_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
1128 
1129  CommandCost ret = CheckOwnership(v->owner);
1130  if (ret.Failed()) return ret;
1131 
1132  if (flags & DC_EXEC) {
1133  if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
1134 
1136  v->UpdateRealOrderIndex();
1137 
1139  }
1140 
1141  /* We have an aircraft/ship, they have a mini-schedule, so update them all */
1144 
1145  return CommandCost();
1146 }
1147 
1161 CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1162 {
1163  VehicleID veh = GB(p1, 0, 20);
1164  VehicleOrderID moving_order = GB(p2, 0, 16);
1165  VehicleOrderID target_order = GB(p2, 16, 16);
1166 
1167  Vehicle *v = Vehicle::GetIfValid(veh);
1168  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1169 
1170  CommandCost ret = CheckOwnership(v->owner);
1171  if (ret.Failed()) return ret;
1172 
1173  /* Don't make senseless movements */
1174  if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() ||
1175  moving_order == target_order || v->GetNumOrders() <= 1) return CMD_ERROR;
1176 
1177  Order *moving_one = v->GetOrder(moving_order);
1178  /* Don't move an empty order */
1179  if (moving_one == nullptr) return CMD_ERROR;
1180 
1181  if (flags & DC_EXEC) {
1182  v->orders.list->MoveOrder(moving_order, target_order);
1183 
1184  /* Update shared list */
1185  Vehicle *u = v->FirstShared();
1186 
1188 
1189  for (; u != nullptr; u = u->NextShared()) {
1190  /* Update the current order.
1191  * There are multiple ways to move orders, which result in cur_implicit_order_index
1192  * and cur_real_order_index to not longer make any sense. E.g. moving another
1193  * real order between them.
1194  *
1195  * Basically one could choose to preserve either of them, but not both.
1196  * While both ways are suitable in this or that case from a human point of view, neither
1197  * of them makes really sense.
1198  * However, from an AI point of view, preserving cur_real_order_index is the most
1199  * predictable and transparent behaviour.
1200  *
1201  * With that decision it basically does not matter what we do to cur_implicit_order_index.
1202  * If we change orders between the implicit- and real-index, the implicit orders are mostly likely
1203  * completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well.
1204  * The worst which can happen is that a lot of implicit orders are removed when reaching current_order.
1205  */
1206  if (u->cur_real_order_index == moving_order) {
1207  u->cur_real_order_index = target_order;
1208  } else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) {
1209  u->cur_real_order_index--;
1210  } else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) {
1211  u->cur_real_order_index++;
1212  }
1213 
1214  if (u->cur_implicit_order_index == moving_order) {
1215  u->cur_implicit_order_index = target_order;
1216  } else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) {
1218  } else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
1220  }
1221 
1222  assert(v->orders.list == u->orders.list);
1223  /* Update any possible open window of the vehicle */
1224  InvalidateVehicleOrder(u, moving_order | (target_order << 8));
1225  }
1226 
1227  /* As we move an order, the order to skip to will be 'wrong'. */
1228  Order *order;
1229  FOR_VEHICLE_ORDERS(v, order) {
1230  if (order->IsType(OT_CONDITIONAL)) {
1231  VehicleOrderID order_id = order->GetConditionSkipToOrder();
1232  if (order_id == moving_order) {
1233  order_id = target_order;
1234  } else if (order_id > moving_order && order_id <= target_order) {
1235  order_id--;
1236  } else if (order_id < moving_order && order_id >= target_order) {
1237  order_id++;
1238  }
1239  order->SetConditionSkipToOrder(order_id);
1240  }
1241  }
1242 
1243  /* Make sure to rebuild the whole list */
1245  }
1246 
1247  return CommandCost();
1248 }
1249 
1265 CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1266 {
1267  VehicleOrderID sel_ord = GB(p1, 20, 8);
1268  VehicleID veh = GB(p1, 0, 20);
1269  ModifyOrderFlags mof = Extract<ModifyOrderFlags, 0, 4>(p2);
1270  uint16 data = GB(p2, 4, 11);
1271 
1272  if (mof >= MOF_END) return CMD_ERROR;
1273 
1274  Vehicle *v = Vehicle::GetIfValid(veh);
1275  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1276 
1277  CommandCost ret = CheckOwnership(v->owner);
1278  if (ret.Failed()) return ret;
1279 
1280  /* Is it a valid order? */
1281  if (sel_ord >= v->GetNumOrders()) return CMD_ERROR;
1282 
1283  Order *order = v->GetOrder(sel_ord);
1284  switch (order->GetType()) {
1285  case OT_GOTO_STATION:
1286  if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD) return CMD_ERROR;
1287  break;
1288 
1289  case OT_GOTO_DEPOT:
1290  if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
1291  break;
1292 
1293  case OT_GOTO_WAYPOINT:
1294  if (mof != MOF_NON_STOP) return CMD_ERROR;
1295  break;
1296 
1297  case OT_CONDITIONAL:
1298  if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR;
1299  break;
1300 
1301  default:
1302  return CMD_ERROR;
1303  }
1304 
1305  switch (mof) {
1306  default: NOT_REACHED();
1307 
1308  case MOF_NON_STOP:
1309  if (!v->IsGroundVehicle()) return CMD_ERROR;
1310  if (data >= ONSF_END) return CMD_ERROR;
1311  if (data == order->GetNonStopType()) return CMD_ERROR;
1312  break;
1313 
1314  case MOF_STOP_LOCATION:
1315  if (v->type != VEH_TRAIN) return CMD_ERROR;
1316  if (data >= OSL_END) return CMD_ERROR;
1317  break;
1318 
1319  case MOF_UNLOAD:
1321  if ((data & ~(OUFB_UNLOAD | OUFB_TRANSFER | OUFB_NO_UNLOAD)) != 0) return CMD_ERROR;
1322  /* Unload and no-unload are mutual exclusive and so are transfer and no unload. */
1323  if (data != 0 && ((data & (OUFB_UNLOAD | OUFB_TRANSFER)) != 0) == ((data & OUFB_NO_UNLOAD) != 0)) return CMD_ERROR;
1324  if (data == order->GetUnloadType()) return CMD_ERROR;
1325  break;
1326 
1327  case MOF_LOAD:
1329  if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
1330  if (data == order->GetLoadType()) return CMD_ERROR;
1331  break;
1332 
1333  case MOF_DEPOT_ACTION:
1334  if (data >= DA_END) return CMD_ERROR;
1335  break;
1336 
1337  case MOF_COND_VARIABLE:
1338  if (data >= OCV_END) return CMD_ERROR;
1339  break;
1340 
1341  case MOF_COND_COMPARATOR:
1342  if (data >= OCC_END) return CMD_ERROR;
1343  switch (order->GetConditionVariable()) {
1344  case OCV_UNCONDITIONALLY: return CMD_ERROR;
1345 
1346  case OCV_REQUIRES_SERVICE:
1347  if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
1348  break;
1349 
1350  default:
1351  if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
1352  break;
1353  }
1354  break;
1355 
1356  case MOF_COND_VALUE:
1357  switch (order->GetConditionVariable()) {
1358  case OCV_UNCONDITIONALLY:
1359  case OCV_REQUIRES_SERVICE:
1360  return CMD_ERROR;
1361 
1362  case OCV_LOAD_PERCENTAGE:
1363  case OCV_RELIABILITY:
1364  if (data > 100) return CMD_ERROR;
1365  break;
1366 
1367  default:
1368  if (data > 2047) return CMD_ERROR;
1369  break;
1370  }
1371  break;
1372 
1373  case MOF_COND_DESTINATION:
1374  if (data >= v->GetNumOrders()) return CMD_ERROR;
1375  break;
1376  }
1377 
1378  if (flags & DC_EXEC) {
1379  switch (mof) {
1380  case MOF_NON_STOP:
1381  order->SetNonStopType((OrderNonStopFlags)data);
1383  order->SetRefit(CT_NO_REFIT);
1386  }
1387  break;
1388 
1389  case MOF_STOP_LOCATION:
1390  order->SetStopLocation((OrderStopLocation)data);
1391  break;
1392 
1393  case MOF_UNLOAD:
1394  order->SetUnloadType((OrderUnloadFlags)data);
1395  break;
1396 
1397  case MOF_LOAD:
1398  order->SetLoadType((OrderLoadFlags)data);
1399  if (data & OLFB_NO_LOAD) order->SetRefit(CT_NO_REFIT);
1400  break;
1401 
1402  case MOF_DEPOT_ACTION: {
1403  switch (data) {
1404  case DA_ALWAYS_GO:
1407  break;
1408 
1409  case DA_SERVICE:
1412  order->SetRefit(CT_NO_REFIT);
1413  break;
1414 
1415  case DA_STOP:
1418  order->SetRefit(CT_NO_REFIT);
1419  break;
1420 
1421  default:
1422  NOT_REACHED();
1423  }
1424  break;
1425  }
1426 
1427  case MOF_COND_VARIABLE: {
1429 
1431  switch (order->GetConditionVariable()) {
1432  case OCV_UNCONDITIONALLY:
1434  order->SetConditionValue(0);
1435  break;
1436 
1437  case OCV_REQUIRES_SERVICE:
1438  if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
1439  order->SetConditionValue(0);
1440  break;
1441 
1442  case OCV_LOAD_PERCENTAGE:
1443  case OCV_RELIABILITY:
1444  if (order->GetConditionValue() > 100) order->SetConditionValue(100);
1445  FALLTHROUGH;
1446 
1447  default:
1448  if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
1449  break;
1450  }
1451  break;
1452  }
1453 
1454  case MOF_COND_COMPARATOR:
1456  break;
1457 
1458  case MOF_COND_VALUE:
1459  order->SetConditionValue(data);
1460  break;
1461 
1462  case MOF_COND_DESTINATION:
1463  order->SetConditionSkipToOrder(data);
1464  break;
1465 
1466  default: NOT_REACHED();
1467  }
1468 
1469  /* Update the windows and full load flags, also for vehicles that share the same order list */
1470  Vehicle *u = v->FirstShared();
1472  for (; u != nullptr; u = u->NextShared()) {
1473  /* Toggle u->current_order "Full load" flag if it changed.
1474  * However, as the same flag is used for depot orders, check
1475  * whether we are not going to a depot as there are three
1476  * cases where the full load flag can be active and only
1477  * one case where the flag is used for depot orders. In the
1478  * other cases for the OrderType the flags are not used,
1479  * so do not care and those orders should not be active
1480  * when this function is called.
1481  */
1482  if (sel_ord == u->cur_real_order_index &&
1483  (u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
1484  u->current_order.GetLoadType() != order->GetLoadType()) {
1485  u->current_order.SetLoadType(order->GetLoadType());
1486  }
1488  }
1489  }
1490 
1491  return CommandCost();
1492 }
1493 
1501 static bool CheckAircraftOrderDistance(const Aircraft *v_new, const Vehicle *v_order, const Order *first)
1502 {
1503  if (first == nullptr || v_new->acache.cached_max_range == 0) return true;
1504 
1505  /* Iterate over all orders to check the distance between all
1506  * 'goto' orders and their respective next order (of any type). */
1507  for (const Order *o = first; o != nullptr; o = o->next) {
1508  switch (o->GetType()) {
1509  case OT_GOTO_STATION:
1510  case OT_GOTO_DEPOT:
1511  case OT_GOTO_WAYPOINT:
1512  /* If we don't have a next order, we've reached the end and must check the first order instead. */
1513  if (GetOrderDistance(o, o->next != nullptr ? o->next : first, v_order) > v_new->acache.cached_max_range_sqr) return false;
1514  break;
1515 
1516  default: break;
1517  }
1518  }
1519 
1520  return true;
1521 }
1522 
1534 CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1535 {
1536  VehicleID veh_src = GB(p2, 0, 20);
1537  VehicleID veh_dst = GB(p1, 0, 20);
1538 
1539  Vehicle *dst = Vehicle::GetIfValid(veh_dst);
1540  if (dst == nullptr || !dst->IsPrimaryVehicle()) return CMD_ERROR;
1541 
1542  CommandCost ret = CheckOwnership(dst->owner);
1543  if (ret.Failed()) return ret;
1544 
1545  switch (GB(p1, 30, 2)) {
1546  case CO_SHARE: {
1547  Vehicle *src = Vehicle::GetIfValid(veh_src);
1548 
1549  /* Sanity checks */
1550  if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1551 
1552  CommandCost ret = CheckOwnership(src->owner);
1553  if (ret.Failed()) return ret;
1554 
1555  /* Trucks can't share orders with busses (and visa versa) */
1556  if (src->type == VEH_ROAD && RoadVehicle::From(src)->IsBus() != RoadVehicle::From(dst)->IsBus()) {
1557  return CMD_ERROR;
1558  }
1559 
1560  /* Is the vehicle already in the shared list? */
1561  if (src->FirstShared() == dst->FirstShared()) return CMD_ERROR;
1562 
1563  const Order *order;
1564 
1565  FOR_VEHICLE_ORDERS(src, order) {
1566  if (!OrderGoesToStation(dst, order)) continue;
1567 
1568  /* Allow copying unreachable destinations if they were already unreachable for the source.
1569  * This is basically to allow cloning / autorenewing / autoreplacing vehicles, while the stations
1570  * are temporarily invalid due to reconstruction. */
1571  const Station *st = Station::Get(order->GetDestination());
1572  if (CanVehicleUseStation(src, st) && !CanVehicleUseStation(dst, st)) {
1573  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1574  }
1575  }
1576 
1577  /* Check for aircraft range limits. */
1578  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1579  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1580  }
1581 
1582  if (src->orders.list == nullptr && !OrderList::CanAllocateItem()) {
1583  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1584  }
1585 
1586  if (flags & DC_EXEC) {
1587  /* If the destination vehicle had a OrderList, destroy it.
1588  * We only reset the order indices, if the new orders are obviously different.
1589  * (We mainly do this to keep the order indices valid and in range.) */
1590  DeleteVehicleOrders(dst, false, dst->GetNumOrders() != src->GetNumOrders());
1591 
1592  dst->orders.list = src->orders.list;
1593 
1594  /* Link this vehicle in the shared-list */
1595  dst->AddToShared(src);
1596 
1599 
1601  }
1602  break;
1603  }
1604 
1605  case CO_COPY: {
1606  Vehicle *src = Vehicle::GetIfValid(veh_src);
1607 
1608  /* Sanity checks */
1609  if (src == nullptr || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
1610 
1611  CommandCost ret = CheckOwnership(src->owner);
1612  if (ret.Failed()) return ret;
1613 
1614  /* Trucks can't copy all the orders from busses (and visa versa),
1615  * and neither can helicopters and aircraft. */
1616  const Order *order;
1617  FOR_VEHICLE_ORDERS(src, order) {
1618  if (OrderGoesToStation(dst, order) &&
1620  return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
1621  }
1622  }
1623 
1624  /* Check for aircraft range limits. */
1625  if (dst->type == VEH_AIRCRAFT && !CheckAircraftOrderDistance(Aircraft::From(dst), src, src->GetFirstOrder())) {
1626  return_cmd_error(STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE);
1627  }
1628 
1629  /* make sure there are orders available */
1631  return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
1632  }
1633 
1634  if (flags & DC_EXEC) {
1635  const Order *order;
1636  Order *first = nullptr;
1637  Order **order_dst;
1638 
1639  /* If the destination vehicle had an order list, destroy the chain but keep the OrderList.
1640  * We only reset the order indices, if the new orders are obviously different.
1641  * (We mainly do this to keep the order indices valid and in range.) */
1642  DeleteVehicleOrders(dst, true, dst->GetNumOrders() != src->GetNumOrders());
1643 
1644  order_dst = &first;
1645  FOR_VEHICLE_ORDERS(src, order) {
1646  *order_dst = new Order();
1647  (*order_dst)->AssignOrder(*order);
1648  order_dst = &(*order_dst)->next;
1649  }
1650  if (dst->orders.list == nullptr) {
1651  dst->orders.list = new OrderList(first, dst);
1652  } else {
1653  assert(dst->orders.list->GetFirstOrder() == nullptr);
1654  assert(!dst->orders.list->IsShared());
1655  delete dst->orders.list;
1656  assert(OrderList::CanAllocateItem());
1657  dst->orders.list = new OrderList(first, dst);
1658  }
1659 
1661 
1663  }
1664  break;
1665  }
1666 
1667  case CO_UNSHARE: return DecloneOrder(dst, flags);
1668  default: return CMD_ERROR;
1669  }
1670 
1671  return CommandCost();
1672 }
1673 
1685 CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
1686 {
1687  VehicleID veh = GB(p1, 0, 20);
1688  VehicleOrderID order_number = GB(p2, 16, 8);
1689  CargoID cargo = GB(p2, 0, 8);
1690 
1691  if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT && cargo != CT_AUTO_REFIT) return CMD_ERROR;
1692 
1693  const Vehicle *v = Vehicle::GetIfValid(veh);
1694  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1695 
1696  CommandCost ret = CheckOwnership(v->owner);
1697  if (ret.Failed()) return ret;
1698 
1699  Order *order = v->GetOrder(order_number);
1700  if (order == nullptr) return CMD_ERROR;
1701 
1702  /* Automatic refit cargo is only supported for goto station orders. */
1703  if (cargo == CT_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
1704 
1705  if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
1706 
1707  if (flags & DC_EXEC) {
1708  order->SetRefit(cargo);
1709 
1710  /* Make the depot order an 'always go' order. */
1711  if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
1714  }
1715 
1716  for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) {
1717  /* Update any possible open window of the vehicle */
1719 
1720  /* If the vehicle already got the current depot set as current order, then update current order as well */
1721  if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
1722  u->current_order.SetRefit(cargo);
1723  }
1724  }
1725  }
1726 
1727  return CommandCost();
1728 }
1729 
1730 
1736 void CheckOrders(const Vehicle *v)
1737 {
1738  /* Does the user wants us to check things? */
1739  if (_settings_client.gui.order_review_system == 0) return;
1740 
1741  /* Do nothing for crashed vehicles */
1742  if (v->vehstatus & VS_CRASHED) return;
1743 
1744  /* Do nothing for stopped vehicles if setting is '1' */
1745  if (_settings_client.gui.order_review_system == 1 && (v->vehstatus & VS_STOPPED)) return;
1746 
1747  /* do nothing we we're not the first vehicle in a share-chain */
1748  if (v->FirstShared() != v) return;
1749 
1750  /* Only check every 20 days, so that we don't flood the message log */
1751  if (v->owner == _local_company && v->day_counter % 20 == 0) {
1752  const Order *order;
1753  StringID message = INVALID_STRING_ID;
1754 
1755  /* Check the order list */
1756  int n_st = 0;
1757 
1758  FOR_VEHICLE_ORDERS(v, order) {
1759  /* Dummy order? */
1760  if (order->IsType(OT_DUMMY)) {
1761  message = STR_NEWS_VEHICLE_HAS_VOID_ORDER;
1762  break;
1763  }
1764  /* Does station have a load-bay for this vehicle? */
1765  if (order->IsType(OT_GOTO_STATION)) {
1766  const Station *st = Station::Get(order->GetDestination());
1767 
1768  n_st++;
1769  if (!CanVehicleUseStation(v, st)) {
1770  message = STR_NEWS_VEHICLE_HAS_INVALID_ENTRY;
1771  } else if (v->type == VEH_AIRCRAFT &&
1772  (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1775  message == INVALID_STRING_ID) {
1776  message = STR_NEWS_PLANE_USES_TOO_SHORT_RUNWAY;
1777  }
1778  }
1779  }
1780 
1781  /* Check if the last and the first order are the same */
1782  if (v->GetNumOrders() > 1) {
1783  const Order *last = v->GetLastOrder();
1784 
1785  if (v->orders.list->GetFirstOrder()->Equals(*last)) {
1786  message = STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY;
1787  }
1788  }
1789 
1790  /* Do we only have 1 station in our order list? */
1791  if (n_st < 2 && message == INVALID_STRING_ID) message = STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS;
1792 
1793 #ifndef NDEBUG
1794  if (v->orders.list != nullptr) v->orders.list->DebugCheckSanity();
1795 #endif
1796 
1797  /* We don't have a problem */
1798  if (message == INVALID_STRING_ID) return;
1799 
1800  SetDParam(0, v->index);
1801  AddVehicleAdviceNewsItem(message, v->index);
1802  }
1803 }
1804 
1813 void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
1814 {
1815  /* Aircraft have StationIDs for depot orders and never use DepotIDs
1816  * This fact is handled specially below
1817  */
1818 
1819  /* Go through all vehicles */
1820  for (Vehicle *v : Vehicle::Iterate()) {
1821  Order *order;
1822 
1823  order = &v->current_order;
1824  if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
1825  (!hangar || v->type == VEH_AIRCRAFT) && v->current_order.GetDestination() == destination) {
1826  order->MakeDummy();
1827  SetWindowDirty(WC_VEHICLE_VIEW, v->index);
1828  }
1829 
1830  /* Clear the order from the order-list */
1831  int id = -1;
1832  FOR_VEHICLE_ORDERS(v, order) {
1833  id++;
1834 restart:
1835 
1836  OrderType ot = order->GetType();
1837  if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
1838  if (ot == OT_GOTO_DEPOT && hangar && v->type != VEH_AIRCRAFT) continue; // Not an aircraft? Can't have a hangar order.
1839  if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT && !hangar)) ot = OT_GOTO_STATION;
1840  if (ot == type && order->GetDestination() == destination) {
1841  /* We want to clear implicit orders, but we don't want to make them
1842  * dummy orders. They should just vanish. Also check the actual order
1843  * type as ot is currently OT_GOTO_STATION. */
1844  if (order->IsType(OT_IMPLICIT)) {
1845  order = order->next; // DeleteOrder() invalidates current order
1846  DeleteOrder(v, id);
1847  if (order != nullptr) goto restart;
1848  break;
1849  }
1850 
1851  /* Clear wait time */
1852  v->orders.list->UpdateTotalDuration(-order->GetWaitTime());
1853  if (order->IsWaitTimetabled()) {
1854  v->orders.list->UpdateTimetableDuration(-order->GetTimetabledWait());
1855  order->SetWaitTimetabled(false);
1856  }
1857  order->SetWaitTime(0);
1858 
1859  /* Clear order, preserving travel time */
1860  bool travel_timetabled = order->IsTravelTimetabled();
1861  order->MakeDummy();
1862  order->SetTravelTimetabled(travel_timetabled);
1863 
1864  for (const Vehicle *w = v->FirstShared(); w != nullptr; w = w->NextShared()) {
1865  /* In GUI, simulate by removing the order and adding it back */
1868  }
1869  }
1870  }
1871  }
1872 
1873  OrderBackup::RemoveOrder(type, destination, hangar);
1874 }
1875 
1881 {
1882  const Order *order;
1883 
1884  FOR_VEHICLE_ORDERS(this, order) {
1885  if (order->IsType(OT_GOTO_DEPOT)) return true;
1886  }
1887 
1888  return false;
1889 }
1890 
1900 void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
1901 {
1903 
1904  if (v->IsOrderListShared()) {
1905  /* Remove ourself from the shared order list. */
1906  v->RemoveFromShared();
1907  v->orders.list = nullptr;
1908  } else if (v->orders.list != nullptr) {
1909  /* Remove the orders */
1910  v->orders.list->FreeChain(keep_orderlist);
1911  if (!keep_orderlist) v->orders.list = nullptr;
1912  }
1913 
1914  if (reset_order_indices) {
1916  if (v->current_order.IsType(OT_LOADING)) {
1918  }
1919  }
1920 }
1921 
1928 uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
1929 {
1930  return ispercent ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
1931 }
1932 
1941 static bool CheckForValidOrders(const Vehicle *v)
1942 {
1943  const Order *order;
1944 
1945  FOR_VEHICLE_ORDERS(v, order) {
1946  switch (order->GetType()) {
1947  case OT_GOTO_STATION:
1948  case OT_GOTO_DEPOT:
1949  case OT_GOTO_WAYPOINT:
1950  return true;
1951 
1952  default:
1953  break;
1954  }
1955  }
1956 
1957  return false;
1958 }
1959 
1963 static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
1964 {
1965  switch (occ) {
1966  case OCC_EQUALS: return variable == value;
1967  case OCC_NOT_EQUALS: return variable != value;
1968  case OCC_LESS_THAN: return variable < value;
1969  case OCC_LESS_EQUALS: return variable <= value;
1970  case OCC_MORE_THAN: return variable > value;
1971  case OCC_MORE_EQUALS: return variable >= value;
1972  case OCC_IS_TRUE: return variable != 0;
1973  case OCC_IS_FALSE: return variable == 0;
1974  default: NOT_REACHED();
1975  }
1976 }
1977 
1985 {
1986  if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
1987 
1988  bool skip_order = false;
1990  uint16 value = order->GetConditionValue();
1991 
1992  switch (order->GetConditionVariable()) {
1993  case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, nullptr), value); break;
1994  case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
1995  case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
1996  case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
1997  case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / DAYS_IN_LEAP_YEAR, value); break;
1998  case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
1999  case OCV_UNCONDITIONALLY: skip_order = true; break;
2000  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;
2001  default: NOT_REACHED();
2002  }
2003 
2004  return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
2005 }
2006 
2014 bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
2015 {
2016  if (conditional_depth > v->GetNumOrders()) {
2017  v->current_order.Free();
2018  v->SetDestTile(0);
2019  return false;
2020  }
2021 
2022  switch (order->GetType()) {
2023  case OT_GOTO_STATION:
2024  v->SetDestTile(v->GetOrderStationLocation(order->GetDestination()));
2025  return true;
2026 
2027  case OT_GOTO_DEPOT:
2028  if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
2029  assert(!pbs_look_ahead);
2030  UpdateVehicleTimetable(v, true);
2032  break;
2033  }
2034 
2036  /* We need to search for the nearest depot (hangar). */
2037  TileIndex location;
2038  DestinationID destination;
2039  bool reverse;
2040 
2041  if (v->FindClosestDepot(&location, &destination, &reverse)) {
2042  /* PBS reservations cannot reverse */
2043  if (pbs_look_ahead && reverse) return false;
2044 
2045  v->SetDestTile(location);
2047 
2048  /* If there is no depot in front, reverse automatically (trains only) */
2049  if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
2050 
2051  if (v->type == VEH_AIRCRAFT) {
2052  Aircraft *a = Aircraft::From(v);
2053  if (a->state == FLYING && a->targetairport != destination) {
2054  /* The aircraft is now heading for a different hangar than the next in the orders */
2057  }
2058  }
2059  return true;
2060  }
2061 
2062  /* If there is no depot, we cannot help PBS either. */
2063  if (pbs_look_ahead) return false;
2064 
2065  UpdateVehicleTimetable(v, true);
2067  } else {
2068  if (v->type != VEH_AIRCRAFT) {
2069  v->SetDestTile(Depot::Get(order->GetDestination())->xy);
2070  } else {
2071  Aircraft *a = Aircraft::From(v);
2072  DestinationID destination = a->current_order.GetDestination();
2073  if (a->targetairport != destination) {
2074  /* The aircraft is now heading for a different hangar than the next in the orders */
2075  a->SetDestTile(a->GetOrderStationLocation(destination));
2076  }
2077  }
2078  return true;
2079  }
2080  break;
2081 
2082  case OT_GOTO_WAYPOINT:
2083  v->SetDestTile(Waypoint::Get(order->GetDestination())->xy);
2084  return true;
2085 
2086  case OT_CONDITIONAL: {
2087  assert(!pbs_look_ahead);
2088  VehicleOrderID next_order = ProcessConditionalOrder(order, v);
2089  if (next_order != INVALID_VEH_ORDER_ID) {
2090  /* Jump to next_order. cur_implicit_order_index becomes exactly that order,
2091  * cur_real_order_index might come after next_order. */
2092  UpdateVehicleTimetable(v, false);
2093  v->cur_implicit_order_index = v->cur_real_order_index = next_order;
2094  v->UpdateRealOrderIndex();
2096 
2097  /* Disable creation of implicit orders.
2098  * When inserting them we do not know that we would have to make the conditional orders point to them. */
2099  if (v->IsGroundVehicle()) {
2100  uint16 &gv_flags = v->GetGroundVehicleFlags();
2102  }
2103  } else {
2104  UpdateVehicleTimetable(v, true);
2106  }
2107  break;
2108  }
2109 
2110  default:
2111  v->SetDestTile(0);
2112  return false;
2113  }
2114 
2115  assert(v->cur_implicit_order_index < v->GetNumOrders());
2116  assert(v->cur_real_order_index < v->GetNumOrders());
2117 
2118  /* Get the current order */
2119  order = v->GetOrder(v->cur_real_order_index);
2120  if (order != nullptr && order->IsType(OT_IMPLICIT)) {
2121  assert(v->GetNumManualOrders() == 0);
2122  order = nullptr;
2123  }
2124 
2125  if (order == nullptr) {
2126  v->current_order.Free();
2127  v->SetDestTile(0);
2128  return false;
2129  }
2130 
2131  v->current_order = *order;
2132  return UpdateOrderDest(v, order, conditional_depth + 1, pbs_look_ahead);
2133 }
2134 
2143 {
2144  switch (v->current_order.GetType()) {
2145  case OT_GOTO_DEPOT:
2146  /* Let a depot order in the orderlist interrupt. */
2147  if (!(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return false;
2148  break;
2149 
2150  case OT_LOADING:
2151  return false;
2152 
2153  case OT_LEAVESTATION:
2154  if (v->type != VEH_AIRCRAFT) return false;
2155  break;
2156 
2157  default: break;
2158  }
2159 
2167  bool may_reverse = v->current_order.IsType(OT_NOTHING);
2168 
2169  /* Check if we've reached a 'via' destination. */
2170  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)) &&
2171  IsTileType(v->tile, MP_STATION) &&
2174  /* We set the last visited station here because we do not want
2175  * the train to stop at this 'via' station if the next order
2176  * is a no-non-stop order; in that case not setting the last
2177  * visited station will cause the vehicle to still stop. */
2179  UpdateVehicleTimetable(v, true);
2181  }
2182 
2183  /* Get the current order */
2184  assert(v->cur_implicit_order_index == 0 || v->cur_implicit_order_index < v->GetNumOrders());
2185  v->UpdateRealOrderIndex();
2186 
2187  const Order *order = v->GetOrder(v->cur_real_order_index);
2188  if (order != nullptr && order->IsType(OT_IMPLICIT)) {
2189  assert(v->GetNumManualOrders() == 0);
2190  order = nullptr;
2191  }
2192 
2193  /* If no order, do nothing. */
2194  if (order == nullptr || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
2195  if (v->type == VEH_AIRCRAFT) {
2196  /* Aircraft do something vastly different here, so handle separately */
2197  extern void HandleMissingAircraftOrders(Aircraft *v);
2198  HandleMissingAircraftOrders(Aircraft::From(v));
2199  return false;
2200  }
2201 
2202  v->current_order.Free();
2203  v->SetDestTile(0);
2204  return false;
2205  }
2206 
2207  /* If it is unchanged, keep it. */
2208  if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
2209  (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->ship_station.tile != INVALID_TILE)) {
2210  return false;
2211  }
2212 
2213  /* Otherwise set it, and determine the destination tile. */
2214  v->current_order = *order;
2215 
2217  switch (v->type) {
2218  default:
2219  NOT_REACHED();
2220 
2221  case VEH_ROAD:
2222  case VEH_TRAIN:
2223  break;
2224 
2225  case VEH_AIRCRAFT:
2226  case VEH_SHIP:
2228  break;
2229  }
2230 
2231  return UpdateOrderDest(v, order) && may_reverse;
2232 }
2233 
2241 bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
2242 {
2243  bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
2244 
2245  return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
2246  v->last_station_visited != station && // Do stop only when we've not just been there
2247  /* Finally do stop when there is no non-stop flag set for this type of station. */
2249 }
2250 
2251 bool Order::CanLoadOrUnload() const
2252 {
2253  return (this->IsType(OT_GOTO_STATION) || this->IsType(OT_IMPLICIT)) &&
2255  ((this->GetLoadType() & OLFB_NO_LOAD) == 0 ||
2256  (this->GetUnloadType() & OUFB_NO_UNLOAD) == 0);
2257 }
2258 
2265 bool Order::CanLeaveWithCargo(bool has_cargo) const
2266 {
2267  return (this->GetLoadType() & OLFB_NO_LOAD) == 0 || (has_cargo &&
2268  (this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0);
2269 }
OrderConditionVariable
Variables (of a vehicle) to &#39;cause&#39; skipping on.
Definition: order_type.h:112
Functions related to OTTD&#39;s strings.
Road vehicle states.
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:25
Date max_age
Maximum age.
Definition: vehicle_base.h:257
StationFacility facilities
The facilities that this station has.
Vehicle is stopped by the player.
Definition: vehicle_base.h:31
This airport has a short landing strip, dangerous for fast aircraft.
Definition: airport.h:150
void InsertOrderAt(Order *new_order, int index)
Insert a new order into the order chain.
Definition: order_cmd.cpp:471
bool IsVehicleInSharedOrdersList(const Vehicle *v) const
Checks whether a vehicle is part of the shared vehicle chain.
Definition: order_cmd.cpp:577
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:340
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:1014
uint16 DepotID
Type for the unique identifier of depots.
Definition: depot_type.h:13
Passes an OrderUnloadType.
Definition: order_type.h:146
uint16 GetTravelTime() const
Get the time in ticks a vehicle will probably take to reach the destination (timetabled or not)...
Definition: order_base.h:185
StationID targetairport
Airport to go to next.
Definition: aircraft.h:78
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:3218
Skip if both values are equal.
Definition: order_type.h:128
Load as long as there is cargo that fits in the train.
Definition: order_type.h:63
OrderConditionComparator GetConditionComparator() const
What is the comparator to use?
Definition: order_base.h:141
uint16 GetServiceIntervalClamped(uint interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1928
void SetConditionValue(uint16 value)
Set the value to base the skip on.
Definition: order_base.h:166
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1736
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:250
Train vehicle type.
Definition: vehicle_type.h:24
union Vehicle::@49 orders
The orders currently assigned to the vehicle.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:329
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:143
void SetWaitTime(uint16 time)
Set the time in ticks to wait at the destination.
Definition: order_base.h:203
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition: order_type.h:21
Other order modifications.
Definition: vehicle_gui.h:33
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:156
static void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:40
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:23
Ship vehicle type.
Definition: vehicle_type.h:26
Maximal number of cargo types in a game.
Definition: cargo_type.h:64
void SetDepotActionType(OrderDepotActionFlags depot_service_type)
Set what we are going to do in the depot.
Definition: order_base.h:158
Selects the OrderDepotAction.
Definition: order_type.h:148
OrderList * list
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:319
Skip if the variable is true.
Definition: order_type.h:134
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:235
bool IsCompleteTimetable() const
Checks whether all orders of the list have a filled timetable.
Definition: order_cmd.cpp:602
bool IsTravelTimetabled() const
Does this order have an explicit travel time set?
Definition: order_base.h:176
Skip based on the reliability.
Definition: order_type.h:114
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
Insert a new order but skip the validation.
Definition: order_cmd.cpp:927
Stop at the middle of the platform.
Definition: order_type.h:85
A comparator changes.
Definition: order_type.h:150
void IncrementImplicitOrderIndex()
Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI...
Definition: vehicle_base.h:798
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:822
uint32 current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:21
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
Process a conditional order and determine the next order.
Definition: order_cmd.cpp:1984
Vehicle data structure.
Definition: vehicle_base.h:210
Base for all depots (except hangars)
void SetRefit(CargoID cargo)
Make this depot/station order also a refit order.
Definition: order_cmd.cpp:164
Flags flags
Flags for this airport type.
Definition: airport.h:180
Unload all cargo that the station accepts.
Definition: order_type.h:53
void LeaveStation()
Perform all actions when leaving a station.
Definition: vehicle.cpp:2180
Tindex index
Index of this pool item.
Definition: pool_type.hpp:227
Vehicle is flying in the air.
Definition: airport.h:75
Helper functions to extract data from command parameters.
CargoID refit_cargo
Refit CargoID.
Definition: order_base.h:42
Base for aircraft.
Representation of a waypoint.
Definition: waypoint_base.h:16
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:300
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition: order_cmd.cpp:1900
OrderNonStopFlags
Non-stop order flags.
Definition: order_type.h:72
void SetUnloadType(OrderUnloadFlags unload_type)
Set how the consist must be unloaded.
Definition: order_base.h:150
Skip if the value is more or equal to the limit.
Definition: order_type.h:133
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:162
Automatically choose cargo type when doing auto refitting.
Definition: cargo_type.h:66
Common return value for all commands.
Definition: command_type.h:23
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
uint16 MapOldOrder() const
Pack this order into a 16 bits integer as close to the TTD representation as possible.
Definition: order_cmd.cpp:207
void SetConditionVariable(OrderConditionVariable condition_variable)
Set variable we have to compare.
Definition: order_base.h:160
byte vehstatus
Status.
Definition: vehicle_base.h:315
Skip based on the age.
Definition: order_type.h:116
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:379
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:680
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:741
bool CanLeaveWithCargo(bool has_cargo) const
A vehicle can leave the current station with cargo if:
Definition: order_cmd.cpp:2265
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-new).
Definition: cargo_type.h:67
void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
Delete an order but skip the parameter validation.
Definition: order_cmd.cpp:1055
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition: order_base.h:137
The vehicle will stop at any station it passes except the destination.
Definition: order_type.h:75
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:707
Stop at the near end of the platform.
Definition: order_type.h:84
Order * next
Pointer to next order. If nullptr, end of list.
Definition: order_base.h:49
void DeleteOrderAt(int index)
Remove an order from the order list and delete it.
Definition: order_cmd.cpp:509
Vehicle * FirstShared() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:673
Order * GetOrderAt(int index) const
Get a certain order of the order chain.
Definition: order_cmd.cpp:356
Cheat no_jetcrash
no jet will crash on small airports anymore
Definition: cheat_type.h:32
Pseudo random number generator.
void MoveOrder(int from, int to)
Move an order to another position within the order list.
Definition: order_cmd.cpp:535
void SetConditionSkipToOrder(VehicleOrderID order_id)
Get the order to skip to.
Definition: order_base.h:164
Stop at the far end of the platform.
Definition: order_type.h:86
DestinationID dest
The destination of the order.
Definition: order_base.h:40
uint16 travel_time
How long in ticks the journey to this destination should take.
Definition: order_base.h:45
The vehicle will stop at any station it passes and the destination.
Definition: order_type.h:73
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:3337
void MakeConditional(VehicleOrderID order)
Makes this order an conditional order.
Definition: order_cmd.cpp:142
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:2241
Passes an OrderStopLocation.
Definition: order_type.h:145
void RemoveVehicle(Vehicle *v)
Removes the vehicle from the shared order list.
Definition: order_cmd.cpp:567
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition: order_base.h:250
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:135
static CommandCost DecloneOrder(Vehicle *dst, DoCommandFlag flags)
Declone an order-list.
Definition: order_cmd.cpp:995
Vehicle orders; Window numbers:
Definition: window_type.h:205
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:484
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:139
Vehicle is crashed.
Definition: vehicle_base.h:37
The tile has no ownership.
Definition: company_type.h:25
Types related to cheating.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:431
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
uint8 type
The type of order + non-stop flags.
Definition: order_base.h:38
void SetNonStopType(OrderNonStopFlags non_stop_type)
Set whether we must stop at stations or not.
Definition: order_base.h:152
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:445
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition: order_cmd.cpp:153
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:897
bool IsRefit() const
Is this order a refit order.
Definition: order_base.h:108
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:748
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:183
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:132
Do not load anything.
Definition: order_type.h:66
uint32 VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:61
static Owner GetTileOwner(TileIndex tile)
Returns the owner of a tile.
Definition: tile_map.h:178
DoCommandFlag
List of flags for a command.
Definition: command_type.h:344
Skip if the value is less or equal to the limit.
Definition: order_type.h:131
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:738
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
Definition of base types and functions in a cross-platform compatible way.
Removed / replaced all orders (after deleting / sharing).
Definition: vehicle_gui.h:32
A number of safeguards to prevent using unsafe methods.
bool value
tells if the bool cheat is active or not
Definition: cheat_type.h:18
Change the destination of a conditional order.
Definition: order_type.h:152
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2142
Always skip.
Definition: order_type.h:118
Base of waypoints.
void MakeLoading(bool ordered)
Makes this order a Loading order.
Definition: order_cmd.cpp:114
static bool IsRoadDepotTile(TileIndex t)
Return whether a tile is a road depot tile.
Definition: road_map.h:115
void FreeChain(bool keep_orderlist=false)
Free a complete order chain.
Definition: order_cmd.cpp:333
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:837
OrderDepotActionFlags
Actions that can be performed when the vehicle enters the depot.
Definition: order_type.h:102
uint8 flags
Load/unload types, depot order/action types.
Definition: order_base.h:39
CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Move an order inside the orderlist.
Definition: order_cmd.cpp:1161
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition: vehicle.cpp:2688
Vehicle view; Window numbers:
Definition: window_type.h:332
bool IsWaitTimetabled() const
Does this order have an explicit wait time set?
Definition: order_base.h:174
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:181
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:290
TileIndex tile
Current tile index.
Definition: vehicle_base.h:228
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
void Push(const Titem &item)
Pushes a new item onto the stack if there is still space in the underlying pool.
Vehicle timetable; Window numbers:
Definition: window_type.h:217
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:2779
OrderConditionComparator
Comparator for the skip reasoning.
Definition: order_type.h:127
Always go to the depot.
Definition: order_type.h:161
OrderLoadFlags GetLoadType() const
How must the consist be loaded?
Definition: order_base.h:127
Service the vehicle and then halt it.
Definition: order_type.h:104
virtual TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
Definition: vehicle_base.h:738
void SetWaitTimetabled(bool timetabled)
Set if the wait time is explicitly timetabled (unless the order is conditional).
Definition: order_base.h:195
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:271
bool Equals(const Order &other) const
Does this order have the same type, flags and destination?
Definition: order_cmd.cpp:174
static bool IsShipDepotTile(TileIndex t)
Is it a ship depot tile?
Definition: water_map.h:226
Service only if needed.
Definition: order_type.h:162
Order * GetLastOrder() const
Returns the last order of a vehicle, or nullptr if it doesn&#39;t exists.
Definition: vehicle_base.h:867
uint16 reliability
Reliability.
Definition: vehicle_base.h:259
static void CancelLoadingDueToDeletedOrder(Vehicle *v)
Cancel the current loading order of the vehicle as the order was deleted.
Definition: order_cmd.cpp:1039
CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
Goto order of order-list.
Definition: order_cmd.cpp:1120
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
bool Failed() const
Did this command fail?
Definition: command_type.h:159
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:2014
Order * GetFirstOrder() const
Get the first order of the vehicles order list.
Definition: vehicle_base.h:652
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:1265
The value to set the condition to.
Definition: order_type.h:151
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
Compare the variable and value based on the given comparator.
Definition: order_cmd.cpp:1963
Skip based on the remaining lifetime.
Definition: order_type.h:119
Skip if the value is less than the limit.
Definition: order_type.h:130
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:665
Transfer all cargo onto the platform.
Definition: order_type.h:55
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:33
byte state
State of the airport.
Definition: aircraft.h:79
Base class for all pools.
Definition: pool_type.hpp:81
Station list; Window numbers:
Definition: window_type.h:295
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
OrderUnloadFlags GetUnloadType() const
How must the consist be unloaded?
Definition: order_base.h:129
void SetLoadType(OrderLoadFlags load_type)
Set how the consist must be loaded.
Definition: order_base.h:148
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
Skip when the vehicle requires service.
Definition: order_type.h:117
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:17
bool HasDepotOrder() const
Checks if a vehicle has a depot in its order list.
Definition: order_cmd.cpp:1880
OrderUnloadFlags
Flags related to the unloading order.
Definition: order_type.h:52
uint16 GetWaitTime() const
Get the time in ticks a vehicle will probably wait at the destination (timetabled or not)...
Definition: order_base.h:183
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don&#39;t get linker errors.
Definition: pool_func.hpp:224
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:2711
execute the given command
Definition: command_type.h:346
A conditional variable changes.
Definition: order_type.h:149
Functions related to companies.
Station with a dock.
Definition: station_type.h:56
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:28
OrderStopLocation
Where to stop the trains.
Definition: order_type.h:83
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:179
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition: roadveh_cmd.cpp:79
Passes an OrderNonStopFlags.
Definition: order_type.h:144
uint16 cached_max_range
Cached maximum range.
Definition: aircraft.h:68
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:469
GUISettings gui
settings related to the GUI
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:94
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:378
static bool IsRailDepotTile(TileIndex t)
Is this tile rail tile and a rail depot?
Definition: rail_map.h:105
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:89
static bool CheckForValidOrders(const Vehicle *v)
Check if a vehicle has any valid orders.
Definition: order_cmd.cpp:1941
OrderStopLocation GetStopLocation() const
Where must we stop at the platform?
Definition: order_base.h:133
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
StationIDStack GetNextStoppingStation(const Vehicle *v, const Order *first=nullptr, uint hops=0) const
Recursively determine the next deterministic station to stop at.
Definition: order_cmd.cpp:414
Ships list; Window numbers:
Definition: window_type.h:313
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
Skip if both values are not equal.
Definition: order_type.h:129
uint DistanceManhattan(TileIndex t0, TileIndex t1)
Gets the Manhattan distance between the two given tiles.
Definition: map.cpp:157
OrderLoadFlags
Flags related to the loading order.
Definition: order_type.h:62
void MakeLeaveStation()
Makes this order a Leave Station order.
Definition: order_cmd.cpp:123
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:653
Vehicle * PreviousShared() const
Get the previous vehicle of the shared vehicle chain.
Definition: vehicle_base.h:667
uint16 wait_time
How long in ticks to wait at the destination.
Definition: order_base.h:44
Send the vehicle to the nearest depot.
Definition: order_type.h:105
int32 Ticks
The type to store ticks in.
Definition: date_type.h:16
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:62
turn a train around
Definition: command_type.h:222
uint16 GetConditionValue() const
Get the value to base the skip on.
Definition: order_base.h:145
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:197
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:67
Full load all cargoes of the consist.
Definition: order_type.h:64
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:52
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition: vehicle.cpp:1994
A tile of a station.
Definition: tile_type.h:46
Skip based on the amount of load.
Definition: order_type.h:113
OrderType
Order types.
Definition: order_type.h:35
int GetPositionInSharedOrderList(const Vehicle *v) const
Gets the position of the given vehicle within the shared order vehicle list.
Definition: order_cmd.cpp:591
Totally no unloading will be done.
Definition: order_type.h:56
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:299
static uint ToPercent16(uint i)
Converts a "fract" value 0..65535 to "percent" value 0..100.
Definition: math_func.hpp:298
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:272
The vehicle will not stop at any stations it passes except the destination.
Definition: order_type.h:74
Skip based on the maximum speed.
Definition: order_type.h:115
Aircraft list; Window numbers:
Definition: window_type.h:319
uint16 & GetGroundVehicleFlags()
Access the ground vehicle flags of the vehicle.
Definition: vehicle.cpp:2854
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:1685
uint8 CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
Calculates how full a vehicle is.
Definition: vehicle.cpp:1377
void DebugCheckSanity() const
Checks for internal consistency of order list.
Definition: order_cmd.cpp:615
Passes an OrderLoadType.
Definition: order_type.h:147
Owner owner
The owner of this station.
ModifyOrderFlags
Enumeration for the data to set in CmdModifyOrder.
Definition: order_type.h:143
static WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:91
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:1534
Order * GetOrder(int index) const
Returns order &#39;index&#39; of a vehicle or nullptr when it doesn&#39;t exists.
Definition: vehicle_base.h:858
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
VehicleOrderID GetNumOrders() const
Get the number of orders this vehicle has.
Definition: vehicle_base.h:685
Aircraft vehicle type.
Definition: vehicle_type.h:27
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:1501
Airport airport
Tile area the airport covers.
Definition: station_base.h:464
bool IsOrderListShared() const
Check if we share our orders with another vehicle.
Definition: vehicle_base.h:679
void MakeGoToWaypoint(StationID destination)
Makes this order a Go To Waypoint order.
Definition: order_cmd.cpp:103
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:286
byte VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition: order_type.h:15
void RecalculateTimetableDuration()
Recomputes Timetable duration.
Definition: order_cmd.cpp:320
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
uint32 Pack() const
Pack this order into a 32 bits integer, or actually only the type, flags and destination.
Definition: order_cmd.cpp:197
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition: order_cmd.cpp:1813
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:67
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
uint8 order_review_system
perform order reviews on vehicles
Definition: settings_type.h:85
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the &#39;Square&#39; distance between the two given tiles.
Definition: map.cpp:174
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition: vehicle_base.h:661
Station with train station.
Definition: station_type.h:52
Force unloading all cargo onto the platform, possibly not getting paid.
Definition: order_type.h:54
static const VehicleOrderID MAX_VEH_ORDER_ID
Last valid VehicleOrderID.
Definition: order_type.h:23
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3246
This depot order is because of a regular order.
Definition: order_type.h:96
Functions related to news.
Go to the depot and stop there.
Definition: order_type.h:163
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:28
Skip if the value is more than the limit.
Definition: order_type.h:132
uint16 max_speed
How fast the vehicle may go on the way to the destination.
Definition: order_base.h:46
Date age
Age in days.
Definition: vehicle_base.h:256
Full load a single cargo of the consist.
Definition: order_type.h:65
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
This depot order is because of the servicing limit.
Definition: order_type.h:95
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition: base_consist.h:27
Skip if the variable is false.
Definition: order_type.h:135
Skip based on the maximum reliability.
Definition: order_type.h:120
void SetStopLocation(OrderStopLocation stop_location)
Set where we must stop at the platform.
Definition: order_base.h:154
Base class for all station-ish types.
Station data structure.
Definition: station_base.h:450
OrderNonStopFlags GetNonStopType() const
At which stations must we stop?
Definition: order_base.h:131
Disable insertion and removal of automatic orders until the vehicle completes the real order...
Road vehicle type.
Definition: vehicle_type.h:25
byte day_counter
Increased by one for each day.
Definition: vehicle_base.h:311
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:316
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:3319
static const int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: date_type.h:30
void MakeGoToStation(StationID destination)
Makes this order a Go To Station order.
Definition: order_cmd.cpp:74
OrderDepotTypeFlags
Reasons that could cause us to go to the depot.
Definition: order_type.h:93
CargoID GetRefitCargo() const
Get the cargo to to refit to.
Definition: order_base.h:122
Cheats _cheats
All the cheats.
Definition: cheat.cpp:16
VehicleOrderID GetNumManualOrders() const
Get the number of manually added orders this vehicle has.
Definition: vehicle_base.h:691
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:199
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.