00001
00002
00005 #include "ai_order.hpp"
00006 #include "ai_vehicle.hpp"
00007 #include "ai_log.hpp"
00008 #include "../ai_instance.hpp"
00009 #include "../../debug.h"
00010 #include "../../vehicle_base.h"
00011 #include "../../depot_base.h"
00012 #include "../../station_map.h"
00013 #include "../../waypoint.h"
00014
00020 static OrderType GetOrderTypeByTile(TileIndex t)
00021 {
00022 if (!::IsValidTile(t)) return OT_END;
00023
00024 switch (::GetTileType(t)) {
00025 default: break;
00026 case MP_STATION:
00027 if (IsHangar(t)) return OT_GOTO_DEPOT;
00028 return OT_GOTO_STATION;
00029 break;
00030 case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
00031 case MP_ROAD: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
00032 case MP_RAILWAY:
00033 switch (::GetRailTileType(t)) {
00034 case RAIL_TILE_DEPOT: return OT_GOTO_DEPOT;
00035 case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT;
00036 default: break;
00037 }
00038 break;
00039 }
00040
00041 return OT_END;
00042 }
00043
00044 bool AIOrder::IsValidVehicleOrder(VehicleID vehicle_id, OrderPosition order_position)
00045 {
00046 return AIVehicle::IsValidVehicle(vehicle_id) && order_position >= 0 && (order_position < ::GetVehicle(vehicle_id)->GetNumOrders() || order_position == ORDER_CURRENT);
00047 }
00048
00054 static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition order_position)
00055 {
00056 const Vehicle *v = ::GetVehicle(vehicle_id);
00057 if (order_position == AIOrder::ORDER_CURRENT) {
00058 const Order *order = &v->current_order;
00059 if (order->GetType() == OT_GOTO_DEPOT && !(order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return order;
00060 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00061 if (order_position == AIOrder::ORDER_INVALID) return NULL;
00062 }
00063 return ::GetVehicleOrder(v, order_position);
00064 }
00065
00066 bool AIOrder::IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position)
00067 {
00068 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00069
00070 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00071 return order != NULL && order->GetType() == OT_GOTO_STATION;
00072 }
00073
00074 bool AIOrder::IsGotoDepotOrder(VehicleID vehicle_id, OrderPosition order_position)
00075 {
00076 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00077
00078 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00079 return order != NULL && order->GetType() == OT_GOTO_DEPOT;
00080 }
00081
00082 bool AIOrder::IsGotoWaypointOrder(VehicleID vehicle_id, OrderPosition order_position)
00083 {
00084 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00085
00086 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00087 return order != NULL && order->GetType() == OT_GOTO_WAYPOINT;
00088 }
00089
00090 bool AIOrder::IsConditionalOrder(VehicleID vehicle_id, OrderPosition order_position)
00091 {
00092 if (order_position == ORDER_CURRENT) return false;
00093 if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
00094
00095 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00096 return order->GetType() == OT_CONDITIONAL;
00097 }
00098
00099 bool AIOrder::IsCurrentOrderPartOfOrderList(VehicleID vehicle_id)
00100 {
00101 if (AIVehicle::IsValidVehicle(vehicle_id)) return false;
00102 if (GetOrderCount(vehicle_id) == 0) return false;
00103
00104 const Order *order = &::GetVehicle(vehicle_id)->current_order;
00105 if (order->GetType() != OT_GOTO_DEPOT) return true;
00106 return (order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0;
00107 }
00108
00109 AIOrder::OrderPosition AIOrder::ResolveOrderPosition(VehicleID vehicle_id, OrderPosition order_position)
00110 {
00111 if (!AIVehicle::IsValidVehicle(vehicle_id)) return ORDER_INVALID;
00112
00113 if (order_position == ORDER_CURRENT) return (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->cur_order_index;
00114 return (order_position >= 0 && order_position < ::GetVehicle(vehicle_id)->GetNumOrders()) ? order_position : ORDER_INVALID;
00115 }
00116
00117
00118 bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags)
00119 {
00120 switch (::GetOrderTypeByTile(destination)) {
00121 case OT_GOTO_STATION:
00122 return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_UNLOAD_FLAGS | AIOF_LOAD_FLAGS)) == 0) &&
00123
00124 (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_UNLOAD) == 0)) &&
00125 (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00126 (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00127 (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) &&
00128 (((order_flags & AIOF_NO_UNLOAD) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)) &&
00129 (((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD) == 0));
00130
00131 case OT_GOTO_DEPOT:
00132 return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_DEPOT_FLAGS)) == 0) &&
00133 (((order_flags & AIOF_SERVICE_IF_NEEDED) == 0) || ((order_flags & AIOF_STOP_IN_DEPOT) == 0));
00134
00135 case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0;
00136 default: return false;
00137 }
00138 }
00139
00140 bool AIOrder::IsValidConditionalOrder(OrderCondition condition, CompareFunction compare)
00141 {
00142 switch (condition) {
00143 case OC_LOAD_PERCENTAGE:
00144 case OC_RELIABILITY:
00145 case OC_MAX_SPEED:
00146 case OC_AGE:
00147 return compare >= CF_EQUALS && compare <= CF_MORE_EQUALS;
00148
00149 case OC_REQUIRES_SERVICE:
00150 return compare == CF_IS_TRUE || compare == CF_IS_FALSE;
00151
00152 case OC_UNCONDITIONALLY:
00153 return true;
00154
00155 default: return false;
00156 }
00157 }
00158
00159 int32 AIOrder::GetOrderCount(VehicleID vehicle_id)
00160 {
00161 return AIVehicle::IsValidVehicle(vehicle_id) ? ::GetVehicle(vehicle_id)->GetNumOrders() : -1;
00162 }
00163
00164 TileIndex AIOrder::GetOrderDestination(VehicleID vehicle_id, OrderPosition order_position)
00165 {
00166 if (!IsValidVehicleOrder(vehicle_id, order_position)) return INVALID_TILE;
00167
00168 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00169 if (order == NULL || order->GetType() == OT_CONDITIONAL) return INVALID_TILE;
00170 const Vehicle *v = ::GetVehicle(vehicle_id);
00171
00172 switch (order->GetType()) {
00173 case OT_GOTO_DEPOT: {
00174 if (v->type != VEH_AIRCRAFT) return ::GetDepot(order->GetDestination())->xy;
00175
00176 const Station *st = ::GetStation(order->GetDestination());
00177 const AirportFTAClass *airport = st->Airport();
00178 if (airport == NULL || airport->nof_depots == 0) return INVALID_TILE;
00179 return st->airport_tile + ::ToTileIndexDiff(st->Airport()->airport_depots[0]);
00180 }
00181
00182 case OT_GOTO_STATION: {
00183 const Station *st = ::GetStation(order->GetDestination());
00184 if (st->train_tile != INVALID_TILE) {
00185 for (uint i = 0; i < st->trainst_w; i++) {
00186 TileIndex t = st->train_tile + TileDiffXY(i, 0);
00187 if (st->TileBelongsToRailStation(t)) return t;
00188 }
00189 } else if (st->dock_tile != INVALID_TILE) {
00190 return st->dock_tile;
00191 } else if (st->bus_stops != NULL) {
00192 return st->bus_stops->xy;
00193 } else if (st->truck_stops != NULL) {
00194 return st->truck_stops->xy;
00195 } else if (st->airport_tile != INVALID_TILE) {
00196 const AirportFTAClass *fta = st->Airport();
00197 BEGIN_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile) {
00198 if (!::IsHangar(tile)) return tile;
00199 } END_TILE_LOOP(tile, fta->size_x, fta->size_y, st->airport_tile)
00200 }
00201 return INVALID_TILE;
00202 }
00203 case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->GetDestination())->xy;
00204 default: return INVALID_TILE;
00205 }
00206 }
00207
00208 AIOrder::AIOrderFlags AIOrder::GetOrderFlags(VehicleID vehicle_id, OrderPosition order_position)
00209 {
00210 if (!IsValidVehicleOrder(vehicle_id, order_position)) return AIOF_INVALID;
00211
00212 const Order *order = ::ResolveOrder(vehicle_id, order_position);
00213 if (order == NULL || order->GetType() == OT_CONDITIONAL) return AIOF_INVALID;
00214
00215 AIOrderFlags order_flags = AIOF_NONE;
00216 order_flags |= (AIOrderFlags)order->GetNonStopType();
00217 switch (order->GetType()) {
00218 case OT_GOTO_DEPOT:
00219 if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED;
00220 if (order->GetDepotActionType() & ODATFB_HALT) order_flags |= AIOF_STOP_IN_DEPOT;
00221 break;
00222
00223 case OT_GOTO_STATION:
00224 order_flags |= (AIOrderFlags)(order->GetLoadType() << 5);
00225 order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2);
00226 break;
00227
00228 default: break;
00229 }
00230
00231 return order_flags;
00232 }
00233
00234 AIOrder::OrderPosition AIOrder::GetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position)
00235 {
00236 if (!IsValidVehicleOrder(vehicle_id, order_position)) return ORDER_INVALID;
00237 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return ORDER_INVALID;
00238
00239 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00240 return (OrderPosition)order->GetConditionSkipToOrder();
00241 }
00242
00243 AIOrder::OrderCondition AIOrder::GetOrderCondition(VehicleID vehicle_id, OrderPosition order_position)
00244 {
00245 if (!IsValidVehicleOrder(vehicle_id, order_position)) return OC_INVALID;
00246 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return OC_INVALID;
00247
00248 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00249 return (OrderCondition)order->GetConditionVariable();
00250 }
00251
00252 AIOrder::CompareFunction AIOrder::GetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position)
00253 {
00254 if (!IsValidVehicleOrder(vehicle_id, order_position)) return CF_INVALID;
00255 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return CF_INVALID;
00256
00257 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00258 return (CompareFunction)order->GetConditionComparator();
00259 }
00260
00261 int32 AIOrder::GetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position)
00262 {
00263 if (!IsValidVehicleOrder(vehicle_id, order_position)) return -1;
00264 if (order_position == ORDER_CURRENT || !IsConditionalOrder(vehicle_id, order_position)) return -1;
00265
00266 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00267 int32 value = order->GetConditionValue();
00268 if (order->GetConditionVariable() == OCV_MAX_SPEED) value = value * 16 / 10;
00269 return value;
00270 }
00271
00272 bool AIOrder::SetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00273 {
00274 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00275 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00276 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to) && jump_to != ORDER_CURRENT);
00277
00278 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_DESTINATION | (jump_to << 4), CMD_MODIFY_ORDER);
00279 }
00280
00281 bool AIOrder::SetOrderCondition(VehicleID vehicle_id, OrderPosition order_position, OrderCondition condition)
00282 {
00283 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00284 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00285 EnforcePrecondition(false, condition >= OC_LOAD_PERCENTAGE && condition <= OC_UNCONDITIONALLY);
00286
00287 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_VARIABLE | (condition << 4), CMD_MODIFY_ORDER);
00288 }
00289
00290 bool AIOrder::SetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position, CompareFunction compare)
00291 {
00292 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00293 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00294 EnforcePrecondition(false, compare >= CF_EQUALS && compare <= CF_IS_FALSE);
00295
00296 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_COMPARATOR | (compare << 4), CMD_MODIFY_ORDER);
00297 }
00298
00299 bool AIOrder::SetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position, int32 value)
00300 {
00301 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00302 EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position));
00303 EnforcePrecondition(false, value >= 0 && value < 2048);
00304 if (GetOrderCondition(vehicle_id, order_position) == OC_MAX_SPEED) value = value * 10 / 16;
00305
00306 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER);
00307 }
00308
00309 bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags)
00310 {
00311 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00312 EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00313
00314 return InsertOrder(vehicle_id, (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->GetNumOrders(), destination, order_flags);
00315 }
00316
00317 bool AIOrder::AppendConditionalOrder(VehicleID vehicle_id, OrderPosition jump_to)
00318 {
00319 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00320 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00321
00322 return InsertConditionalOrder(vehicle_id, (AIOrder::OrderPosition)::GetVehicle(vehicle_id)->GetNumOrders(), jump_to);
00323 }
00324
00325 bool AIOrder::InsertOrder(VehicleID vehicle_id, OrderPosition order_position, TileIndex destination, AIOrder::AIOrderFlags order_flags)
00326 {
00327
00328 if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00329
00330 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00331 EnforcePrecondition(false, order_position >= 0 && order_position <= ::GetVehicle(vehicle_id)->GetNumOrders());
00332 EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags));
00333
00334 Order order;
00335 switch (::GetOrderTypeByTile(destination)) {
00336 case OT_GOTO_DEPOT: {
00337 OrderDepotTypeFlags odtf = (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0));
00338 OrderDepotActionFlags odaf = (OrderDepotActionFlags)(ODATF_SERVICE_ONLY | ((order_flags & AIOF_STOP_IN_DEPOT) ? ODATFB_HALT : 0));
00339 OrderNonStopFlags onsf = (OrderNonStopFlags)((order_flags & AIOF_NON_STOP_INTERMEDIATE) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
00340
00341
00342 if (::GetVehicle(vehicle_id)->type == VEH_AIRCRAFT) {
00343 if (!::IsTileType(destination, MP_STATION)) return false;
00344 order.MakeGoToDepot(::GetStationIndex(destination), odtf, onsf, odaf);
00345 } else {
00346 if (::IsTileType(destination, MP_STATION)) return false;
00347 order.MakeGoToDepot(::GetDepotByTile(destination)->index, odtf, onsf, odaf);
00348 }
00349 break;
00350 }
00351
00352 case OT_GOTO_STATION:
00353 order.MakeGoToStation(::GetStationIndex(destination));
00354 order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3));
00355 order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3));
00356 break;
00357
00358 case OT_GOTO_WAYPOINT:
00359 order.MakeGoToWaypoint(::GetWaypointIndex(destination));
00360 break;
00361
00362 default:
00363 return false;
00364 }
00365
00366 order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2));
00367
00368 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), order.Pack(), CMD_INSERT_ORDER);
00369 }
00370
00371 bool AIOrder::InsertConditionalOrder(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
00372 {
00373
00374 if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00375
00376 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00377 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to));
00378
00379 Order order;
00380 order.MakeConditional(jump_to);
00381
00382 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), order.Pack(), CMD_INSERT_ORDER);
00383 }
00384
00385 bool AIOrder::RemoveOrder(VehicleID vehicle_id, OrderPosition order_position)
00386 {
00387 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00388
00389 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00390
00391 return AIObject::DoCommand(0, vehicle_id, order_position, CMD_DELETE_ORDER);
00392 }
00393
00394 bool AIOrder::SkipToOrder(VehicleID vehicle_id, OrderPosition next_order)
00395 {
00396 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, next_order));
00397
00398 return AIObject::DoCommand(0, vehicle_id, next_order, CMD_SKIP_TO_ORDER);
00399 }
00400
00409 static void _DoCommandReturnSetOrderFlags(class AIInstance *instance)
00410 {
00411 AIObject::SetLastCommandRes(AIOrder::_SetOrderFlags());
00412 AIInstance::DoCommandReturn(instance);
00413 }
00414
00415 bool AIOrder::_SetOrderFlags()
00416 {
00417
00418 int retry = AIObject::GetCallbackVariable(3) - 1;
00419 if (retry < 0) {
00420 DEBUG(ai, 0, "Possible infinite loop in SetOrderFlags() detected");
00421 return false;
00422 }
00423 AIObject::SetCallbackVariable(3, retry);
00424
00425 VehicleID vehicle_id = (VehicleID)AIObject::GetCallbackVariable(0);
00426 OrderPosition order_position = (OrderPosition)AIObject::GetCallbackVariable(1);
00427 AIOrderFlags order_flags = (AIOrderFlags)AIObject::GetCallbackVariable(2);
00428
00429 order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position);
00430
00431 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
00432 EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_position), order_flags));
00433
00434 const Order *order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position);
00435
00436 AIOrderFlags current = GetOrderFlags(vehicle_id, order_position);
00437
00438 if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) {
00439 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00440 }
00441
00442 switch (order->GetType()) {
00443 case OT_GOTO_DEPOT:
00444 if ((current & AIOF_DEPOT_FLAGS) != (order_flags & AIOF_DEPOT_FLAGS)) {
00445 uint data = DA_ALWAYS_GO;
00446 if (order_flags & AIOF_SERVICE_IF_NEEDED) data = DA_SERVICE;
00447 if (order_flags & AIOF_STOP_IN_DEPOT) data = DA_STOP;
00448 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00449 }
00450 break;
00451
00452 case OT_GOTO_STATION:
00453 if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) {
00454 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00455 }
00456 if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) {
00457 return AIObject::DoCommand(0, vehicle_id | (order_position << 16), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &_DoCommandReturnSetOrderFlags);
00458 }
00459 break;
00460
00461 default: break;
00462 }
00463
00464 assert(GetOrderFlags(vehicle_id, order_position) == order_flags);
00465
00466 return true;
00467 }
00468
00469 bool AIOrder::SetOrderFlags(VehicleID vehicle_id, OrderPosition order_position, AIOrder::AIOrderFlags order_flags)
00470 {
00471 AIObject::SetCallbackVariable(0, vehicle_id);
00472 AIObject::SetCallbackVariable(1, order_position);
00473 AIObject::SetCallbackVariable(2, order_flags);
00474
00475
00476 AIObject::SetCallbackVariable(3, 8);
00477 return AIOrder::_SetOrderFlags();
00478 }
00479
00480 bool AIOrder::ChangeOrder(VehicleID vehicle_id, OrderPosition order_position, AIOrder::AIOrderFlags order_flags)
00481 {
00482 AILog::Warning("AIOrder::ChangeOrder is deprecated and will be removed soon, please use AIOrder::SetOrderFlags instead.");
00483 return SetOrderFlags(vehicle_id, order_position, order_flags);
00484 }
00485
00486 bool AIOrder::MoveOrder(VehicleID vehicle_id, OrderPosition order_position_move, OrderPosition order_position_target)
00487 {
00488 order_position_move = AIOrder::ResolveOrderPosition(vehicle_id, order_position_move);
00489 order_position_target = AIOrder::ResolveOrderPosition(vehicle_id, order_position_target);
00490
00491 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_move));
00492 EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_target));
00493
00494 return AIObject::DoCommand(0, vehicle_id, order_position_move | (order_position_target << 16), CMD_MOVE_ORDER);
00495 }
00496
00497 bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00498 {
00499 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00500 EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00501
00502 return AIObject::DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_COPY, CMD_CLONE_ORDER);
00503 }
00504
00505 bool AIOrder::ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)
00506 {
00507 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00508 EnforcePrecondition(false, AIVehicle::IsValidVehicle(main_vehicle_id));
00509
00510 return AIObject::DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_SHARE, CMD_CLONE_ORDER);
00511 }
00512
00513 bool AIOrder::UnshareOrders(VehicleID vehicle_id)
00514 {
00515 EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
00516
00517 return AIObject::DoCommand(0, vehicle_id, CO_UNSHARE, CMD_CLONE_ORDER);
00518 }