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");
45 INSTANTIATE_POOL_METHODS(OrderList)
46 
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 
346 Order *OrderList::GetOrderAt(int index) const
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 }