00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../../stdafx.h"
00013 #include "ai_order.hpp"
00014 #include "ai_vehicle.hpp"
00015 #include "../ai_instance.hpp"
00016 #include "../../debug.h"
00017 #include "../../vehicle_base.h"
00018 #include "../../roadstop_base.h"
00019 #include "../../depot_base.h"
00020 #include "../../station_base.h"
00021 #include "../../waypoint_base.h"
00022
00028 static OrderType GetOrderTypeByTile(TileIndex t)
00029 {
00030 if (!::IsValidTile(t)) return OT_END;
00031
00032 switch (::GetTileType(t)) {
00033 default: break;
00034 case MP_STATION:
00035 if (IsBuoy(t) || IsRailWaypoint(t)) return OT_GOTO_WAYPOINT;
00036 if (IsHangar(t)) return OT_GOTO_DEPOT;
00037 return OT_GOTO_STATION;
00038
00039 case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
00040 case MP_ROAD: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
00041 case MP_RAILWAY:
00042 if (IsRailDepot(t)) return OT_GOTO_DEPOT;
00043 break;
00044 }
00045
00046 return OT_END;
00047 }
00048
00049 bool AIOrder::IsValidVehicleOrder(VehicleID vehicle_id, OrderPosition order_position)
00050 {
00051 return AIVehicle::IsValidVehicle(vehicle_id) && order_position >= 0 && (order_position < ::Vehicle::Get(vehicle_id)->GetNumManualOrders() || order_position == ORDER_CURRENT);
00052 }
00053
00059 static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition order_position)
00060 {
00061 const Vehicle *v = ::Vehicle::Get(vehicle_id);
00062 if (order_position == AIOrder::ORDER_CURRENT) {
00063 const Order *order = &v->current_order;
00064 if (order->GetType() == OT_GOTO_DEPOT && !(order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return order;
00065 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00066 if (order_position == AIOrder::ORDER_INVALID) return NULL;
00067 }
00068 const Order *order = v->orders.list->GetFirstOrder();
00069 while (order->GetType() == OT_AUTOMATIC) order = order->next;
00070 while (order_position > 0) {
00071 order_position = (AIOrder::OrderPosition)(order_position - 1);
00072 order = order->next;
00073 while (order->GetType() == OT_AUTOMATIC) order = order->next;
00074 }
00075 return order;
00076 }
00077
00078 bool AIOrder::IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position)
00079 {
00080 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00081
00082 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00083 return order != NULL && order->GetType() == OT_GOTO_STATION;
00084 }
00085
00086 bool AIOrder::IsGotoDepotOrder(VehicleID vehicle_id, OrderPosition order_position)
00087 {
00088 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00089
00090 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00091 return order != NULL && order->GetType() == OT_GOTO_DEPOT;
00092 }
00093
00094 bool AIOrder::IsGotoWaypointOrder(VehicleID vehicle_id, OrderPosition order_position)
00095 {
00096 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00097
00098 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00099 return order != NULL && order->GetType() == OT_GOTO_WAYPOINT;
00100 }
00101
00102 bool AIOrder::IsConditionalOrder(VehicleID vehicle_id, OrderPosition order_position)
00103 {
00104 if (order_position == ORDER_CURRENT) return false;
00105 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00106
00107 const Order *order = Vehicle::Get(vehicle_id)->GetOrder(order_position);
00108 return order->GetType() == OT_CONDITIONAL;
00109 }
00110
00111 bool AIOrder::IsVoidOrder(VehicleID vehicle_id, OrderPosition order_position)
00112 {
00113 if (order_position == ORDER_CURRENT) return false;
00114 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00115
00116 const Order *order = Vehicle::Get(vehicle_id)->GetOrder(order_position);
00117 return order->GetType() == OT_DUMMY;
00118 }
00119
00120 bool AIOrder::IsCurrentOrderPartOfOrderList(VehicleID vehicle_id)
00121 {
00122 if (AIVehicle::IsValidVehicle(vehicle_id)) return false;
00123 if (GetOrderCount(vehicle_id) == 0) return false;
00124
00125 const Order *order = &::Vehicle::Get(vehicle_id)->current_order;
00126 if (order->GetType() != OT_GOTO_DEPOT) return true;
00127 return (order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0;
00128 }
00129
00130 AIOrder::OrderPosition AIOrder::ResolveOrderPosition(VehicleID vehicle_id, OrderPosition order_position)
00131 {
00132 if (!AIVehicle::IsValidVehicle(vehicle_id)) return ORDER_INVALID;
00133
00134 if (order_position == ORDER_CURRENT) {
00135 int cur_order_pos = ::Vehicle::Get(vehicle_id)->cur_real_order_index;
00136 const Order *order = ::Vehicle::Get(vehicle_id)->GetOrder(0);
00137 if (order == NULL) return ORDER_INVALID;
00138 int num_automatic_orders = 0;
00139 for (int i = 0; i < cur_order_pos; i++) {
00140 if (order->GetType() == OT_AUTOMATIC) num_automatic_orders++;
00141 order = order->next;
00142 }
00143 return (AIOrder::OrderPosition)(cur_order_pos - num_automatic_orders);
00144 }
00145 return (order_position >= 0 && order_position < ::Vehicle::Get(vehicle_id)->GetNumManualOrders()) ? order_position : ORDER_INVALID;
00146 }
00147
00148
00149 bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags)
00150 {
00151 OrderType ot = (order_flags & AIOF_GOTO_NEAREST_DEPOT) ? OT_GOTO_DEPOT : ::GetOrderTypeByTile(destination);
00152 switch (ot) {
00153 case OT_GOTO_STATION:
00154 return (order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_UNLOAD_FLAGS | AIOF_LOAD_FLAGS)) == 0 &&
00155
00156 ((order_flags & AIOF_TRANSFER) == 0 || (order_flags & AIOF_UNLOAD) == 0) &&
00157 ((order_flags & AIOF_TRANSFER) == 0 || (order_flags & AIOF_NO_UNLOAD) == 0) &&
00158 ((order_flags & AIOF_UNLOAD) == 0 || (order_flags & AIOF_NO_UNLOAD) == 0) &&
00159 ((order_flags & AIOF_UNLOAD) == 0 || (order_flags & AIOF_NO_UNLOAD) == 0) &&
00160 ((order_flags & AIOF_NO_UNLOAD) == 0 || (order_flags & AIOF_NO_LOAD) == 0) &&
00161 ((order_flags & AIOF_FULL_LOAD_ANY) == 0 || (order_flags & AIOF_NO_LOAD) == 0);
00162
00163 case OT_GOTO_DEPOT:
00164 return (order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_DEPOT_FLAGS)) == 0 &&
00165 ((order_flags & AIOF_SERVICE_IF_NEEDED) == 0 || (order_flags & AIOF_STOP_IN_DEPOT) == 0);
00166
00167 case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
00168 default: return false;
00169 }
00170 }
00171
00172 bool AIOrder::IsValidConditionalOrder(OrderCondition condition, CompareFunction compare)
00173 {
00174 switch (condition) {
00175 case OC_LOAD_PERCENTAGE:
00176 case OC_RELIABILITY:
00177 case OC_MAX_SPEED:
00178 case OC_AGE:
00179 return compare >= CF_EQUALS && compare <= CF_MORE_EQUALS;
00180
00181 case OC_REQUIRES_SERVICE:
00182 return compare == CF_IS_TRUE || compare == CF_IS_FALSE;
00183
00184 case OC_UNCONDITIONALLY:
00185 return true;
00186
00187 default: return false;
00188 }
00189 }
00190
00191 int32 AIOrder::GetOrderCount(VehicleID vehicle_id)
00192 {
00193 return AIVehicle::IsValidVehicle(vehicle_id) ? ::Vehicle::Get(vehicle_id)->GetNumOrders() : -1;
00194 }
00195
00196 TileIndex AIOrder::GetOrderDestination(VehicleID vehicle_id, OrderPosition order_position)
00197 {
00198 if (!IsValidVehicleOrder(vehicle_id, order_position)) return INVALID_TILE;
00199
00200 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00201 if (order == NULL || order->GetType() == OT_CONDITIONAL) return INVALID_TILE;
00202 const Vehicle *v = ::Vehicle::Get(vehicle_id);
00203
00204 switch (order->GetType()) {
00205 case OT_GOTO_DEPOT: {
00206
00207 if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) return INVALID_TILE;
00208
00209 if (v->type != VEH_AIRCRAFT) return ::Depot::Get(order->GetDestination())->xy;
00210
00211 const Station *st = ::Station::Get(order->GetDestination());
00212 if (!st->airport.HasHangar()) return INVALID_TILE;
00213 return st->airport.GetHangarTile(0);
00214 }
00215
00216 case OT_GOTO_STATION: {
00217 const Station *st = ::Station::Get(order->GetDestination());
00218 if (st->train_station.tile != INVALID_TILE) {
00219 TILE_AREA_LOOP(t, st->train_station) {
00220 if (st->TileBelongsToRailStation(t)) return t;
00221 }
00222 } else if (st->dock_tile != INVALID_TILE) {
00223 return st->dock_tile;
00224 } else if (st->bus_stops != NULL) {
00225 return st->bus_stops->xy;
00226 } else if (st->truck_stops != NULL) {
00227 return st->truck_stops->xy;
00228 } else if (st->airport.tile != INVALID_TILE) {
00229 TILE_AREA_LOOP(tile, st->airport) {
00230 if (st->TileBelongsToAirport(tile) && !::IsHangar(tile)) return tile;
00231 }
00232 }
00233 return INVALID_TILE;
00234 }
00235
00236 case OT_GOTO_WAYPOINT: {
00237 const Waypoint *wp = ::Waypoint::Get(order->GetDestination());
00238 if (wp->train_station.tile != INVALID_TILE) {
00239 TILE_AREA_LOOP(t, wp->train_station) {
00240 if (wp->TileBelongsToRailStation(t)) return t;
00241 }
00242 }
00243
00244 return wp->xy;
00245 }
00246 default: return INVALID_TILE;
00247 }
00248 }
00249
00250 AIOrder::AIOrderFlags AIOrder::GetOrderFlags(VehicleID vehicle_id, OrderPosition order_position)
00251 {
00252 if (!IsValidVehicleOrder(vehicle_id, order_position)) return AIOF_INVALID;
00253
00254 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00255 if (order == NULL || order->GetType() == OT_CONDITIONAL || order->GetType() == OT_DUMMY) return AIOF_INVALID;
00256
00257 AIOrderFlags order_flags = AIOF_NONE;
00258 order_flags |= (AIOrderFlags)order->GetNonStopType();
00259 switch (order->GetType()) {
00260 case OT_GOTO_DEPOT:
00261 if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
00262 if (order->GetDepotActionType() & ODATFB_HALT) order_flags |= AIOF_STOP_IN_DEPOT;
00263 if (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) order_flags |= AIOF_GOTO_NEAREST_DEPOT;
00264 break;
00265
00266 case OT_GOTO_STATION:
00267 order_flags |= (AIOrderFlags)(order->GetLoadType() << 5);
00268 order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2);
00269 break;
00270
00271 default: break;
00272 }
00273
00274 return order_flags;
00275 }
00276
00277 AIOrder::OrderPosition AIOrder::GetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position)
00278 {
00279 if (!IsValidVehicleOrder(vehicle_id, order_position)) return ORDER_INVALID;
00280 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return ORDER_INVALID;
00281
00282 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00283 return (OrderPosition)order->GetConditionSkipToOrder();
00284 }
00285
00286 AIOrder::OrderCondition AIOrder::GetOrderCondition(VehicleID vehicle_id, OrderPosition order_position)
00287 {
00288 if (!IsValidVehicleOrder(vehicle_id, order_position)) return OC_INVALID;
00289 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return OC_INVALID;
00290
00291 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00292 return (OrderCondition)order->GetConditionVariable();
00293 }
00294
00295 AIOrder::CompareFunction AIOrder::GetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position)
00296 {
00297 if (!IsValidVehicleOrder(vehicle_id, order_position)) return CF_INVALID;
00298 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return CF_INVALID;
00299
00300 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00301 return (CompareFunction)order->GetConditionComparator();
00302 }
00303
00304 int32 AIOrder::GetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position)
00305 {
00306 if (!IsValidVehicleOrder(vehicle_id, order_position)) return -1;
00307 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return -1;
00308
00309 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00310 int32 value = order->GetConditionValue();
00311 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = value * 16 / 10;
00312 return value;
00313 }
00314
00315 AIOrder::StopLocation AIOrder::GetStopLocation(VehicleID vehicle_id, OrderPosition order_position)
00316 {
00317 if (!IsValidVehicleOrder(vehicle_id, order_position)) return STOPLOCATION_INVALID;
00318 if (AIVehicle::GetVehicleType(vehicle_id) != AIVehicle::VT_RAIL) return STOPLOCATION_INVALID;
00319 if (!IsGotoStationOrder(vehicle_id, order_position)) return STOPLOCATION_INVALID;
00320
00321 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00322 return (AIOrder::StopLocation)order->GetStopLocation();
00323 }
00324
00325 bool AIOrder::SetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00326 {
00327 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00328 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00329 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to) && jump_to != ORDER_CURRENT);
00330
00331 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_DESTINATION | (jump_to << 4), CMD_MODIFY_ORDER);
00332 }
00333
00334 bool AIOrder::SetOrderCondition(VehicleID vehicle_id, OrderPosition order_position, OrderCondition condition)
00335 {
00336 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00337 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00338 EnforcePrecondition(false, condition >= OC_LOAD_PERCENTAGE && condition <= OC_UNCONDITIONALLY);
00339
00340 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_VARIABLE | (condition << 4), CMD_MODIFY_ORDER);
00341 }
00342
00343 bool AIOrder::SetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position, CompareFunction compare)
00344 {
00345 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00346 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00347 EnforcePrecondition(false, compare >= CF_EQUALS && compare <= CF_IS_FALSE);
00348
00349 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_COMPARATOR | (compare << 4), CMD_MODIFY_ORDER);
00350 }
00351
00352 bool AIOrder::SetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position, int32 value)
00353 {
00354 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00355 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00356 EnforcePrecondition(false, value >= 0 && value < 2048);
00357 if (GetOrderCondition(vehicle_id, order_position) == OC_MAX_SPEED) value = value * 10 / 16;
00358
00359 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER);
00360 }
00361
00362 bool AIOrder::SetStopLocation(VehicleID vehicle_id, OrderPosition order_position, StopLocation stop_location)
00363 {
00364 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00365 EnforcePrecondition(false, AIVehicle::GetVehicleType(vehicle_id) == AIVehicle::VT_RAIL);
00366 EnforcePrecondition(false, IsGotoStationOrder(vehicle_id, order_position));
00367 EnforcePrecondition(false, stop_location >= STOPLOCATION_NEAR && stop_location <= STOPLOCATION_FAR);
00368
00369 uint32 p1 = vehicle_id | (order_position << 20);
00370 uint32 p2 = MOF_STOP_LOCATION | (stop_location << 4);
00371 return AIObject::DoCommand(0, p1, p2, CMD_MODIFY_ORDER);
00372 }
00373
00374 bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags)
00375 {
00376 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00377 EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00378
00379 return InsertOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumOrders(), destination, order_flags);
00380 }
00381
00382 bool AIOrder::AppendConditionalOrder(VehicleID vehicle_id, OrderPosition jump_to)
00383 {
00384 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00385 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00386
00387 return InsertConditionalOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumOrders(), jump_to);
00388 }
00389
00390 bool AIOrder::InsertOrder(VehicleID vehicle_id, OrderPosition order_position, TileIndex destination, AIOrder::AIOrderFlags order_flags)
00391 {
00392
00393 if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00394
00395 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00396 EnforcePrecondition(false, order_position >= 0 && order_position <= ::Vehicle::Get(vehicle_id)->GetNumOrders());
00397 EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00398
00399 Order order;
00400 OrderType ot = (order_flags & AIOF_GOTO_NEAREST_DEPOT) ? OT_GOTO_DEPOT : ::GetOrderTypeByTile(destination);
00401 switch (ot) {
00402 case OT_GOTO_DEPOT: {
00403 OrderDepotTypeFlags odtf = (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0));
00404 OrderDepotActionFlags odaf = (OrderDepotActionFlags)(ODATF_SERVICE_ONLY | ((order_flags & AIOF_STOP_IN_DEPOT) ? ODATFB_HALT : 0));
00405 if (order_flags & AIOF_GOTO_NEAREST_DEPOT) odaf |= ODATFB_NEAREST_DEPOT;
00406 OrderNonStopFlags onsf = (OrderNonStopFlags)((order_flags & AIOF_NON_STOP_INTERMEDIATE) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00407 if (order_flags & AIOF_GOTO_NEAREST_DEPOT) {
00408 order.MakeGoToDepot(0, odtf, onsf, odaf);
00409 } else {
00410
00411
00412 if (::Vehicle::Get(vehicle_id)->type == VEH_AIRCRAFT) {
00413 if (!::IsTileType(destination, MP_STATION)) return false;
00414 order.MakeGoToDepot(::GetStationIndex(destination), odtf, onsf, odaf);
00415 } else {
00416 if (::IsTileType(destination, MP_STATION)) return false;
00417 order.MakeGoToDepot(::GetDepotIndex(destination), odtf, onsf, odaf);
00418 }
00419 }
00420 break;
00421 }
00422
00423 case OT_GOTO_STATION:
00424 order.MakeGoToStation(::GetStationIndex(destination));
00425 order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
00426 order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
00427 order.SetStopLocation(OSL_PLATFORM_FAR_END);
00428 break;
00429
00430 case OT_GOTO_WAYPOINT:
00431 order.MakeGoToWaypoint(::GetStationIndex(destination));
00432 break;
00433
00434 default:
00435 return false;
00436 }
00437
00438 order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2));
00439
00440 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), order.Pack(), CMD_INSERT_ORDER);
00441 }
00442
00443 bool AIOrder::InsertConditionalOrder(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00444 {
00445
00446 if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00447
00448 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00449 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00450
00451 Order order;
00452 order.MakeConditional(jump_to);
00453
00454 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), order.Pack(), CMD_INSERT_ORDER);
00455 }
00456
00457 bool AIOrder::RemoveOrder(VehicleID vehicle_id, OrderPosition order_position)
00458 {
00459 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00460
00461 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00462
00463 return AIObject::DoCommand(0, vehicle_id, order_position, CMD_DELETE_ORDER);
00464 }
00465
00466 bool AIOrder::SkipToOrder(VehicleID vehicle_id, OrderPosition next_order)
00467 {
00468 next_order = AIOrder::ResolveOrderPosition(vehicle_id, next_order);
00469
00470 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, next_order));
00471
00472 return AIObject::DoCommand(0, vehicle_id, next_order, CMD_SKIP_TO_ORDER);
00473 }
00474
00483 static void _DoCommandReturnSetOrderFlags(class AIInstance *instance)
00484 {
00485 AIObject::SetLastCommandRes(AIOrder::_SetOrderFlags());
00486 AIInstance::DoCommandReturn(instance);
00487 }
00488
00489 bool AIOrder::_SetOrderFlags()
00490 {
00491
00492 int retry = AIObject::GetCallbackVariable(3) - 1;
00493 if (retry < 0) {
00494 DEBUG(ai, 0, "Possible infinite loop in SetOrderFlags() detected");
00495 return false;
00496 }
00497 AIObject::SetCallbackVariable(3, retry);
00498
00499 VehicleID vehicle_id = (VehicleID)AIObject::GetCallbackVariable(0);
00500 OrderPosition order_position = (OrderPosition)AIObject::GetCallbackVariable(1);
00501 AIOrderFlags order_flags = (AIOrderFlags)AIObject::GetCallbackVariable(2);
00502
00503 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00504
00505 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00506 EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_position), order_flags));
00507
00508 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00509
00510 AIOrderFlags current = GetOrderFlags(vehicle_id, order_position);
00511
00512 if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) {
00513 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00514 }
00515
00516 switch (order->GetType()) {
00517 case OT_GOTO_DEPOT:
00518 if ((current & AIOF_DEPOT_FLAGS) != (order_flags & AIOF_DEPOT_FLAGS)) {
00519 uint data = DA_ALWAYS_GO;
00520 if (order_flags & AIOF_SERVICE_IF_NEEDED) data = DA_SERVICE;
00521 if (order_flags & AIOF_STOP_IN_DEPOT) data = DA_STOP;
00522 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00523 }
00524 break;
00525
00526 case OT_GOTO_STATION:
00527 if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) {
00528 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00529 }
00530 if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) {
00531 return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00532 }
00533 break;
00534
00535 default: break;
00536 }
00537
00538 assert(GetOrderFlags(vehicle_id, order_position) == order_flags);
00539
00540 return true;
00541 }
00542
00543 bool AIOrder::SetOrderFlags(VehicleID vehicle_id, OrderPosition order_position, AIOrder::AIOrderFlags order_flags)
00544 {
00545 AIObject::SetCallbackVariable(0, vehicle_id);
00546 AIObject::SetCallbackVariable(1, order_position);
00547 AIObject::SetCallbackVariable(2, order_flags);
00548
00549
00550 AIObject::SetCallbackVariable(3, 8);
00551 return AIOrder::_SetOrderFlags();
00552 }
00553
00554 bool AIOrder::MoveOrder(VehicleID vehicle_id, OrderPosition order_position_move, OrderPosition order_position_target)
00555 {
00556 order_position_move = AIOrder::ResolveOrderPosition(vehicle_id, order_position_move);
00557 order_position_target = AIOrder::ResolveOrderPosition(vehicle_id, order_position_target);
00558
00559 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_move));
00560 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_target));
00561
00562 return AIObject::DoCommand(0, vehicle_id, order_position_move | (order_position_target << 16), CMD_MOVE_ORDER);
00563 }
00564
00565 bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00566 {
00567 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00568 EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00569
00570 return AIObject::DoCommand(0, vehicle_id | CO_COPY << 30, main_vehicle_id, CMD_CLONE_ORDER);
00571 }
00572
00573 bool AIOrder::ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00574 {
00575 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00576 EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00577
00578 return AIObject::DoCommand(0, vehicle_id | CO_SHARE << 30, main_vehicle_id, CMD_CLONE_ORDER);
00579 }
00580
00581 bool AIOrder::UnshareOrders(VehicleID vehicle_id)
00582 {
00583 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00584
00585 return AIObject::DoCommand(0, vehicle_id | CO_UNSHARE << 30, 0, CMD_CLONE_ORDER);
00586 }