46 this->flags = 0; |
46 this->flags = 0; |
47 this->dest = 0; |
47 this->dest = 0; |
48 this->next = NULL; |
48 this->next = NULL; |
49 } |
49 } |
50 |
50 |
|
51 void Order::MakeGoToStation(StationID destination) |
|
52 { |
|
53 this->type = OT_GOTO_STATION; |
|
54 this->flags = 0; |
|
55 this->dest = destination; |
|
56 } |
|
57 |
|
58 void Order::MakeGoToDepot(DepotID destination, bool order) |
|
59 { |
|
60 this->type = OT_GOTO_DEPOT; |
|
61 this->flags = order ? OFB_PART_OF_ORDERS : OFB_NON_STOP; |
|
62 this->dest = destination; |
|
63 this->refit_cargo = CT_NO_REFIT; |
|
64 this->refit_subtype = 0; |
|
65 } |
|
66 |
|
67 void Order::MakeGoToWaypoint(WaypointID destination) |
|
68 { |
|
69 this->type = OT_GOTO_WAYPOINT; |
|
70 this->flags = 0; |
|
71 this->dest = destination; |
|
72 } |
|
73 |
|
74 void Order::MakeLoading() |
|
75 { |
|
76 this->type = OT_LOADING; |
|
77 } |
|
78 |
|
79 void Order::MakeLeaveStation() |
|
80 { |
|
81 this->type = OT_LEAVESTATION; |
|
82 this->flags = 0; |
|
83 } |
|
84 |
|
85 void Order::MakeDummy() |
|
86 { |
|
87 this->type = OT_DUMMY; |
|
88 this->flags = 0; |
|
89 } |
|
90 |
51 void Order::FreeChain() |
91 void Order::FreeChain() |
52 { |
92 { |
53 if (next != NULL) next->FreeChain(); |
93 if (next != NULL) next->FreeChain(); |
54 delete this; |
94 delete this; |
55 } |
95 } |
126 /** |
166 /** |
127 * |
167 * |
128 * Unpacks a order from savegames with version 4 and lower |
168 * Unpacks a order from savegames with version 4 and lower |
129 * |
169 * |
130 */ |
170 */ |
131 static Order UnpackVersion4Order(uint16 packed) |
171 Order UnpackVersion4Order(uint16 packed) |
132 { |
172 { |
133 Order order; |
173 Order order; |
134 order.type = (OrderType)GB(packed, 0, 4); |
174 order.type = (OrderType)GB(packed, 0, 4); |
135 order.flags = GB(packed, 4, 4); |
175 order.flags = GB(packed, 4, 4); |
136 order.dest = GB(packed, 8, 8); |
176 order.dest = GB(packed, 8, 8); |
239 |
279 |
240 if (!CheckOwnership(v->owner)) return CMD_ERROR; |
280 if (!CheckOwnership(v->owner)) return CMD_ERROR; |
241 |
281 |
242 /* Check if the inserted order is to the correct destination (owner, type), |
282 /* Check if the inserted order is to the correct destination (owner, type), |
243 * and has the correct flags if any */ |
283 * and has the correct flags if any */ |
244 switch (new_order.type) { |
284 switch (new_order.GetType()) { |
245 case OT_GOTO_STATION: { |
285 case OT_GOTO_STATION: { |
246 const Station *st; |
286 const Station *st; |
247 |
287 |
248 if (!IsValidStationID(new_order.dest)) return CMD_ERROR; |
288 if (!IsValidStationID(new_order.dest)) return CMD_ERROR; |
249 st = GetStation(new_order.dest); |
289 st = GetStation(new_order.dest); |
399 |
439 |
400 /* Find the last goto station or depot order before the insert location. |
440 /* Find the last goto station or depot order before the insert location. |
401 * If the order is to be inserted at the beginning of the order list this |
441 * If the order is to be inserted at the beginning of the order list this |
402 * finds the last order in the list. */ |
442 * finds the last order in the list. */ |
403 for (const Order *o = v->orders; o != NULL; o = o->next) { |
443 for (const Order *o = v->orders; o != NULL; o = o->next) { |
404 if (o->type == OT_GOTO_STATION || o->type == OT_GOTO_DEPOT) prev = o; |
444 if (o->IsType(OT_GOTO_STATION) || o->IsType(OT_GOTO_DEPOT)) prev = o; |
405 if (++n == sel_ord && prev != NULL) break; |
445 if (++n == sel_ord && prev != NULL) break; |
406 } |
446 } |
407 if (prev != NULL) { |
447 if (prev != NULL) { |
408 uint dist = DistanceManhattan( |
448 uint dist = DistanceManhattan( |
409 GetOrderLocation(*prev), |
449 GetOrderLocation(*prev), |
573 |
613 |
574 assert(v->orders == u->orders); |
614 assert(v->orders == u->orders); |
575 |
615 |
576 /* NON-stop flag is misused to see if a train is in a station that is |
616 /* NON-stop flag is misused to see if a train is in a station that is |
577 * on his order list or not */ |
617 * on his order list or not */ |
578 if (sel_ord == u->cur_order_index && u->current_order.type == OT_LOADING && |
618 if (sel_ord == u->cur_order_index && u->current_order.IsType(OT_LOADING) && |
579 HasBit(u->current_order.flags, OF_NON_STOP)) { |
619 HasBit(u->current_order.flags, OF_NON_STOP)) { |
580 u->current_order.flags = 0; |
620 u->current_order.flags = 0; |
581 } |
621 } |
582 |
622 |
583 /* Update any possible open window of the vehicle */ |
623 /* Update any possible open window of the vehicle */ |
612 if (flags & DC_EXEC) { |
652 if (flags & DC_EXEC) { |
613 v->cur_order_index = sel_ord; |
653 v->cur_order_index = sel_ord; |
614 |
654 |
615 if (v->type == VEH_ROAD) ClearSlot(v); |
655 if (v->type == VEH_ROAD) ClearSlot(v); |
616 |
656 |
617 if (v->current_order.type == OT_LOADING) { |
657 if (v->current_order.IsType(OT_LOADING)) { |
618 v->LeaveStation(); |
658 v->LeaveStation(); |
619 /* NON-stop flag is misused to see if a train is in a station that is |
659 /* NON-stop flag is misused to see if a train is in a station that is |
620 * on his order list or not */ |
660 * on his order list or not */ |
621 if (HasBit(v->current_order.flags, OF_NON_STOP)) v->current_order.flags = 0; |
661 if (HasBit(v->current_order.flags, OF_NON_STOP)) v->current_order.flags = 0; |
622 } |
662 } |
743 |
783 |
744 /* Is it a valid order? */ |
784 /* Is it a valid order? */ |
745 if (sel_ord >= v->num_orders) return CMD_ERROR; |
785 if (sel_ord >= v->num_orders) return CMD_ERROR; |
746 |
786 |
747 order = GetVehicleOrder(v, sel_ord); |
787 order = GetVehicleOrder(v, sel_ord); |
748 if ((order->type != OT_GOTO_STATION || GetStation(order->dest)->IsBuoy()) && |
788 if ((!order->IsType(OT_GOTO_STATION) || GetStation(order->dest)->IsBuoy()) && |
749 (order->type != OT_GOTO_DEPOT || p2 == OF_UNLOAD) && |
789 (!order->IsType(OT_GOTO_DEPOT) || p2 == OF_UNLOAD) && |
750 (order->type != OT_GOTO_WAYPOINT || p2 != OF_NON_STOP)) { |
790 (!order->IsType(OT_GOTO_WAYPOINT) || p2 != OF_NON_STOP)) { |
751 return CMD_ERROR; |
791 return CMD_ERROR; |
752 } |
792 } |
753 |
793 |
754 if (flags & DC_EXEC) { |
794 if (flags & DC_EXEC) { |
755 switch (p2) { |
795 switch (p2) { |
756 case OF_FULL_LOAD: |
796 case OF_FULL_LOAD: |
757 ToggleBit(order->flags, OF_FULL_LOAD); |
797 ToggleBit(order->flags, OF_FULL_LOAD); |
758 if (order->type != OT_GOTO_DEPOT) ClrBit(order->flags, OF_UNLOAD); |
798 if (!order->IsType(OT_GOTO_DEPOT)) ClrBit(order->flags, OF_UNLOAD); |
759 break; |
799 break; |
760 case OF_UNLOAD: |
800 case OF_UNLOAD: |
761 ToggleBit(order->flags, OF_UNLOAD); |
801 ToggleBit(order->flags, OF_UNLOAD); |
762 ClrBit(order->flags, OF_FULL_LOAD); |
802 ClrBit(order->flags, OF_FULL_LOAD); |
763 break; |
803 break; |
785 * other cases for the OrderTypeByte the flags are not used, |
825 * other cases for the OrderTypeByte the flags are not used, |
786 * so do not care and those orders should not be active |
826 * so do not care and those orders should not be active |
787 * when this function is called. |
827 * when this function is called. |
788 */ |
828 */ |
789 if (sel_ord == u->cur_order_index && |
829 if (sel_ord == u->cur_order_index && |
790 u->current_order.type != OT_GOTO_DEPOT && |
830 !u->current_order.IsType(OT_GOTO_DEPOT) && |
791 HasBit(u->current_order.flags, OF_FULL_LOAD) != HasBit(order->flags, OF_FULL_LOAD)) { |
831 HasBit(u->current_order.flags, OF_FULL_LOAD) != HasBit(order->flags, OF_FULL_LOAD)) { |
792 ToggleBit(u->current_order.flags, OF_FULL_LOAD); |
832 ToggleBit(u->current_order.flags, OF_FULL_LOAD); |
793 } |
833 } |
794 InvalidateVehicleOrder(u); |
834 InvalidateVehicleOrder(u); |
795 } |
835 } |
882 if (src->type == VEH_ROAD) { |
922 if (src->type == VEH_ROAD) { |
883 const Order *order; |
923 const Order *order; |
884 TileIndex required_dst = INVALID_TILE; |
924 TileIndex required_dst = INVALID_TILE; |
885 |
925 |
886 FOR_VEHICLE_ORDERS(src, order) { |
926 FOR_VEHICLE_ORDERS(src, order) { |
887 if (order->type == OT_GOTO_STATION) { |
927 if (order->IsType(OT_GOTO_STATION)) { |
888 const Station *st = GetStation(order->dest); |
928 const Station *st = GetStation(order->dest); |
889 if (IsCargoInClass(dst->cargo_type, CC_PASSENGERS)) { |
929 if (IsCargoInClass(dst->cargo_type, CC_PASSENGERS)) { |
890 if (st->bus_stops != NULL) required_dst = st->bus_stops->xy; |
930 if (st->bus_stops != NULL) required_dst = st->bus_stops->xy; |
891 } else { |
931 } else { |
892 if (st->truck_stops != NULL) required_dst = st->truck_stops->xy; |
932 if (st->truck_stops != NULL) required_dst = st->truck_stops->xy; |
1160 /* Check the order list */ |
1200 /* Check the order list */ |
1161 n_st = 0; |
1201 n_st = 0; |
1162 |
1202 |
1163 FOR_VEHICLE_ORDERS(v, order) { |
1203 FOR_VEHICLE_ORDERS(v, order) { |
1164 /* Dummy order? */ |
1204 /* Dummy order? */ |
1165 if (order->type == OT_DUMMY) { |
1205 if (order->IsType(OT_DUMMY)) { |
1166 problem_type = 1; |
1206 problem_type = 1; |
1167 break; |
1207 break; |
1168 } |
1208 } |
1169 /* Does station have a load-bay for this vehicle? */ |
1209 /* Does station have a load-bay for this vehicle? */ |
1170 if (order->type == OT_GOTO_STATION) { |
1210 if (order->IsType(OT_GOTO_STATION)) { |
1171 const Station* st = GetStation(order->dest); |
1211 const Station* st = GetStation(order->dest); |
1172 TileIndex required_tile = GetStationTileForVehicle(v, st); |
1212 TileIndex required_tile = GetStationTileForVehicle(v, st); |
1173 |
1213 |
1174 n_st++; |
1214 n_st++; |
1175 if (required_tile == 0) problem_type = 3; |
1215 if (required_tile == 0) problem_type = 3; |
1226 if (v->last_station_visited == destination && type == OT_GOTO_STATION) { |
1266 if (v->last_station_visited == destination && type == OT_GOTO_STATION) { |
1227 v->last_station_visited = INVALID_STATION; |
1267 v->last_station_visited = INVALID_STATION; |
1228 } |
1268 } |
1229 |
1269 |
1230 order = &v->current_order; |
1270 order = &v->current_order; |
1231 if ((v->type == VEH_AIRCRAFT && order->type == OT_GOTO_DEPOT ? OT_GOTO_STATION : order->type) == type && |
1271 if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type && |
1232 v->current_order.dest == destination) { |
1272 v->current_order.dest == destination) { |
1233 order->type = OT_DUMMY; |
1273 order->MakeDummy(); |
1234 order->flags = 0; |
|
1235 InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
1274 InvalidateWindow(WC_VEHICLE_VIEW, v->index); |
1236 } |
1275 } |
1237 |
1276 |
1238 /* Clear the order from the order-list */ |
1277 /* Clear the order from the order-list */ |
1239 invalidate = false; |
1278 invalidate = false; |
1240 FOR_VEHICLE_ORDERS(v, order) { |
1279 FOR_VEHICLE_ORDERS(v, order) { |
1241 if ((v->type == VEH_AIRCRAFT && order->type == OT_GOTO_DEPOT ? OT_GOTO_STATION : order->type) == type && |
1280 if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type && |
1242 order->dest == destination) { |
1281 order->dest == destination) { |
1243 order->type = OT_DUMMY; |
1282 order->MakeDummy(); |
1244 order->flags = 0; |
|
1245 invalidate = true; |
1283 invalidate = true; |
1246 } |
1284 } |
1247 } |
1285 } |
1248 |
1286 |
1249 /* Only invalidate once, and if needed */ |
1287 /* Only invalidate once, and if needed */ |
1352 * @return true *if* the vehicle is eligible for reversing |
1390 * @return true *if* the vehicle is eligible for reversing |
1353 * (basically only when leaving a station). |
1391 * (basically only when leaving a station). |
1354 */ |
1392 */ |
1355 bool ProcessOrders(Vehicle *v) |
1393 bool ProcessOrders(Vehicle *v) |
1356 { |
1394 { |
1357 switch (v->current_order.type) { |
1395 switch (v->current_order.GetType()) { |
1358 case OT_GOTO_DEPOT: |
1396 case OT_GOTO_DEPOT: |
1359 /* Let a depot order in the orderlist interrupt. */ |
1397 /* Let a depot order in the orderlist interrupt. */ |
1360 if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return false; |
1398 if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return false; |
1361 |
1399 |
1362 if ((v->current_order.flags & OFB_SERVICE_IF_NEEDED) && !VehicleNeedsService(v)) { |
1400 if ((v->current_order.flags & OFB_SERVICE_IF_NEEDED) && !VehicleNeedsService(v)) { |
1380 * station (and the difficulty setting to allowed, of course) |
1418 * station (and the difficulty setting to allowed, of course) |
1381 * this can be detected because only after OT_LEAVESTATION, current_order |
1419 * this can be detected because only after OT_LEAVESTATION, current_order |
1382 * will be reset to nothing. (That also happens if no order, but in that case |
1420 * will be reset to nothing. (That also happens if no order, but in that case |
1383 * it won't hit the point in code where may_reverse is checked) |
1421 * it won't hit the point in code where may_reverse is checked) |
1384 */ |
1422 */ |
1385 bool may_reverse = v->current_order.type == OT_NOTHING; |
1423 bool may_reverse = v->current_order.IsType(OT_NOTHING); |
1386 |
1424 |
1387 /* Check if we've reached the waypoint? */ |
1425 /* Check if we've reached the waypoint? */ |
1388 if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) { |
1426 if (v->current_order.IsType(OT_GOTO_WAYPOINT) && v->tile == v->dest_tile) { |
1389 UpdateVehicleTimetable(v, true); |
1427 UpdateVehicleTimetable(v, true); |
1390 v->cur_order_index++; |
1428 v->cur_order_index++; |
1391 } |
1429 } |
1392 |
1430 |
1393 /* Check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */ |
1431 /* Check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */ |
1404 if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0; |
1442 if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0; |
1405 |
1443 |
1406 const Order *order = GetVehicleOrder(v, v->cur_order_index); |
1444 const Order *order = GetVehicleOrder(v, v->cur_order_index); |
1407 |
1445 |
1408 /* If no order, do nothing. */ |
1446 /* If no order, do nothing. */ |
1409 if (order == NULL || (v->type == VEH_AIRCRAFT && order->type == OT_DUMMY && !CheckForValidOrders(v))) { |
1447 if (order == NULL || (v->type == VEH_AIRCRAFT && order->IsType(OT_DUMMY) && !CheckForValidOrders(v))) { |
1410 if (v->type == VEH_AIRCRAFT) { |
1448 if (v->type == VEH_AIRCRAFT) { |
1411 /* Aircraft do something vastly different here, so handle separately */ |
1449 /* Aircraft do something vastly different here, so handle separately */ |
1412 extern void HandleMissingAircraftOrders(Vehicle *v); |
1450 extern void HandleMissingAircraftOrders(Vehicle *v); |
1413 HandleMissingAircraftOrders(v); |
1451 HandleMissingAircraftOrders(v); |
1414 return false; |
1452 return false; |
1420 return false; |
1458 return false; |
1421 } |
1459 } |
1422 |
1460 |
1423 /* If it is unchanged, keep it. */ |
1461 /* If it is unchanged, keep it. */ |
1424 if (order->Equals(v->current_order) && |
1462 if (order->Equals(v->current_order) && |
1425 (v->type != VEH_SHIP || order->type != OT_GOTO_STATION || GetStation(order->dest)->dock_tile != 0)) { |
1463 (v->type != VEH_SHIP || !order->IsType(OT_GOTO_STATION) || GetStation(order->dest)->dock_tile != 0)) { |
1426 return false; |
1464 return false; |
1427 } |
1465 } |
1428 |
1466 |
1429 /* Otherwise set it, and determine the destination tile. */ |
1467 /* Otherwise set it, and determine the destination tile. */ |
1430 v->current_order = *order; |
1468 v->current_order = *order; |
1488 _Order_pool.AddBlockToPool(); |
1526 _Order_pool.AddBlockToPool(); |
1489 |
1527 |
1490 _backup_orders_tile = 0; |
1528 _backup_orders_tile = 0; |
1491 } |
1529 } |
1492 |
1530 |
|
1531 const SaveLoad *GetOrderDescription() { |
1493 static const SaveLoad _order_desc[] = { |
1532 static const SaveLoad _order_desc[] = { |
1494 SLE_VAR(Order, type, SLE_UINT8), |
1533 SLE_VAR(Order, type, SLE_UINT8), |
1495 SLE_VAR(Order, flags, SLE_UINT8), |
1534 SLE_VAR(Order, flags, SLE_UINT8), |
1496 SLE_VAR(Order, dest, SLE_UINT16), |
1535 SLE_VAR(Order, dest, SLE_UINT16), |
1497 SLE_REF(Order, next, REF_ORDER), |
1536 SLE_REF(Order, next, REF_ORDER), |
1503 /* Leftover from the minor savegame version stuff |
1542 /* Leftover from the minor savegame version stuff |
1504 * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */ |
1543 * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */ |
1505 SLE_CONDNULL(10, 5, 35), |
1544 SLE_CONDNULL(10, 5, 35), |
1506 SLE_END() |
1545 SLE_END() |
1507 }; |
1546 }; |
|
1547 return _order_desc; |
|
1548 } |
1508 |
1549 |
1509 static void Save_ORDR() |
1550 static void Save_ORDR() |
1510 { |
1551 { |
1511 Order *order; |
1552 Order *order; |
1512 |
1553 |
1513 FOR_ALL_ORDERS(order) { |
1554 FOR_ALL_ORDERS(order) { |
1514 SlSetArrayIndex(order->index); |
1555 SlSetArrayIndex(order->index); |
1515 SlObject(order, _order_desc); |
1556 SlObject(order, GetOrderDescription()); |
1516 } |
1557 } |
1517 } |
1558 } |
1518 |
1559 |
1519 static void Load_ORDR() |
1560 static void Load_ORDR() |
1520 { |
1561 { |