|
1 /* $Id$ */ |
|
2 |
|
3 /** @file ai_order.cpp handles the functions of the AIOrder class */ |
|
4 |
|
5 #include "ai_order.hpp" |
|
6 #include "ai_map.hpp" |
|
7 #include "ai_vehicle.hpp" |
|
8 #include "../../command.h" |
|
9 #include "../../order.h" |
|
10 |
|
11 #include "../../depot.h" |
|
12 #include "../../rail_map.h" |
|
13 #include "../../road_map.h" |
|
14 #include "../../station_map.h" |
|
15 #include "../../water_map.h" |
|
16 #include "../../waypoint.h" |
|
17 |
|
18 /** |
|
19 * Gets the order type given a tile |
|
20 * @param t the tile to get the order from |
|
21 * @return the order type, or OT_END when there is no order |
|
22 */ |
|
23 static OrderType GetOrderTypeByTile(TileIndex t) |
|
24 { |
|
25 if (!::IsValidTile(t)) return OT_END; |
|
26 |
|
27 switch (::GetTileType(t)) { |
|
28 default: break; |
|
29 case MP_STATION: return OT_GOTO_STATION; break; |
|
30 case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break; |
|
31 case MP_STREET: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break; |
|
32 case MP_RAILWAY: |
|
33 switch (::GetRailTileType(t)) { |
|
34 case RAIL_TILE_DEPOT: return OT_GOTO_DEPOT; |
|
35 case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT; |
|
36 default: break; |
|
37 } |
|
38 break; |
|
39 } |
|
40 |
|
41 return OT_END; |
|
42 } |
|
43 |
|
44 /* static */ bool AIOrder::IsValidVehicleOrder(VehicleID vehicle_id, uint32 order_id) |
|
45 { |
|
46 return AIVehicle::IsValidVehicle(vehicle_id) && order_id < ::GetVehicle(vehicle_id)->num_orders; |
|
47 } |
|
48 |
|
49 /* static */ bool AIOrder::AreOrderFlagsValid(TileIndex destination, AIOrderFlags order_flags) |
|
50 { |
|
51 switch (::GetOrderTypeByTile(destination)) { |
|
52 case OT_GOTO_DEPOT: return (order_flags & ~(AIOF_NON_STOP | AIOF_SERVICE_IF_NEEDED)) == 0; |
|
53 case OT_GOTO_STATION: return (order_flags & ~(AIOF_NON_STOP | AIOF_TRANSFER | AIOF_UNLOAD | AIOF_FULL_LOAD)) == 0; |
|
54 case OT_GOTO_WAYPOINT: return (order_flags & ~(AIOF_NON_STOP)) == 0; |
|
55 default: return false; |
|
56 } |
|
57 } |
|
58 |
|
59 int32 AIOrder::GetNumberOfOrders(VehicleID vehicle_id) |
|
60 { |
|
61 return AIVehicle::IsValidVehicle(vehicle_id) ? ::GetVehicle(vehicle_id)->num_orders : -1; |
|
62 } |
|
63 |
|
64 TileIndex AIOrder::GetOrderDestination(VehicleID vehicle_id, uint32 order_id) |
|
65 { |
|
66 if (!AIOrder::IsValidVehicleOrder(vehicle_id, order_id)) return INVALID_TILE; |
|
67 |
|
68 Order *order = ::GetVehicle(vehicle_id)->orders; |
|
69 for (uint i = 0; i < order_id; i++) order = order->next; |
|
70 |
|
71 switch (order->type) { |
|
72 case OT_GOTO_DEPOT: return ::GetDepot(order->dest)->xy; |
|
73 case OT_GOTO_STATION: return ::GetStation(order->dest)->xy; |
|
74 case OT_GOTO_WAYPOINT: return ::GetWaypoint(order->dest)->xy; |
|
75 default: return INVALID_TILE; |
|
76 } |
|
77 } |
|
78 |
|
79 AIOrder::AIOrderFlags AIOrder::GetOrderFlags(VehicleID vehicle_id, uint32 order_id) |
|
80 { |
|
81 if (!AIOrder::IsValidVehicleOrder(vehicle_id, order_id)) return AIOF_INVALID; |
|
82 |
|
83 Order *order = ::GetVehicle(vehicle_id)->orders; |
|
84 for (uint i = 0; i < order_id; i++) order = order->next; |
|
85 |
|
86 return (AIOrder::AIOrderFlags)order->flags; |
|
87 } |
|
88 |
|
89 bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags) |
|
90 { |
|
91 if (!AIVehicle::IsValidVehicle(vehicle_id)) return false; |
|
92 return this->InsertOrder(vehicle_id, GetVehicle(vehicle_id)->num_orders, destination, order_flags); |
|
93 } |
|
94 |
|
95 bool AIOrder::InsertOrder(VehicleID vehicle_id, uint32 order_id, TileIndex destination, AIOrder::AIOrderFlags order_flags) |
|
96 { |
|
97 if (!IsValidVehicleOrder(vehicle_id, order_id) || |
|
98 !this->AreOrderFlagsValid(destination, order_flags)) return false; |
|
99 |
|
100 Order order; |
|
101 order.type = ::GetOrderTypeByTile(destination); |
|
102 order.flags = order_flags; |
|
103 switch (order.type) { |
|
104 case OT_GOTO_DEPOT: order.dest = ::GetDepotByTile(destination)->index; |
|
105 case OT_GOTO_STATION: order.dest = ::GetStationIndex(destination); |
|
106 case OT_GOTO_WAYPOINT: order.dest = ::GetWaypointIndex(destination); |
|
107 default: NOT_REACHED(); return false; |
|
108 } |
|
109 |
|
110 return this->DoCommand(0, vehicle_id | (order_id << 16), PackOrder(&order), CMD_INSERT_ORDER); |
|
111 } |
|
112 |
|
113 bool AIOrder::RemoveOrder(VehicleID vehicle_id, uint32 order_id) |
|
114 { |
|
115 if (!IsValidVehicleOrder(vehicle_id, order_id)) return false; |
|
116 |
|
117 return this->DoCommand(0, vehicle_id, order_id, CMD_DELETE_ORDER); |
|
118 } |
|
119 |
|
120 bool AIOrder::ChangeOrder(VehicleID vehicle_id, uint32 order_id, AIOrder::AIOrderFlags order_flags) |
|
121 { |
|
122 if (!IsValidVehicleOrder(vehicle_id, order_id) || |
|
123 !this->AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_id), order_flags)) return false; |
|
124 |
|
125 return this->DoCommand(0, vehicle_id | (order_id << 16), order_flags, CMD_MODIFY_ORDER); |
|
126 } |
|
127 |
|
128 bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id) |
|
129 { |
|
130 if (!AIVehicle::IsValidVehicle(vehicle_id) || !AIVehicle::IsValidVehicle(main_vehicle_id)) return false; |
|
131 |
|
132 return this->DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_COPY, CMD_CLONE_ORDER); |
|
133 } |
|
134 |
|
135 bool AIOrder::ShareOrders(VehicleID vehicle_id, VehicleID main_vehicle_id) |
|
136 { |
|
137 if (!AIVehicle::IsValidVehicle(vehicle_id) || !AIVehicle::IsValidVehicle(main_vehicle_id)) return false; |
|
138 |
|
139 return this->DoCommand(0, vehicle_id | (main_vehicle_id << 16), CO_SHARE, CMD_CLONE_ORDER); |
|
140 } |
|
141 |
|
142 bool AIOrder::UnshareOrders(VehicleID vehicle_id) |
|
143 { |
|
144 if (!AIVehicle::IsValidVehicle(vehicle_id)) return false; |
|
145 |
|
146 return this->DoCommand(0, vehicle_id, CO_UNSHARE, CMD_CLONE_ORDER); |
|
147 } |