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