# HG changeset patch # User rubidium # Date 1208039287 0 # Node ID ddbb8d2ae3ea70293c2372e2453015d51d675c0d # Parent 56ee7da4ad5603e22a3a76ae2f06bf20ae2e3e64 (svn r12677) [NoAI] -Change [API CHANGE]: rework of the OrderFlags to support the new order possibilities in OpenTTD. As a result of this the following has changed: * AIOF_UNLOAD and AIOF_TRANSFER cannot be used at the same time anymore. Use AIOF_NO_LOAD and AIOF_TRANSFER for the same result. * AIOF_FULL_LOAD will now always full load the vehicle and not full load any when the corresponding patch setting has been set. Full load any can be achieved with AIOF_FULL_LOAD_ANY. * AIOF_NON_STOP has been replaced by AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS and AIOF_NON_STOP_AT_DESTINATION_STATION instead of determining the non-stop workings based on a patch setting. diff -r 56ee7da4ad56 -r ddbb8d2ae3ea src/ai/api/ai_order.cpp --- a/src/ai/api/ai_order.cpp Sat Apr 12 21:38:49 2008 +0000 +++ b/src/ai/api/ai_order.cpp Sat Apr 12 22:28:07 2008 +0000 @@ -49,9 +49,18 @@ /* static */ bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags) { switch (::GetOrderTypeByTile(destination)) { - case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP | AIOF_SERVICE_IF_NEEDED)) == 0; - case OT_GOTO_STATION: return (order_flags & ~(AIOF_NON_STOP | AIOF_TRANSFER | AIOF_UNLOAD | AIOF_FULL_LOAD)) == 0 && ((order_flags & AIOF_UNLOAD) == 0 || (order_flags & AIOF_FULL_LOAD) == 0); - case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP)) == 0; + case OT_GOTO_STATION: + return ((order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_UNLOAD_FLAGS | AIOF_LOAD_FLAGS)) == 0) && + /* Test the different mutual exclusive flags. */ + (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_UNLOAD) == 0)) && + (((order_flags & AIOF_TRANSFER) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) && + (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) && + (((order_flags & AIOF_UNLOAD) == 0) || ((order_flags & AIOF_NO_UNLOAD) == 0)) && + (((order_flags & AIOF_NO_UNLOAD) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)) && + (((order_flags & AIOF_FULL_LOAD_ANY) == 0) || ((order_flags & AIOF_NO_LOAD) == 0)); + + case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP_FLAGS | AIOF_SERVICE_IF_NEEDED)) == 0; + case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP_FLAGS)) == 0; default: return false; } } @@ -83,17 +92,16 @@ Order *order = ::GetVehicle(vehicle_id)->orders; for (uint i = 0; i < order_id; i++) order = order->next; - AIOrderFlags order_flags= AIOF_NONE; - if (order->GetNonStopType() != ONSF_STOP_EVERYWHERE) order_flags |= AIOF_NON_STOP; + AIOrderFlags order_flags = AIOF_NONE; + order_flags |= (AIOrderFlags)order->GetNonStopType(); switch (order->GetType()) { case OT_GOTO_DEPOT: if (order->GetDepotOrderType() & ODTFB_SERVICE) order_flags |= AIOF_SERVICE_IF_NEEDED; break; case OT_GOTO_STATION: - if (order->GetLoadType() & OLFB_FULL_LOAD) order_flags |= AIOF_FULL_LOAD; - if (order->GetUnloadType() & OUFB_UNLOAD) order_flags |= AIOF_UNLOAD; - if (order->GetUnloadType() & OUFB_TRANSFER) order_flags |= AIOF_TRANSFER; + order_flags |= (AIOrderFlags)(order->GetLoadType() << 5); + order_flags |= (AIOrderFlags)(order->GetUnloadType() << 2); break; default: break; @@ -118,14 +126,13 @@ Order order; switch (::GetOrderTypeByTile(destination)) { case OT_GOTO_DEPOT: - order.MakeGoToDepot(::GetDepotByTile(destination)->index, ODTFB_PART_OF_ORDERS); - if (order_flags & AIOF_SERVICE_IF_NEEDED) order.SetDepotOrderType(ODTFB_SERVICE); + order.MakeGoToDepot(::GetDepotByTile(destination)->index, (OrderDepotTypeFlags)(ODTFB_PART_OF_ORDERS | ((order_flags & AIOF_SERVICE_IF_NEEDED) ? ODTFB_SERVICE : 0))); break; case OT_GOTO_STATION: order.MakeGoToStation(::GetStationIndex(destination)); - if (order_flags & AIOF_FULL_LOAD) order.SetLoadType(OLFB_FULL_LOAD); - order.SetUnloadType((OrderUnloadFlags)(((order_flags & AIOF_TRANSFER) ? OUFB_TRANSFER : 0) | ((order_flags & AIOF_UNLOAD) ? OUFB_UNLOAD : 0))); + order.SetLoadType((OrderLoadFlags)GB(order_flags, 5, 3)); + order.SetUnloadType((OrderUnloadFlags)GB(order_flags, 2, 3)); break; case OT_GOTO_WAYPOINT: @@ -136,7 +143,7 @@ return false; } - if (order_flags & AIOF_NON_STOP) order.SetNonStopType(ONSF_NO_STOP_AT_DESTINATION_STATION); + order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2)); return AIObject::DoCommand(0, vehicle_id | (order_id << 16), order.Pack(), CMD_INSERT_ORDER); } @@ -153,16 +160,41 @@ EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_id)); EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_id), order_flags)); - for (;;) { - /* Loop as long as there is a difference between the requested and - * the current orders of the vehicle. */ - AIOrderFlags current = GetOrderFlags(vehicle_id, order_id); - AIOrderFlags diff = current ^ order_flags; - if (diff == 0) return true; + Order *order = ::GetVehicle(vehicle_id)->orders; + for (uint i = 0; i < order_id; i++) order = order->next; - bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), FIND_FIRST_BIT(diff), CMD_MODIFY_ORDER); + AIOrderFlags current = GetOrderFlags(vehicle_id, order_id); + + if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) { + bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER); if (!res) return false; } + + switch (order->GetType()) { + case OT_GOTO_DEPOT: + if ((current & AIOF_SERVICE_IF_NEEDED) != (order_flags & AIOF_SERVICE_IF_NEEDED)) { + bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), MOF_DEPOT_ACTION, CMD_MODIFY_ORDER); + if (!res) return false; + } + break; + + case OT_GOTO_STATION: + if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) { + bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER); + if (!res) return false; + } + if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) { + bool res = AIObject::DoCommand(0, vehicle_id | (order_id << 16), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER); + if (!res) return false; + } + break; + + default: break; + } + + assert(GetOrderFlags(vehicle_id, order_id) == order_flags); + + return true; } /* static */ bool AIOrder::MoveOrder(VehicleID vehicle_id, uint32 order_id_move, uint32 order_id_target) diff -r 56ee7da4ad56 -r ddbb8d2ae3ea src/ai/api/ai_order.hpp --- a/src/ai/api/ai_order.hpp Sat Apr 12 21:38:49 2008 +0000 +++ b/src/ai/api/ai_order.hpp Sat Apr 12 22:28:07 2008 +0000 @@ -36,18 +36,34 @@ /** Just go to the station/depot, stop unload if possible and load if needed. */ AIOF_NONE = 0, - /** Transfer instead of deliver the goods; only for stations. */ - AIOF_TRANSFER = 1 << 0, - /** Always unload the vehicle; only for stations. Cannot be set when AIOF_FULL_LOAD is set. */ - AIOF_UNLOAD = 1 << 1, - /** Wait till the the vehicle is fully loaded; only for stations. Cannot be set when AIOF_UNLOAD is set. */ - AIOF_FULL_LOAD = 1 << 2, + /** Do not stop at the stations that are passed when going to the destination. */ + AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS = 1 << 0, + /** Do not stop at the destionation station. */ + AIOF_NON_STOP_AT_DESTINATION_STATION = 1 << 1, + + /** Always unload the vehicle; only for stations. Cannot be set when AIOF_TRANSFER or AIOF_NO_UNLOAD is set. */ + AIOF_UNLOAD = 1 << 2, + /** Transfer instead of deliver the goods; only for stations. Cannot be set when AIOF_UNLOAD or AIOF_NO_UNLOAD is set. */ + AIOF_TRANSFER = 1 << 3, + /** Never unload the vehicle; only for stations. Cannot be set when AIOF_UNLOAD, AIOF_TRANSFER or AIOF_NO_LOAD is set. */ + AIOF_NO_UNLOAD = 1 << 4, + + /** Wait till the vehicle is fully loaded; only for stations. Cannot be set when AIOF_NO_LOAD is set. */ + AIOF_FULL_LOAD = 2 << 5, + /** Wait till at least one cargo of the vehicle is fully loaded; only for stations. Cannot be set when AIOF_NO_LOAD is set. */ + AIOF_FULL_LOAD_ANY = 3 << 5, + /** Do not load any cargo; only for stations. Cannot be set when AIOF_NO_UNLOAD, AIOF_FULL_LOAD or AIOF_FULL_LOAD_ANY is set. */ + AIOF_NO_LOAD = 1 << 7, /** Service the vehicle when needed, otherwise skip this order; only for depots. */ AIOF_SERVICE_IF_NEEDED = 1 << 2, - /** Do not stop at the stations that are passed when going to the destination. */ - AIOF_NON_STOP = 1 << 3, + /** All flags related to non-stop settings. */ + AIOF_NON_STOP_FLAGS = AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS | AIOF_NON_STOP_AT_DESTINATION_STATION, + /** All flags related to unloading. */ + AIOF_UNLOAD_FLAGS = AIOF_TRANSFER | AIOF_UNLOAD | AIOF_NO_UNLOAD, + /** All flags related to loading. */ + AIOF_LOAD_FLAGS = AIOF_FULL_LOAD | AIOF_FULL_LOAD_ANY | AIOF_NO_LOAD, /** For marking invalid order flags */ AIOF_INVALID = 0xFFFF, diff -r 56ee7da4ad56 -r ddbb8d2ae3ea src/ai/api/ai_order.hpp.sq --- a/src/ai/api/ai_order.hpp.sq Sat Apr 12 21:38:49 2008 +0000 +++ b/src/ai/api/ai_order.hpp.sq Sat Apr 12 22:28:07 2008 +0000 @@ -24,11 +24,18 @@ SQAIOrder.DefSQConst(engine, AIOrder::ERR_ORDER_TOO_MANY, "ERR_ORDER_TOO_MANY"); SQAIOrder.DefSQConst(engine, AIOrder::ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION, "ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION"); SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NONE, "AIOF_NONE"); - SQAIOrder.DefSQConst(engine, AIOrder::AIOF_TRANSFER, "AIOF_TRANSFER"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS, "AIOF_NON_STOP_AT_INTERMEDIATE_STATIONS"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_AT_DESTINATION_STATION, "AIOF_NON_STOP_AT_DESTINATION_STATION"); SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD, "AIOF_UNLOAD"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_TRANSFER, "AIOF_TRANSFER"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_UNLOAD, "AIOF_NO_UNLOAD"); SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD, "AIOF_FULL_LOAD"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_FULL_LOAD_ANY, "AIOF_FULL_LOAD_ANY"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NO_LOAD, "AIOF_NO_LOAD"); SQAIOrder.DefSQConst(engine, AIOrder::AIOF_SERVICE_IF_NEEDED, "AIOF_SERVICE_IF_NEEDED"); - SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP, "AIOF_NON_STOP"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_NON_STOP_FLAGS, "AIOF_NON_STOP_FLAGS"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_UNLOAD_FLAGS, "AIOF_UNLOAD_FLAGS"); + SQAIOrder.DefSQConst(engine, AIOrder::AIOF_LOAD_FLAGS, "AIOF_LOAD_FLAGS"); SQAIOrder.DefSQConst(engine, AIOrder::AIOF_INVALID, "AIOF_INVALID"); AIError::RegisterErrorMap(STR_8831_NO_MORE_SPACE_FOR_ORDERS, AIOrder::ERR_ORDER_TOO_MANY);