order_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: order_cmd.cpp 23795 2012-01-13 21:54:59Z rubidium $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "cmd_helper.h"
00015 #include "command_func.h"
00016 #include "company_func.h"
00017 #include "news_func.h"
00018 #include "vehicle_gui.h"
00019 #include "strings_func.h"
00020 #include "window_func.h"
00021 #include "timetable.h"
00022 #include "vehicle_func.h"
00023 #include "depot_base.h"
00024 #include "core/pool_func.hpp"
00025 #include "aircraft.h"
00026 #include "roadveh.h"
00027 #include "station_base.h"
00028 #include "waypoint_base.h"
00029 #include "company_base.h"
00030 #include "order_backup.h"
00031 
00032 #include "table/strings.h"
00033 
00034 /* DestinationID must be at least as large as every these below, because it can
00035  * be any of them
00036  */
00037 assert_compile(sizeof(DestinationID) >= sizeof(DepotID));
00038 assert_compile(sizeof(DestinationID) >= sizeof(StationID));
00039 
00040 OrderPool _order_pool("Order");
00041 INSTANTIATE_POOL_METHODS(Order)
00042 OrderListPool _orderlist_pool("OrderList");
00043 INSTANTIATE_POOL_METHODS(OrderList)
00044 
00046 Order::~Order()
00047 {
00048   if (CleaningPool()) return;
00049 
00050   /* We can visit oil rigs and buoys that are not our own. They will be shown in
00051    * the list of stations. So, we need to invalidate that window if needed. */
00052   if (this->IsType(OT_GOTO_STATION) || this->IsType(OT_GOTO_WAYPOINT)) {
00053     BaseStation *bs = BaseStation::GetIfValid(this->GetDestination());
00054     if (bs != NULL && bs->owner == OWNER_NONE) InvalidateWindowClassesData(WC_STATION_LIST, 0);
00055   }
00056 }
00057 
00062 void Order::Free()
00063 {
00064   this->type  = OT_NOTHING;
00065   this->flags = 0;
00066   this->dest  = 0;
00067   this->next  = NULL;
00068 }
00069 
00074 void Order::MakeGoToStation(StationID destination)
00075 {
00076   this->type = OT_GOTO_STATION;
00077   this->flags = 0;
00078   this->dest = destination;
00079 }
00080 
00090 void Order::MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type, OrderDepotActionFlags action, CargoID cargo, byte subtype)
00091 {
00092   this->type = OT_GOTO_DEPOT;
00093   this->SetDepotOrderType(order);
00094   this->SetDepotActionType(action);
00095   this->SetNonStopType(non_stop_type);
00096   this->dest = destination;
00097   this->SetRefit(cargo, subtype);
00098 }
00099 
00104 void Order::MakeGoToWaypoint(StationID destination)
00105 {
00106   this->type = OT_GOTO_WAYPOINT;
00107   this->flags = 0;
00108   this->dest = destination;
00109 }
00110 
00115 void Order::MakeLoading(bool ordered)
00116 {
00117   this->type = OT_LOADING;
00118   if (!ordered) this->flags = 0;
00119 }
00120 
00124 void Order::MakeLeaveStation()
00125 {
00126   this->type = OT_LEAVESTATION;
00127   this->flags = 0;
00128 }
00129 
00133 void Order::MakeDummy()
00134 {
00135   this->type = OT_DUMMY;
00136   this->flags = 0;
00137 }
00138 
00143 void Order::MakeConditional(VehicleOrderID order)
00144 {
00145   this->type = OT_CONDITIONAL;
00146   this->flags = order;
00147   this->dest = 0;
00148 }
00149 
00154 void Order::MakeImplicit(StationID destination)
00155 {
00156   this->type = OT_IMPLICIT;
00157   this->dest = destination;
00158 }
00159 
00166 void Order::SetRefit(CargoID cargo, byte subtype)
00167 {
00168   this->refit_cargo = cargo;
00169   this->refit_subtype = subtype;
00170 }
00171 
00177 bool Order::Equals(const Order &other) const
00178 {
00179   /* In case of go to nearest depot orders we need "only" compare the flags
00180    * with the other and not the nearest depot order bit or the actual
00181    * destination because those get clear/filled in during the order
00182    * evaluation. If we do not do this the order will continuously be seen as
00183    * a different order and it will try to find a "nearest depot" every tick. */
00184   if ((this->IsType(OT_GOTO_DEPOT) && this->type == other.type) &&
00185       ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0 ||
00186        (other.GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0)) {
00187     return this->GetDepotOrderType() == other.GetDepotOrderType() &&
00188         (this->GetDepotActionType() & ~ODATFB_NEAREST_DEPOT) == (other.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT);
00189   }
00190 
00191   return this->type == other.type && this->flags == other.flags && this->dest == other.dest;
00192 }
00193 
00200 uint32 Order::Pack() const
00201 {
00202   return this->dest << 16 | this->flags << 8 | this->type;
00203 }
00204 
00210 uint16 Order::MapOldOrder() const
00211 {
00212   uint16 order = this->GetType();
00213   switch (this->type) {
00214     case OT_GOTO_STATION:
00215       if (this->GetUnloadType() & OUFB_UNLOAD) SetBit(order, 5);
00216       if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
00217       if (this->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) SetBit(order, 7);
00218       order |= GB(this->GetDestination(), 0, 8) << 8;
00219       break;
00220     case OT_GOTO_DEPOT:
00221       if (!(this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) SetBit(order, 6);
00222       SetBit(order, 7);
00223       order |= GB(this->GetDestination(), 0, 8) << 8;
00224       break;
00225     case OT_LOADING:
00226       if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
00227       break;
00228   }
00229   return order;
00230 }
00231 
00236 Order::Order(uint32 packed)
00237 {
00238   this->type    = (OrderType)GB(packed,  0,  8);
00239   this->flags   = GB(packed,  8,  8);
00240   this->dest    = GB(packed, 16, 16);
00241   this->next    = NULL;
00242   this->refit_cargo   = CT_NO_REFIT;
00243   this->refit_subtype = 0;
00244   this->wait_time     = 0;
00245   this->travel_time   = 0;
00246 }
00247 
00253 void InvalidateVehicleOrder(const Vehicle *v, int data)
00254 {
00255   SetWindowDirty(WC_VEHICLE_VIEW, v->index);
00256 
00257   if (data != 0) {
00258     /* Calls SetDirty() too */
00259     InvalidateWindowData(WC_VEHICLE_ORDERS,    v->index, data);
00260     InvalidateWindowData(WC_VEHICLE_TIMETABLE, v->index, data);
00261     return;
00262   }
00263 
00264   SetWindowDirty(WC_VEHICLE_ORDERS,    v->index);
00265   SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
00266 }
00267 
00275 void Order::AssignOrder(const Order &other)
00276 {
00277   this->type  = other.type;
00278   this->flags = other.flags;
00279   this->dest  = other.dest;
00280 
00281   this->refit_cargo   = other.refit_cargo;
00282   this->refit_subtype = other.refit_subtype;
00283 
00284   this->wait_time   = other.wait_time;
00285   this->travel_time = other.travel_time;
00286 }
00287 
00293 void OrderList::Initialize(Order *chain, Vehicle *v)
00294 {
00295   this->first = chain;
00296   this->first_shared = v;
00297 
00298   this->num_orders = 0;
00299   this->num_manual_orders = 0;
00300   this->num_vehicles = 1;
00301   this->timetable_duration = 0;
00302 
00303   for (Order *o = this->first; o != NULL; o = o->next) {
00304     ++this->num_orders;
00305     if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
00306     this->timetable_duration += o->wait_time + o->travel_time;
00307   }
00308 
00309   for (Vehicle *u = this->first_shared->PreviousShared(); u != NULL; u = u->PreviousShared()) {
00310     ++this->num_vehicles;
00311     this->first_shared = u;
00312   }
00313 
00314   for (const Vehicle *u = v->NextShared(); u != NULL; u = u->NextShared()) ++this->num_vehicles;
00315 }
00316 
00322 void OrderList::FreeChain(bool keep_orderlist)
00323 {
00324   Order *next;
00325   for (Order *o = this->first; o != NULL; o = next) {
00326     next = o->next;
00327     delete o;
00328   }
00329 
00330   if (keep_orderlist) {
00331     this->first = NULL;
00332     this->num_orders = 0;
00333     this->num_manual_orders = 0;
00334     this->timetable_duration = 0;
00335   } else {
00336     delete this;
00337   }
00338 }
00339 
00345 Order *OrderList::GetOrderAt(int index) const
00346 {
00347   if (index < 0) return NULL;
00348 
00349   Order *order = this->first;
00350 
00351   while (order != NULL && index-- > 0) {
00352     order = order->next;
00353   }
00354   return order;
00355 }
00356 
00362 void OrderList::InsertOrderAt(Order *new_order, int index)
00363 {
00364   if (this->first == NULL) {
00365     this->first = new_order;
00366   } else {
00367     if (index == 0) {
00368       /* Insert as first or only order */
00369       new_order->next = this->first;
00370       this->first = new_order;
00371     } else if (index >= this->num_orders) {
00372       /* index is after the last order, add it to the end */
00373       this->GetLastOrder()->next = new_order;
00374     } else {
00375       /* Put the new order in between */
00376       Order *order = this->GetOrderAt(index - 1);
00377       new_order->next = order->next;
00378       order->next = new_order;
00379     }
00380   }
00381   ++this->num_orders;
00382   if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
00383   this->timetable_duration += new_order->wait_time + new_order->travel_time;
00384 
00385   /* We can visit oil rigs and buoys that are not our own. They will be shown in
00386    * the list of stations. So, we need to invalidate that window if needed. */
00387   if (new_order->IsType(OT_GOTO_STATION) || new_order->IsType(OT_GOTO_WAYPOINT)) {
00388     BaseStation *bs = BaseStation::Get(new_order->GetDestination());
00389     if (bs->owner == OWNER_NONE) InvalidateWindowClassesData(WC_STATION_LIST, 0);
00390   }
00391 
00392 }
00393 
00394 
00399 void OrderList::DeleteOrderAt(int index)
00400 {
00401   if (index >= this->num_orders) return;
00402 
00403   Order *to_remove;
00404 
00405   if (index == 0) {
00406     to_remove = this->first;
00407     this->first = to_remove->next;
00408   } else {
00409     Order *prev = GetOrderAt(index - 1);
00410     to_remove = prev->next;
00411     prev->next = to_remove->next;
00412   }
00413   --this->num_orders;
00414   if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
00415   this->timetable_duration -= (to_remove->wait_time + to_remove->travel_time);
00416   delete to_remove;
00417 }
00418 
00424 void OrderList::MoveOrder(int from, int to)
00425 {
00426   if (from >= this->num_orders || to >= this->num_orders || from == to) return;
00427 
00428   Order *moving_one;
00429 
00430   /* Take the moving order out of the pointer-chain */
00431   if (from == 0) {
00432     moving_one = this->first;
00433     this->first = moving_one->next;
00434   } else {
00435     Order *one_before = GetOrderAt(from - 1);
00436     moving_one = one_before->next;
00437     one_before->next = moving_one->next;
00438   }
00439 
00440   /* Insert the moving_order again in the pointer-chain */
00441   if (to == 0) {
00442     moving_one->next = this->first;
00443     this->first = moving_one;
00444   } else {
00445     Order *one_before = GetOrderAt(to - 1);
00446     moving_one->next = one_before->next;
00447     one_before->next = moving_one;
00448   }
00449 }
00450 
00456 void OrderList::RemoveVehicle(Vehicle *v)
00457 {
00458   --this->num_vehicles;
00459   if (v == this->first_shared) this->first_shared = v->NextShared();
00460 }
00461 
00466 bool OrderList::IsVehicleInSharedOrdersList(const Vehicle *v) const
00467 {
00468   for (const Vehicle *v_shared = this->first_shared; v_shared != NULL; v_shared = v_shared->NextShared()) {
00469     if (v_shared == v) return true;
00470   }
00471 
00472   return false;
00473 }
00474 
00480 int OrderList::GetPositionInSharedOrderList(const Vehicle *v) const
00481 {
00482   int count = 0;
00483   for (const Vehicle *v_shared = v->PreviousShared(); v_shared != NULL; v_shared = v_shared->PreviousShared()) count++;
00484   return count;
00485 }
00486 
00491 bool OrderList::IsCompleteTimetable() const
00492 {
00493   for (Order *o = this->first; o != NULL; o = o->next) {
00494     /* Implicit orders are, by definition, not timetabled. */
00495     if (o->IsType(OT_IMPLICIT)) continue;
00496     if (!o->IsCompletelyTimetabled()) return false;
00497   }
00498   return true;
00499 }
00500 
00504 void OrderList::DebugCheckSanity() const
00505 {
00506   VehicleOrderID check_num_orders = 0;
00507   VehicleOrderID check_num_manual_orders = 0;
00508   uint check_num_vehicles = 0;
00509   Ticks check_timetable_duration = 0;
00510 
00511   DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
00512 
00513   for (const Order *o = this->first; o != NULL; o = o->next) {
00514     ++check_num_orders;
00515     if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
00516     check_timetable_duration += o->wait_time + o->travel_time;
00517   }
00518   assert(this->num_orders == check_num_orders);
00519   assert(this->num_manual_orders == check_num_manual_orders);
00520   assert(this->timetable_duration == check_timetable_duration);
00521 
00522   for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
00523     ++check_num_vehicles;
00524     assert(v->orders.list == this);
00525   }
00526   assert(this->num_vehicles == check_num_vehicles);
00527   DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i ticks",
00528       (uint)this->num_orders, (uint)this->num_manual_orders,
00529       this->num_vehicles, this->timetable_duration);
00530 }
00531 
00539 static inline bool OrderGoesToStation(const Vehicle *v, const Order *o)
00540 {
00541   return o->IsType(OT_GOTO_STATION) ||
00542       (v->type == VEH_AIRCRAFT && o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotActionType() & ODATFB_NEAREST_DEPOT));
00543 }
00544 
00551 static void DeleteOrderWarnings(const Vehicle *v)
00552 {
00553   DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS);
00554   DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_VOID_ORDER);
00555   DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_DUPLICATE_ENTRY);
00556   DeleteVehicleNews(v->index, STR_NEWS_VEHICLE_HAS_INVALID_ENTRY);
00557 }
00558 
00564 TileIndex Order::GetLocation(const Vehicle *v) const
00565 {
00566   switch (this->GetType()) {
00567     case OT_GOTO_WAYPOINT:
00568     case OT_GOTO_STATION:
00569     case OT_IMPLICIT:
00570       return BaseStation::Get(this->GetDestination())->xy;
00571 
00572     case OT_GOTO_DEPOT:
00573       if ((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return INVALID_TILE;
00574       return (v->type == VEH_AIRCRAFT) ? Station::Get(this->GetDestination())->xy : Depot::Get(this->GetDestination())->xy;
00575 
00576     default:
00577       return INVALID_TILE;
00578   }
00579 }
00580 
00581 static uint GetOrderDistance(const Order *prev, const Order *cur, const Vehicle *v, int conditional_depth = 0)
00582 {
00583   assert(v->type == VEH_SHIP);
00584 
00585   if (cur->IsType(OT_CONDITIONAL)) {
00586     if (conditional_depth > v->GetNumOrders()) return 0;
00587 
00588     conditional_depth++;
00589 
00590     int dist1 = GetOrderDistance(prev, v->GetOrder(cur->GetConditionSkipToOrder()), v, conditional_depth);
00591     int dist2 = GetOrderDistance(prev, cur->next == NULL ? v->orders.list->GetFirstOrder() : cur->next, v, conditional_depth);
00592     return max(dist1, dist2);
00593   }
00594 
00595   TileIndex prev_tile = prev->GetLocation(v);
00596   TileIndex cur_tile = cur->GetLocation(v);
00597   if (prev_tile == INVALID_TILE || cur_tile == INVALID_TILE) return 0;
00598   return DistanceManhattan(prev_tile, cur_tile);
00599 }
00600 
00614 CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00615 {
00616   VehicleID veh          = GB(p1,  0, 20);
00617   VehicleOrderID sel_ord = GB(p1, 20, 8);
00618   Order new_order(p2);
00619 
00620   Vehicle *v = Vehicle::GetIfValid(veh);
00621   if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00622 
00623   CommandCost ret = CheckOwnership(v->owner);
00624   if (ret.Failed()) return ret;
00625 
00626   /* Check if the inserted order is to the correct destination (owner, type),
00627    * and has the correct flags if any */
00628   switch (new_order.GetType()) {
00629     case OT_GOTO_STATION: {
00630       const Station *st = Station::GetIfValid(new_order.GetDestination());
00631       if (st == NULL) return CMD_ERROR;
00632 
00633       if (st->owner != OWNER_NONE) {
00634         CommandCost ret = CheckOwnership(st->owner);
00635         if (ret.Failed()) return ret;
00636       }
00637 
00638       if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
00639       for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
00640         if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED);
00641       }
00642 
00643       /* Non stop only allowed for ground vehicles. */
00644       if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
00645 
00646       /* Filter invalid load/unload types. */
00647       switch (new_order.GetLoadType()) {
00648         case OLF_LOAD_IF_POSSIBLE: case OLFB_FULL_LOAD: case OLF_FULL_LOAD_ANY: case OLFB_NO_LOAD: break;
00649         default: return CMD_ERROR;
00650       }
00651       switch (new_order.GetUnloadType()) {
00652         case OUF_UNLOAD_IF_POSSIBLE: case OUFB_UNLOAD: case OUFB_TRANSFER: case OUFB_NO_UNLOAD: break;
00653         default: return CMD_ERROR;
00654       }
00655 
00656       /* Filter invalid stop locations */
00657       switch (new_order.GetStopLocation()) {
00658         case OSL_PLATFORM_NEAR_END:
00659         case OSL_PLATFORM_MIDDLE:
00660           if (v->type != VEH_TRAIN) return CMD_ERROR;
00661           /* FALL THROUGH */
00662         case OSL_PLATFORM_FAR_END:
00663           break;
00664 
00665         default:
00666           return CMD_ERROR;
00667       }
00668 
00669       break;
00670     }
00671 
00672     case OT_GOTO_DEPOT: {
00673       if ((new_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) {
00674         if (v->type == VEH_AIRCRAFT) {
00675           const Station *st = Station::GetIfValid(new_order.GetDestination());
00676 
00677           if (st == NULL) return CMD_ERROR;
00678 
00679           CommandCost ret = CheckOwnership(st->owner);
00680           if (ret.Failed()) return ret;
00681 
00682           if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
00683             return CMD_ERROR;
00684           }
00685         } else {
00686           const Depot *dp = Depot::GetIfValid(new_order.GetDestination());
00687 
00688           if (dp == NULL) return CMD_ERROR;
00689 
00690           CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
00691           if (ret.Failed()) return ret;
00692 
00693           switch (v->type) {
00694             case VEH_TRAIN:
00695               if (!IsRailDepotTile(dp->xy)) return CMD_ERROR;
00696               break;
00697 
00698             case VEH_ROAD:
00699               if (!IsRoadDepotTile(dp->xy)) return CMD_ERROR;
00700               break;
00701 
00702             case VEH_SHIP:
00703               if (!IsShipDepotTile(dp->xy)) return CMD_ERROR;
00704               break;
00705 
00706             default: return CMD_ERROR;
00707           }
00708         }
00709       }
00710 
00711       if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
00712       if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR;
00713       if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT)) return CMD_ERROR;
00714       if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR;
00715       break;
00716     }
00717 
00718     case OT_GOTO_WAYPOINT: {
00719       const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
00720       if (wp == NULL) return CMD_ERROR;
00721 
00722       switch (v->type) {
00723         default: return CMD_ERROR;
00724 
00725         case VEH_TRAIN: {
00726           if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
00727 
00728           CommandCost ret = CheckOwnership(wp->owner);
00729           if (ret.Failed()) return ret;
00730           break;
00731         }
00732 
00733         case VEH_SHIP:
00734           if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
00735           if (wp->owner != OWNER_NONE) {
00736             CommandCost ret = CheckOwnership(wp->owner);
00737             if (ret.Failed()) return ret;
00738           }
00739           break;
00740       }
00741 
00742       /* Order flags can be any of the following for waypoints:
00743        * [non-stop]
00744        * non-stop orders (if any) are only valid for trains */
00745       if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
00746       break;
00747     }
00748 
00749     case OT_CONDITIONAL: {
00750       VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
00751       if (skip_to != 0 && skip_to >= v->GetNumOrders()) return CMD_ERROR; // Always allow jumping to the first (even when there is no order).
00752       if (new_order.GetConditionVariable() >= OCV_END) return CMD_ERROR;
00753 
00754       OrderConditionComparator occ = new_order.GetConditionComparator();
00755       if (occ >= OCC_END) return CMD_ERROR;
00756       switch (new_order.GetConditionVariable()) {
00757         case OCV_REQUIRES_SERVICE:
00758           if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) return CMD_ERROR;
00759           break;
00760 
00761         case OCV_UNCONDITIONALLY:
00762           if (occ != OCC_EQUALS) return CMD_ERROR;
00763           if (new_order.GetConditionValue() != 0) return CMD_ERROR;
00764           break;
00765 
00766         case OCV_LOAD_PERCENTAGE:
00767         case OCV_RELIABILITY:
00768           if (new_order.GetConditionValue() > 100) return CMD_ERROR;
00769           /* FALL THROUGH */
00770         default:
00771           if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) return CMD_ERROR;
00772           break;
00773       }
00774       break;
00775     }
00776 
00777     default: return CMD_ERROR;
00778   }
00779 
00780   if (sel_ord > v->GetNumOrders()) return CMD_ERROR;
00781 
00782   if (v->GetNumOrders() >= MAX_VEH_ORDER_ID) return_cmd_error(STR_ERROR_TOO_MANY_ORDERS);
00783   if (!Order::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
00784   if (v->orders.list == NULL && !OrderList::CanAllocateItem()) return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
00785 
00786   if (v->type == VEH_SHIP && _settings_game.pf.pathfinder_for_ships != VPF_NPF) {
00787     /* Make sure the new destination is not too far away from the previous */
00788     const Order *prev = NULL;
00789     uint n = 0;
00790 
00791     /* Find the last goto station or depot order before the insert location.
00792      * If the order is to be inserted at the beginning of the order list this
00793      * finds the last order in the list. */
00794     const Order *o;
00795     FOR_VEHICLE_ORDERS(v, o) {
00796       switch (o->GetType()) {
00797         case OT_GOTO_STATION:
00798         case OT_GOTO_DEPOT:
00799         case OT_GOTO_WAYPOINT:
00800           prev = o;
00801           break;
00802 
00803         default: break;
00804       }
00805       if (++n == sel_ord && prev != NULL) break;
00806     }
00807     if (prev != NULL) {
00808       uint dist = GetOrderDistance(prev, &new_order, v);
00809       if (dist >= 130) {
00810         return_cmd_error(STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION);
00811       }
00812     }
00813   }
00814 
00815   if (flags & DC_EXEC) {
00816     Order *new_o = new Order();
00817     new_o->AssignOrder(new_order);
00818     InsertOrder(v, new_o, sel_ord);
00819   }
00820 
00821   return CommandCost();
00822 }
00823 
00830 void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
00831 {
00832   /* Create new order and link in list */
00833   if (v->orders.list == NULL) {
00834     v->orders.list = new OrderList(new_o, v);
00835   } else {
00836     v->orders.list->InsertOrderAt(new_o, sel_ord);
00837   }
00838 
00839   Vehicle *u = v->FirstShared();
00840   DeleteOrderWarnings(u);
00841   for (; u != NULL; u = u->NextShared()) {
00842     assert(v->orders.list == u->orders.list);
00843 
00844     /* If there is added an order before the current one, we need
00845      * to update the selected order. We do not change implicit/real order indices though.
00846      * If the new order is between the current implicit order and real order, the implicit order will
00847      * later skip the inserted order. */
00848     if (sel_ord <= u->cur_real_order_index) {
00849       uint cur = u->cur_real_order_index + 1;
00850       /* Check if we don't go out of bound */
00851       if (cur < u->GetNumOrders()) {
00852         u->cur_real_order_index = cur;
00853       }
00854     }
00855     if (sel_ord == u->cur_implicit_order_index && u->IsGroundVehicle()) {
00856       /* We are inserting an order just before the current implicit order.
00857        * We do not know whether we will reach current implicit or the newly inserted order first.
00858        * So, disable creation of implicit orders until we are on track again. */
00859       uint16 &gv_flags = u->GetGroundVehicleFlags();
00860       SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
00861     }
00862     if (sel_ord <= u->cur_implicit_order_index) {
00863       uint cur = u->cur_implicit_order_index + 1;
00864       /* Check if we don't go out of bound */
00865       if (cur < u->GetNumOrders()) {
00866         u->cur_implicit_order_index = cur;
00867       }
00868     }
00869     /* Update any possible open window of the vehicle */
00870     InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
00871   }
00872 
00873   /* As we insert an order, the order to skip to will be 'wrong'. */
00874   VehicleOrderID cur_order_id = 0;
00875   Order *order;
00876   FOR_VEHICLE_ORDERS(v, order) {
00877     if (order->IsType(OT_CONDITIONAL)) {
00878       VehicleOrderID order_id = order->GetConditionSkipToOrder();
00879       if (order_id >= sel_ord) {
00880         order->SetConditionSkipToOrder(order_id + 1);
00881       }
00882       if (order_id == cur_order_id) {
00883         order->SetConditionSkipToOrder((order_id + 1) % v->GetNumOrders());
00884       }
00885     }
00886     cur_order_id++;
00887   }
00888 
00889   /* Make sure to rebuild the whole list */
00890   InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
00891 }
00892 
00898 static CommandCost DecloneOrder(Vehicle *dst, DoCommandFlag flags)
00899 {
00900   if (flags & DC_EXEC) {
00901     DeleteVehicleOrders(dst);
00902     InvalidateVehicleOrder(dst, -1);
00903     InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
00904   }
00905   return CommandCost();
00906 }
00907 
00917 CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
00918 {
00919   VehicleID veh_id = GB(p1, 0, 20);
00920   VehicleOrderID sel_ord = GB(p2, 0, 8);
00921 
00922   Vehicle *v = Vehicle::GetIfValid(veh_id);
00923 
00924   if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
00925 
00926   CommandCost ret = CheckOwnership(v->owner);
00927   if (ret.Failed()) return ret;
00928 
00929   /* If we did not select an order, we maybe want to de-clone the orders */
00930   if (sel_ord >= v->GetNumOrders()) return DecloneOrder(v, flags);
00931 
00932   if (v->GetOrder(sel_ord) == NULL) return CMD_ERROR;
00933 
00934   if (flags & DC_EXEC) DeleteOrder(v, sel_ord);
00935   return CommandCost();
00936 }
00937 
00942 static void CancelLoadingDueToDeletedOrder(Vehicle *v)
00943 {
00944   assert(v->current_order.IsType(OT_LOADING));
00945   /* NON-stop flag is misused to see if a train is in a station that is
00946    * on his order list or not */
00947   v->current_order.SetNonStopType(ONSF_STOP_EVERYWHERE);
00948   /* When full loading, "cancel" that order so the vehicle doesn't
00949    * stay indefinitely at this station anymore. */
00950   if (v->current_order.GetLoadType() & OLFB_FULL_LOAD) v->current_order.SetLoadType(OLF_LOAD_IF_POSSIBLE);
00951 }
00952 
00958 void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
00959 {
00960   v->orders.list->DeleteOrderAt(sel_ord);
00961 
00962   Vehicle *u = v->FirstShared();
00963   DeleteOrderWarnings(u);
00964   for (; u != NULL; u = u->NextShared()) {
00965     assert(v->orders.list == u->orders.list);
00966 
00967     if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
00968       CancelLoadingDueToDeletedOrder(u);
00969     }
00970 
00971     if (sel_ord < u->cur_real_order_index) {
00972       u->cur_real_order_index--;
00973     } else if (sel_ord == u->cur_real_order_index) {
00974       u->UpdateRealOrderIndex();
00975     }
00976 
00977     if (sel_ord < u->cur_implicit_order_index) {
00978       u->cur_implicit_order_index--;
00979     } else if (sel_ord == u->cur_implicit_order_index) {
00980       /* Make sure the index is valid */
00981       if (u->cur_implicit_order_index >= u->GetNumOrders()) u->cur_implicit_order_index = 0;
00982 
00983       /* Skip non-implicit orders for the implicit-order-index (e.g. if the current implicit order was deleted */
00984       while (u->cur_implicit_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_implicit_order_index)->IsType(OT_IMPLICIT)) {
00985         u->cur_implicit_order_index++;
00986         if (u->cur_implicit_order_index >= u->GetNumOrders()) u->cur_implicit_order_index = 0;
00987       }
00988     }
00989 
00990     /* Update any possible open window of the vehicle */
00991     InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
00992   }
00993 
00994   /* As we delete an order, the order to skip to will be 'wrong'. */
00995   VehicleOrderID cur_order_id = 0;
00996   Order *order = NULL;
00997   FOR_VEHICLE_ORDERS(v, order) {
00998     if (order->IsType(OT_CONDITIONAL)) {
00999       VehicleOrderID order_id = order->GetConditionSkipToOrder();
01000       if (order_id >= sel_ord) {
01001         order_id = max(order_id - 1, 0);
01002       }
01003       if (order_id == cur_order_id) {
01004         order_id = (order_id + 1) % v->GetNumOrders();
01005       }
01006       order->SetConditionSkipToOrder(order_id);
01007     }
01008     cur_order_id++;
01009   }
01010 
01011   InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
01012 }
01013 
01023 CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01024 {
01025   VehicleID veh_id = GB(p1, 0, 20);
01026   VehicleOrderID sel_ord = GB(p2, 0, 8);
01027 
01028   Vehicle *v = Vehicle::GetIfValid(veh_id);
01029 
01030   if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_implicit_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
01031 
01032   CommandCost ret = CheckOwnership(v->owner);
01033   if (ret.Failed()) return ret;
01034 
01035   if (flags & DC_EXEC) {
01036     v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
01037     v->UpdateRealOrderIndex();
01038 
01039     if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
01040 
01041     InvalidateVehicleOrder(v, -2);
01042   }
01043 
01044   /* We have an aircraft/ship, they have a mini-schedule, so update them all */
01045   if (v->type == VEH_AIRCRAFT) SetWindowClassesDirty(WC_AIRCRAFT_LIST);
01046   if (v->type == VEH_SHIP) SetWindowClassesDirty(WC_SHIPS_LIST);
01047 
01048   return CommandCost();
01049 }
01050 
01064 CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01065 {
01066   VehicleID veh = GB(p1, 0, 20);
01067   VehicleOrderID moving_order = GB(p2,  0, 16);
01068   VehicleOrderID target_order = GB(p2, 16, 16);
01069 
01070   Vehicle *v = Vehicle::GetIfValid(veh);
01071   if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
01072 
01073   CommandCost ret = CheckOwnership(v->owner);
01074   if (ret.Failed()) return ret;
01075 
01076   /* Don't make senseless movements */
01077   if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() ||
01078       moving_order == target_order || v->GetNumOrders() <= 1) return CMD_ERROR;
01079 
01080   Order *moving_one = v->GetOrder(moving_order);
01081   /* Don't move an empty order */
01082   if (moving_one == NULL) return CMD_ERROR;
01083 
01084   if (flags & DC_EXEC) {
01085     v->orders.list->MoveOrder(moving_order, target_order);
01086 
01087     /* Update shared list */
01088     Vehicle *u = v->FirstShared();
01089 
01090     DeleteOrderWarnings(u);
01091 
01092     for (; u != NULL; u = u->NextShared()) {
01093       /* Update the current order.
01094        * There are multiple ways to move orders, which result in cur_implicit_order_index
01095        * and cur_real_order_index to not longer make any sense. E.g. moving another
01096        * real order between them.
01097        *
01098        * Basically one could choose to preserve either of them, but not both.
01099        * While both ways are suitable in this or that case from a human point of view, neither
01100        * of them makes really sense.
01101        * However, from an AI point of view, preserving cur_real_order_index is the most
01102        * predictable and transparent behaviour.
01103        *
01104        * With that decision it basically does not matter what we do to cur_implicit_order_index.
01105        * If we change orders between the implict- and real-index, the implicit orders are mostly likely
01106        * completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well.
01107        * The worst which can happen is that a lot of implicit orders are removed when reaching current_order.
01108        */
01109       if (u->cur_real_order_index == moving_order) {
01110         u->cur_real_order_index = target_order;
01111       } else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) {
01112         u->cur_real_order_index--;
01113       } else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) {
01114         u->cur_real_order_index++;
01115       }
01116 
01117       if (u->cur_implicit_order_index == moving_order) {
01118         u->cur_implicit_order_index = target_order;
01119       } else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) {
01120         u->cur_implicit_order_index--;
01121       } else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
01122         u->cur_implicit_order_index++;
01123       }
01124 
01125       assert(v->orders.list == u->orders.list);
01126       /* Update any possible open window of the vehicle */
01127       InvalidateVehicleOrder(u, moving_order | (target_order << 8));
01128     }
01129 
01130     /* As we move an order, the order to skip to will be 'wrong'. */
01131     Order *order;
01132     FOR_VEHICLE_ORDERS(v, order) {
01133       if (order->IsType(OT_CONDITIONAL)) {
01134         VehicleOrderID order_id = order->GetConditionSkipToOrder();
01135         if (order_id == moving_order) {
01136           order_id = target_order;
01137         } else if (order_id > moving_order && order_id <= target_order) {
01138           order_id--;
01139         } else if (order_id < moving_order && order_id >= target_order) {
01140           order_id++;
01141         }
01142         order->SetConditionSkipToOrder(order_id);
01143       }
01144     }
01145 
01146     /* Make sure to rebuild the whole list */
01147     InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0);
01148   }
01149 
01150   return CommandCost();
01151 }
01152 
01168 CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01169 {
01170   VehicleOrderID sel_ord = GB(p1, 20,  8);
01171   VehicleID veh          = GB(p1,  0, 20);
01172   ModifyOrderFlags mof   = Extract<ModifyOrderFlags, 0, 4>(p2);
01173   uint16 data            = GB(p2,  4, 11);
01174 
01175   if (mof >= MOF_END) return CMD_ERROR;
01176 
01177   Vehicle *v = Vehicle::GetIfValid(veh);
01178   if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
01179 
01180   CommandCost ret = CheckOwnership(v->owner);
01181   if (ret.Failed()) return ret;
01182 
01183   /* Is it a valid order? */
01184   if (sel_ord >= v->GetNumOrders()) return CMD_ERROR;
01185 
01186   Order *order = v->GetOrder(sel_ord);
01187   switch (order->GetType()) {
01188     case OT_GOTO_STATION:
01189       if (mof == MOF_COND_VARIABLE || mof == MOF_COND_COMPARATOR || mof == MOF_DEPOT_ACTION || mof == MOF_COND_VALUE) return CMD_ERROR;
01190       break;
01191 
01192     case OT_GOTO_DEPOT:
01193       if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
01194       break;
01195 
01196     case OT_GOTO_WAYPOINT:
01197       if (mof != MOF_NON_STOP) return CMD_ERROR;
01198       break;
01199 
01200     case OT_CONDITIONAL:
01201       if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE && mof != MOF_COND_DESTINATION) return CMD_ERROR;
01202       break;
01203 
01204     default:
01205       return CMD_ERROR;
01206   }
01207 
01208   switch (mof) {
01209     default: NOT_REACHED();
01210 
01211     case MOF_NON_STOP:
01212       if (!v->IsGroundVehicle()) return CMD_ERROR;
01213       if (data >= ONSF_END) return CMD_ERROR;
01214       if (data == order->GetNonStopType()) return CMD_ERROR;
01215       break;
01216 
01217     case MOF_STOP_LOCATION:
01218       if (v->type != VEH_TRAIN) return CMD_ERROR;
01219       if (data >= OSL_END) return CMD_ERROR;
01220       break;
01221 
01222     case MOF_UNLOAD:
01223       if ((data & ~(OUFB_UNLOAD | OUFB_TRANSFER | OUFB_NO_UNLOAD)) != 0) return CMD_ERROR;
01224       /* Unload and no-unload are mutual exclusive and so are transfer and no unload. */
01225       if (data != 0 && ((data & (OUFB_UNLOAD | OUFB_TRANSFER)) != 0) == ((data & OUFB_NO_UNLOAD) != 0)) return CMD_ERROR;
01226       if (data == order->GetUnloadType()) return CMD_ERROR;
01227       break;
01228 
01229     case MOF_LOAD:
01230       if (data > OLFB_NO_LOAD || data == 1) return CMD_ERROR;
01231       if (data == order->GetLoadType()) return CMD_ERROR;
01232       break;
01233 
01234     case MOF_DEPOT_ACTION:
01235       if (data >= DA_END) return CMD_ERROR;
01236       break;
01237 
01238     case MOF_COND_VARIABLE:
01239       if (data >= OCV_END) return CMD_ERROR;
01240       break;
01241 
01242     case MOF_COND_COMPARATOR:
01243       if (data >= OCC_END) return CMD_ERROR;
01244       switch (order->GetConditionVariable()) {
01245         case OCV_UNCONDITIONALLY: return CMD_ERROR;
01246 
01247         case OCV_REQUIRES_SERVICE:
01248           if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
01249           break;
01250 
01251         default:
01252           if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
01253           break;
01254       }
01255       break;
01256 
01257     case MOF_COND_VALUE:
01258       switch (order->GetConditionVariable()) {
01259         case OCV_UNCONDITIONALLY: return CMD_ERROR;
01260 
01261         case OCV_LOAD_PERCENTAGE:
01262         case OCV_RELIABILITY:
01263           if (data > 100) return CMD_ERROR;
01264           break;
01265 
01266         default:
01267           if (data > 2047) return CMD_ERROR;
01268           break;
01269       }
01270       break;
01271 
01272     case MOF_COND_DESTINATION:
01273       if (data >= v->GetNumOrders()) return CMD_ERROR;
01274       break;
01275   }
01276 
01277   if (flags & DC_EXEC) {
01278     switch (mof) {
01279       case MOF_NON_STOP:
01280         order->SetNonStopType((OrderNonStopFlags)data);
01281         break;
01282 
01283       case MOF_STOP_LOCATION:
01284         order->SetStopLocation((OrderStopLocation)data);
01285         break;
01286 
01287       case MOF_UNLOAD:
01288         order->SetUnloadType((OrderUnloadFlags)data);
01289         break;
01290 
01291       case MOF_LOAD:
01292         order->SetLoadType((OrderLoadFlags)data);
01293         break;
01294 
01295       case MOF_DEPOT_ACTION: {
01296         switch (data) {
01297           case DA_ALWAYS_GO:
01298             order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
01299             order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
01300             break;
01301 
01302           case DA_SERVICE:
01303             order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() | ODTFB_SERVICE));
01304             order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
01305             order->SetRefit(CT_NO_REFIT);
01306             break;
01307 
01308           case DA_STOP:
01309             order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
01310             order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() | ODATFB_HALT));
01311             order->SetRefit(CT_NO_REFIT);
01312             break;
01313 
01314           default:
01315             NOT_REACHED();
01316         }
01317         break;
01318       }
01319 
01320       case MOF_COND_VARIABLE: {
01321         order->SetConditionVariable((OrderConditionVariable)data);
01322 
01323         OrderConditionComparator occ = order->GetConditionComparator();
01324         switch (order->GetConditionVariable()) {
01325           case OCV_UNCONDITIONALLY:
01326             order->SetConditionComparator(OCC_EQUALS);
01327             order->SetConditionValue(0);
01328             break;
01329 
01330           case OCV_REQUIRES_SERVICE:
01331             if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
01332             break;
01333 
01334           case OCV_LOAD_PERCENTAGE:
01335           case OCV_RELIABILITY:
01336             if (order->GetConditionValue() > 100) order->SetConditionValue(100);
01337             /* FALL THROUGH */
01338           default:
01339             if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
01340             break;
01341         }
01342         break;
01343       }
01344 
01345       case MOF_COND_COMPARATOR:
01346         order->SetConditionComparator((OrderConditionComparator)data);
01347         break;
01348 
01349       case MOF_COND_VALUE:
01350         order->SetConditionValue(data);
01351         break;
01352 
01353       case MOF_COND_DESTINATION:
01354         order->SetConditionSkipToOrder(data);
01355         break;
01356 
01357       default: NOT_REACHED();
01358     }
01359 
01360     /* Update the windows and full load flags, also for vehicles that share the same order list */
01361     Vehicle *u = v->FirstShared();
01362     DeleteOrderWarnings(u);
01363     for (; u != NULL; u = u->NextShared()) {
01364       /* Toggle u->current_order "Full load" flag if it changed.
01365        * However, as the same flag is used for depot orders, check
01366        * whether we are not going to a depot as there are three
01367        * cases where the full load flag can be active and only
01368        * one case where the flag is used for depot orders. In the
01369        * other cases for the OrderTypeByte the flags are not used,
01370        * so do not care and those orders should not be active
01371        * when this function is called.
01372        */
01373       if (sel_ord == u->cur_real_order_index &&
01374           (u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
01375           u->current_order.GetLoadType() != order->GetLoadType()) {
01376         u->current_order.SetLoadType(order->GetLoadType());
01377       }
01378       InvalidateVehicleOrder(u, -2);
01379     }
01380   }
01381 
01382   return CommandCost();
01383 }
01384 
01396 CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01397 {
01398   VehicleID veh_src = GB(p2, 0, 20);
01399   VehicleID veh_dst = GB(p1, 0, 20);
01400 
01401   Vehicle *dst = Vehicle::GetIfValid(veh_dst);
01402   if (dst == NULL || !dst->IsPrimaryVehicle()) return CMD_ERROR;
01403 
01404   CommandCost ret = CheckOwnership(dst->owner);
01405   if (ret.Failed()) return ret;
01406 
01407   switch (GB(p1, 30, 2)) {
01408     case CO_SHARE: {
01409       Vehicle *src = Vehicle::GetIfValid(veh_src);
01410 
01411       /* Sanity checks */
01412       if (src == NULL || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
01413 
01414       CommandCost ret = CheckOwnership(src->owner);
01415       if (ret.Failed()) return ret;
01416 
01417       /* Trucks can't share orders with busses (and visa versa) */
01418       if (src->type == VEH_ROAD && RoadVehicle::From(src)->IsBus() != RoadVehicle::From(dst)->IsBus()) {
01419         return CMD_ERROR;
01420       }
01421 
01422       /* Is the vehicle already in the shared list? */
01423       if (src->FirstShared() == dst->FirstShared()) return CMD_ERROR;
01424 
01425       const Order *order;
01426 
01427       FOR_VEHICLE_ORDERS(src, order) {
01428         if (OrderGoesToStation(dst, order) &&
01429             !CanVehicleUseStation(dst, Station::Get(order->GetDestination()))) {
01430           return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
01431         }
01432       }
01433 
01434       if (src->orders.list == NULL && !OrderList::CanAllocateItem()) {
01435         return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
01436       }
01437 
01438       if (flags & DC_EXEC) {
01439         /* If the destination vehicle had a OrderList, destroy it.
01440          * We only reset the order indices, if the new orders are obviously different.
01441          * (We mainly do this to keep the order indices valid and in range.) */
01442         DeleteVehicleOrders(dst, false, dst->GetNumOrders() != src->GetNumOrders());
01443 
01444         dst->orders.list = src->orders.list;
01445 
01446         /* Link this vehicle in the shared-list */
01447         dst->AddToShared(src);
01448 
01449         InvalidateVehicleOrder(dst, -1);
01450         InvalidateVehicleOrder(src, -2);
01451 
01452         InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
01453       }
01454       break;
01455     }
01456 
01457     case CO_COPY: {
01458       Vehicle *src = Vehicle::GetIfValid(veh_src);
01459 
01460       /* Sanity checks */
01461       if (src == NULL || !src->IsPrimaryVehicle() || dst->type != src->type || dst == src) return CMD_ERROR;
01462 
01463       CommandCost ret = CheckOwnership(src->owner);
01464       if (ret.Failed()) return ret;
01465 
01466       /* Trucks can't copy all the orders from busses (and visa versa),
01467        * and neither can helicopters and aircarft. */
01468       const Order *order;
01469       FOR_VEHICLE_ORDERS(src, order) {
01470         if (OrderGoesToStation(dst, order) &&
01471             !CanVehicleUseStation(dst, Station::Get(order->GetDestination()))) {
01472           return_cmd_error(STR_ERROR_CAN_T_COPY_SHARE_ORDER);
01473         }
01474       }
01475 
01476       /* make sure there are orders available */
01477       int delta = dst->IsOrderListShared() ? src->GetNumOrders() + 1 : src->GetNumOrders() - dst->GetNumOrders();
01478       if (!Order::CanAllocateItem(delta) ||
01479           ((dst->orders.list == NULL || dst->IsOrderListShared()) && !OrderList::CanAllocateItem())) {
01480         return_cmd_error(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS);
01481       }
01482 
01483       if (flags & DC_EXEC) {
01484         const Order *order;
01485         Order *first = NULL;
01486         Order **order_dst;
01487 
01488         /* If the destination vehicle had an order list, destroy the chain but keep the OrderList.
01489          * We only reset the order indices, if the new orders are obviously different.
01490          * (We mainly do this to keep the order indices valid and in range.) */
01491         DeleteVehicleOrders(dst, true, dst->GetNumOrders() != src->GetNumOrders());
01492 
01493         order_dst = &first;
01494         FOR_VEHICLE_ORDERS(src, order) {
01495           *order_dst = new Order();
01496           (*order_dst)->AssignOrder(*order);
01497           order_dst = &(*order_dst)->next;
01498         }
01499         if (dst->orders.list == NULL) {
01500           dst->orders.list = new OrderList(first, dst);
01501         } else {
01502           assert(dst->orders.list->GetFirstOrder() == NULL);
01503           assert(!dst->orders.list->IsShared());
01504           delete dst->orders.list;
01505           dst->orders.list = new OrderList(first, dst);
01506         }
01507 
01508         InvalidateVehicleOrder(dst, -1);
01509 
01510         InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
01511       }
01512       break;
01513     }
01514 
01515     case CO_UNSHARE: return DecloneOrder(dst, flags);
01516     default: return CMD_ERROR;
01517   }
01518 
01519   return CommandCost();
01520 }
01521 
01534 CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
01535 {
01536   VehicleID veh = GB(p1, 0, 20);
01537   VehicleOrderID order_number  = GB(p2, 16, 8);
01538   CargoID cargo = GB(p2, 0, 8);
01539   byte subtype  = GB(p2, 8, 8);
01540 
01541   if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT) return CMD_ERROR;
01542 
01543   const Vehicle *v = Vehicle::GetIfValid(veh);
01544   if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
01545 
01546   CommandCost ret = CheckOwnership(v->owner);
01547   if (ret.Failed()) return ret;
01548 
01549   Order *order = v->GetOrder(order_number);
01550   if (order == NULL) return CMD_ERROR;
01551 
01552   if (flags & DC_EXEC) {
01553     order->SetRefit(cargo, subtype);
01554 
01555     /* Make the depot order an 'always go' order. */
01556     if (cargo != CT_NO_REFIT) {
01557       order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
01558       order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
01559     }
01560 
01561     for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
01562       /* Update any possible open window of the vehicle */
01563       InvalidateVehicleOrder(u, -2);
01564 
01565       /* If the vehicle already got the current depot set as current order, then update current order as well */
01566       if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
01567         u->current_order.SetRefit(cargo, subtype);
01568       }
01569     }
01570   }
01571 
01572   return CommandCost();
01573 }
01574 
01575 
01581 void CheckOrders(const Vehicle *v)
01582 {
01583   /* Does the user wants us to check things? */
01584   if (_settings_client.gui.order_review_system == 0) return;
01585 
01586   /* Do nothing for crashed vehicles */
01587   if (v->vehstatus & VS_CRASHED) return;
01588 
01589   /* Do nothing for stopped vehicles if setting is '1' */
01590   if (_settings_client.gui.order_review_system == 1 && (v->vehstatus & VS_STOPPED)) return;
01591 
01592   /* do nothing we we're not the first vehicle in a share-chain */
01593   if (v->FirstShared() != v) return;
01594 
01595   /* Only check every 20 days, so that we don't flood the message log */
01596   if (v->owner == _local_company && v->day_counter % 20 == 0) {
01597     int n_st, problem_type = -1;
01598     const Order *order;
01599     int message = 0;
01600 
01601     /* Check the order list */
01602     n_st = 0;
01603 
01604     FOR_VEHICLE_ORDERS(v, order) {
01605       /* Dummy order? */
01606       if (order->IsType(OT_DUMMY)) {
01607         problem_type = 1;
01608         break;
01609       }
01610       /* Does station have a load-bay for this vehicle? */
01611       if (order->IsType(OT_GOTO_STATION)) {
01612         const Station *st = Station::Get(order->GetDestination());
01613 
01614         n_st++;
01615         if (!CanVehicleUseStation(v, st)) problem_type = 3;
01616       }
01617     }
01618 
01619     /* Check if the last and the first order are the same */
01620     if (v->GetNumOrders() > 1) {
01621       const Order *last = v->GetLastOrder();
01622 
01623       if (v->orders.list->GetFirstOrder()->Equals(*last)) {
01624         problem_type = 2;
01625       }
01626     }
01627 
01628     /* Do we only have 1 station in our order list? */
01629     if (n_st < 2 && problem_type == -1) problem_type = 0;
01630 
01631 #ifndef NDEBUG
01632     if (v->orders.list != NULL) v->orders.list->DebugCheckSanity();
01633 #endif
01634 
01635     /* We don't have a problem */
01636     if (problem_type < 0) return;
01637 
01638     message = STR_NEWS_VEHICLE_HAS_TOO_FEW_ORDERS + problem_type;
01639     //DEBUG(misc, 3, "Triggered News Item for vehicle %d", v->index);
01640 
01641     SetDParam(0, v->index);
01642     AddVehicleNewsItem(
01643       message,
01644       NS_ADVICE,
01645       v->index
01646     );
01647   }
01648 }
01649 
01655 void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination)
01656 {
01657   Vehicle *v;
01658 
01659   /* Aircraft have StationIDs for depot orders and never use DepotIDs
01660    * This fact is handled specially below
01661    */
01662 
01663   /* Go through all vehicles */
01664   FOR_ALL_VEHICLES(v) {
01665     Order *order;
01666 
01667     order = &v->current_order;
01668     if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type &&
01669         v->current_order.GetDestination() == destination) {
01670       order->MakeDummy();
01671       SetWindowDirty(WC_VEHICLE_VIEW, v->index);
01672     }
01673 
01674     /* Clear the order from the order-list */
01675     int id = -1;
01676     FOR_VEHICLE_ORDERS(v, order) {
01677       id++;
01678 restart:
01679 
01680       OrderType ot = order->GetType();
01681       if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
01682       if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT)) ot = OT_GOTO_STATION;
01683       if (ot == type && order->GetDestination() == destination) {
01684         /* We want to clear implicit orders, but we don't want to make them
01685          * dummy orders. They should just vanish. Also check the actual order
01686          * type as ot is currently OT_GOTO_STATION. */
01687         if (order->IsType(OT_IMPLICIT)) {
01688           order = order->next; // DeleteOrder() invalidates current order
01689           DeleteOrder(v, id);
01690           if (order != NULL) goto restart;
01691           break;
01692         }
01693 
01694         order->MakeDummy();
01695         for (const Vehicle *w = v->FirstShared(); w != NULL; w = w->NextShared()) {
01696           /* In GUI, simulate by removing the order and adding it back */
01697           InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
01698           InvalidateVehicleOrder(w, (INVALID_VEH_ORDER_ID << 8) | id);
01699         }
01700       }
01701     }
01702   }
01703 
01704   OrderBackup::RemoveOrder(type, destination);
01705 }
01706 
01711 bool Vehicle::HasDepotOrder() const
01712 {
01713   const Order *order;
01714 
01715   FOR_VEHICLE_ORDERS(this, order) {
01716     if (order->IsType(OT_GOTO_DEPOT)) return true;
01717   }
01718 
01719   return false;
01720 }
01721 
01731 void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
01732 {
01733   DeleteOrderWarnings(v);
01734 
01735   if (v->IsOrderListShared()) {
01736     /* Remove ourself from the shared order list. */
01737     v->RemoveFromShared();
01738     v->orders.list = NULL;
01739   } else if (v->orders.list != NULL) {
01740     /* Remove the orders */
01741     v->orders.list->FreeChain(keep_orderlist);
01742     if (!keep_orderlist) v->orders.list = NULL;
01743   }
01744 
01745   if (reset_order_indices) {
01746     v->cur_implicit_order_index = v->cur_real_order_index = 0;
01747     if (v->current_order.IsType(OT_LOADING)) {
01748       CancelLoadingDueToDeletedOrder(v);
01749     }
01750   }
01751 }
01752 
01760 uint16 GetServiceIntervalClamped(uint interval, CompanyID company_id)
01761 {
01762   return (Company::Get(company_id)->settings.vehicle.servint_ispercent) ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
01763 }
01764 
01773 static bool CheckForValidOrders(const Vehicle *v)
01774 {
01775   const Order *order;
01776 
01777   FOR_VEHICLE_ORDERS(v, order) {
01778     switch (order->GetType()) {
01779       case OT_GOTO_STATION:
01780       case OT_GOTO_DEPOT:
01781       case OT_GOTO_WAYPOINT:
01782         return true;
01783 
01784       default:
01785         break;
01786     }
01787   }
01788 
01789   return false;
01790 }
01791 
01795 static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
01796 {
01797   switch (occ) {
01798     case OCC_EQUALS:      return variable == value;
01799     case OCC_NOT_EQUALS:  return variable != value;
01800     case OCC_LESS_THAN:   return variable <  value;
01801     case OCC_LESS_EQUALS: return variable <= value;
01802     case OCC_MORE_THAN:   return variable >  value;
01803     case OCC_MORE_EQUALS: return variable >= value;
01804     case OCC_IS_TRUE:     return variable != 0;
01805     case OCC_IS_FALSE:    return variable == 0;
01806     default: NOT_REACHED();
01807   }
01808 }
01809 
01816 VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
01817 {
01818   if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
01819 
01820   bool skip_order = false;
01821   OrderConditionComparator occ = order->GetConditionComparator();
01822   uint16 value = order->GetConditionValue();
01823 
01824   switch (order->GetConditionVariable()) {
01825     case OCV_LOAD_PERCENTAGE:  skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
01826     case OCV_RELIABILITY:      skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability),       value); break;
01827     case OCV_MAX_SPEED:        skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
01828     case OCV_AGE:              skip_order = OrderConditionCompare(occ, v->age / DAYS_IN_LEAP_YEAR,        value); break;
01829     case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(),               value); break;
01830     case OCV_UNCONDITIONALLY:  skip_order = true; break;
01831     default: NOT_REACHED();
01832   }
01833 
01834   return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
01835 }
01836 
01844 bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool pbs_look_ahead)
01845 {
01846   if (conditional_depth > v->GetNumOrders()) return false;
01847 
01848   switch (order->GetType()) {
01849     case OT_GOTO_STATION:
01850       v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
01851       return true;
01852 
01853     case OT_GOTO_DEPOT:
01854       if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
01855         assert(!pbs_look_ahead);
01856         UpdateVehicleTimetable(v, true);
01857         v->IncrementRealOrderIndex();
01858         break;
01859       }
01860 
01861       if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
01862         /* We need to search for the nearest depot (hangar). */
01863         TileIndex location;
01864         DestinationID destination;
01865         bool reverse;
01866 
01867         if (v->FindClosestDepot(&location, &destination, &reverse)) {
01868           /* PBS reservations cannot reverse */
01869           if (pbs_look_ahead && reverse) return false;
01870 
01871           v->dest_tile = location;
01872           v->current_order.MakeGoToDepot(destination, v->current_order.GetDepotOrderType(), v->current_order.GetNonStopType(), (OrderDepotActionFlags)(v->current_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT), v->current_order.GetRefitCargo(), v->current_order.GetRefitSubtype());
01873 
01874           /* If there is no depot in front, reverse automatically (trains only) */
01875           if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
01876 
01877           if (v->type == VEH_AIRCRAFT) {
01878             Aircraft *a = Aircraft::From(v);
01879             if (a->state == FLYING && a->targetairport != destination) {
01880               /* The aircraft is now heading for a different hangar than the next in the orders */
01881               extern void AircraftNextAirportPos_and_Order(Aircraft *a);
01882               AircraftNextAirportPos_and_Order(a);
01883             }
01884           }
01885           return true;
01886         }
01887 
01888         /* If there is no depot, we cannot help PBS either. */
01889         if (pbs_look_ahead) return false;
01890 
01891         UpdateVehicleTimetable(v, true);
01892         v->IncrementRealOrderIndex();
01893       } else {
01894         if (v->type != VEH_AIRCRAFT) {
01895           v->dest_tile = Depot::Get(order->GetDestination())->xy;
01896         }
01897         return true;
01898       }
01899       break;
01900 
01901     case OT_GOTO_WAYPOINT:
01902       v->dest_tile = Waypoint::Get(order->GetDestination())->xy;
01903       return true;
01904 
01905     case OT_CONDITIONAL: {
01906       assert(!pbs_look_ahead);
01907       VehicleOrderID next_order = ProcessConditionalOrder(order, v);
01908       if (next_order != INVALID_VEH_ORDER_ID) {
01909         /* Jump to next_order. cur_implicit_order_index becomes exactly that order,
01910          * cur_real_order_index might come after next_order. */
01911         UpdateVehicleTimetable(v, false);
01912         v->cur_implicit_order_index = v->cur_real_order_index = next_order;
01913         v->UpdateRealOrderIndex();
01914         v->current_order_time += v->GetOrder(v->cur_real_order_index)->travel_time;
01915 
01916         /* Disable creation of implicit orders.
01917          * When inserting them we do not know that we would have to make the conditional orders point to them. */
01918         if (v->IsGroundVehicle()) {
01919           uint16 &gv_flags = v->GetGroundVehicleFlags();
01920           SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
01921         }
01922       } else {
01923         UpdateVehicleTimetable(v, true);
01924         v->IncrementRealOrderIndex();
01925       }
01926       break;
01927     }
01928 
01929     default:
01930       v->dest_tile = 0;
01931       return false;
01932   }
01933 
01934   assert(v->cur_implicit_order_index < v->GetNumOrders());
01935   assert(v->cur_real_order_index < v->GetNumOrders());
01936 
01937   /* Get the current order */
01938   order = v->GetOrder(v->cur_real_order_index);
01939   if (order != NULL && order->IsType(OT_IMPLICIT)) {
01940     assert(v->GetNumManualOrders() == 0);
01941     order = NULL;
01942   }
01943 
01944   if (order == NULL) {
01945     v->current_order.Free();
01946     v->dest_tile = 0;
01947     return false;
01948   }
01949 
01950   v->current_order = *order;
01951   return UpdateOrderDest(v, order, conditional_depth + 1, pbs_look_ahead);
01952 }
01953 
01961 bool ProcessOrders(Vehicle *v)
01962 {
01963   switch (v->current_order.GetType()) {
01964     case OT_GOTO_DEPOT:
01965       /* Let a depot order in the orderlist interrupt. */
01966       if (!(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return false;
01967       break;
01968 
01969     case OT_LOADING:
01970       return false;
01971 
01972     case OT_LEAVESTATION:
01973       if (v->type != VEH_AIRCRAFT) return false;
01974       break;
01975 
01976     default: break;
01977   }
01978 
01986   bool may_reverse = v->current_order.IsType(OT_NOTHING);
01987 
01988   /* Check if we've reached a 'via' destination. */
01989   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)) &&
01990       IsTileType(v->tile, MP_STATION) &&
01991       v->current_order.GetDestination() == GetStationIndex(v->tile)) {
01992     v->DeleteUnreachedImplicitOrders();
01993     /* We set the last visited station here because we do not want
01994      * the train to stop at this 'via' station if the next order
01995      * is a no-non-stop order; in that case not setting the last
01996      * visited station will cause the vehicle to still stop. */
01997     v->last_station_visited = v->current_order.GetDestination();
01998     UpdateVehicleTimetable(v, true);
01999     v->IncrementImplicitOrderIndex();
02000   }
02001 
02002   /* Get the current order */
02003   assert(v->cur_implicit_order_index == 0 || v->cur_implicit_order_index < v->GetNumOrders());
02004   v->UpdateRealOrderIndex();
02005 
02006   const Order *order = v->GetOrder(v->cur_real_order_index);
02007   if (order != NULL && order->IsType(OT_IMPLICIT)) {
02008     assert(v->GetNumManualOrders() == 0);
02009     order = NULL;
02010   }
02011 
02012   /* If no order, do nothing. */
02013   if (order == NULL || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
02014     if (v->type == VEH_AIRCRAFT) {
02015       /* Aircraft do something vastly different here, so handle separately */
02016       extern void HandleMissingAircraftOrders(Aircraft *v);
02017       HandleMissingAircraftOrders(Aircraft::From(v));
02018       return false;
02019     }
02020 
02021     v->current_order.Free();
02022     v->dest_tile = 0;
02023     return false;
02024   }
02025 
02026   /* If it is unchanged, keep it. */
02027   if (order->Equals(v->current_order) && (v->type == VEH_AIRCRAFT || v->dest_tile != 0) &&
02028       (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || Station::Get(order->GetDestination())->dock_tile != INVALID_TILE)) {
02029     return false;
02030   }
02031 
02032   /* Otherwise set it, and determine the destination tile. */
02033   v->current_order = *order;
02034 
02035   InvalidateVehicleOrder(v, -2);
02036   switch (v->type) {
02037     default:
02038       NOT_REACHED();
02039 
02040     case VEH_ROAD:
02041     case VEH_TRAIN:
02042       break;
02043 
02044     case VEH_AIRCRAFT:
02045     case VEH_SHIP:
02046       SetWindowClassesDirty(GetWindowClassForVehicleType(v->type));
02047       break;
02048   }
02049 
02050   return UpdateOrderDest(v, order) && may_reverse;
02051 }
02052 
02060 bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
02061 {
02062   bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
02063 
02064   return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
02065       v->last_station_visited != station && // Do stop only when we've not just been there
02066       /* Finally do stop when there is no non-stop flag set for this type of station. */
02067       !(this->GetNonStopType() & (is_dest_station ? ONSF_NO_STOP_AT_DESTINATION_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS));
02068 }
02069 
02070 void InitializeOrders()
02071 {
02072   _order_pool.CleanPool();
02073   _orderlist_pool.CleanPool();
02074 }