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