151 } |
151 } |
152 |
152 |
153 const Depot *depot = FindClosestShipDepot(v); |
153 const Depot *depot = FindClosestShipDepot(v); |
154 |
154 |
155 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
155 if (depot == NULL || DistanceManhattan(v->tile, depot->xy) > 12) { |
156 if (v->current_order.type == OT_GOTO_DEPOT) { |
156 if (v->current_order.IsType(OT_GOTO_DEPOT)) { |
157 v->current_order.type = OT_DUMMY; |
157 v->current_order.MakeDummy(); |
158 v->current_order.flags = 0; |
|
159 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
158 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
160 } |
159 } |
161 return; |
160 return; |
162 } |
161 } |
163 |
162 |
164 v->current_order.type = OT_GOTO_DEPOT; |
163 v->current_order.MakeGoToDepot(depot->index, false); |
165 v->current_order.flags = OFB_NON_STOP; |
|
166 v->current_order.dest = depot->index; |
|
167 v->dest_tile = depot->xy; |
164 v->dest_tile = depot->xy; |
168 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
165 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
169 } |
166 } |
170 |
167 |
171 void Ship::OnNewDay() |
168 void Ship::OnNewDay() |
240 void Ship::PlayLeaveStationSound() const |
237 void Ship::PlayLeaveStationSound() const |
241 { |
238 { |
242 PlayShipSound(this); |
239 PlayShipSound(this); |
243 } |
240 } |
244 |
241 |
245 static void ProcessShipOrder(Vehicle *v) |
242 TileIndex Ship::GetOrderStationLocation(StationID station) |
246 { |
243 { |
247 const Order *order; |
244 if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION; |
248 |
245 |
249 switch (v->current_order.type) { |
246 Station *st = GetStation(station); |
250 case OT_GOTO_DEPOT: |
247 if (st->dock_tile != 0) { |
251 if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return; |
248 return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile))); |
252 if (v->current_order.flags & OFB_SERVICE_IF_NEEDED && |
|
253 !VehicleNeedsService(v)) { |
|
254 UpdateVehicleTimetable(v, true); |
|
255 v->cur_order_index++; |
|
256 } |
|
257 break; |
|
258 |
|
259 case OT_LOADING: |
|
260 case OT_LEAVESTATION: |
|
261 return; |
|
262 |
|
263 default: break; |
|
264 } |
|
265 |
|
266 if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0; |
|
267 |
|
268 order = GetVehicleOrder(v, v->cur_order_index); |
|
269 |
|
270 if (order == NULL) { |
|
271 v->current_order.Free(); |
|
272 v->dest_tile = 0; |
|
273 return; |
|
274 } |
|
275 |
|
276 if (order->type == v->current_order.type && |
|
277 order->flags == v->current_order.flags && |
|
278 order->dest == v->current_order.dest && |
|
279 (order->type != OT_GOTO_STATION || GetStation(order->dest)->dock_tile != 0)) |
|
280 return; |
|
281 |
|
282 v->current_order = *order; |
|
283 |
|
284 if (order->type == OT_GOTO_STATION) { |
|
285 const Station *st; |
|
286 |
|
287 if (order->dest == v->last_station_visited) |
|
288 v->last_station_visited = INVALID_STATION; |
|
289 |
|
290 st = GetStation(order->dest); |
|
291 if (st->dock_tile != 0) { |
|
292 v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile))); |
|
293 } else { |
|
294 v->cur_order_index++; |
|
295 } |
|
296 } else if (order->type == OT_GOTO_DEPOT) { |
|
297 v->dest_tile = GetDepot(order->dest)->xy; |
|
298 } else { |
249 } else { |
299 v->dest_tile = 0; |
250 this->cur_order_index++; |
300 } |
251 return 0; |
301 |
252 } |
302 InvalidateVehicleOrder(v); |
|
303 |
|
304 InvalidateWindowClasses(WC_SHIPS_LIST); |
|
305 } |
253 } |
306 |
254 |
307 void Ship::UpdateDeltaXY(Direction direction) |
255 void Ship::UpdateDeltaXY(Direction direction) |
308 { |
256 { |
309 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
257 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0) |
320 #undef MKIT |
268 #undef MKIT |
321 |
269 |
322 uint32 x = _delta_xy_table[direction]; |
270 uint32 x = _delta_xy_table[direction]; |
323 this->x_offs = GB(x, 0, 8); |
271 this->x_offs = GB(x, 0, 8); |
324 this->y_offs = GB(x, 8, 8); |
272 this->y_offs = GB(x, 8, 8); |
325 this->sprite_width = GB(x, 16, 8); |
273 this->x_extent = GB(x, 16, 8); |
326 this->sprite_height = GB(x, 24, 8); |
274 this->y_extent = GB(x, 24, 8); |
327 this->z_height = 6; |
275 this->z_extent = 6; |
328 } |
276 } |
329 |
277 |
330 void RecalcShipStuff(Vehicle *v) |
278 void RecalcShipStuff(Vehicle *v) |
331 { |
279 { |
332 v->UpdateDeltaXY(v->direction); |
280 v->UpdateDeltaXY(v->direction); |
472 i = RemoveFirstTrack(&bits); |
420 i = RemoveFirstTrack(&bits); |
473 |
421 |
474 pfs.best_bird_dist = (uint)-1; |
422 pfs.best_bird_dist = (uint)-1; |
475 pfs.best_length = (uint)-1; |
423 pfs.best_length = (uint)-1; |
476 |
424 |
477 FollowTrack(tile, 0x1800 | TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs); |
425 FollowTrack(tile, PATHFIND_FLAGS_SHIP_MODE | PATHFIND_FLAGS_DISABLE_TILE_HASH, TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs); |
478 |
426 |
479 if (best_track != INVALID_TRACK) { |
427 if (best_track != INVALID_TRACK) { |
480 if (pfs.best_bird_dist != 0) { |
428 if (pfs.best_bird_dist != 0) { |
481 /* neither reached the destination, pick the one with the smallest bird dist */ |
429 /* neither reached the destination, pick the one with the smallest bird dist */ |
482 if (pfs.best_bird_dist > best_bird_dist) goto bad; |
430 if (pfs.best_bird_dist > best_bird_dist) goto bad; |
672 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
620 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
673 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
621 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
674 |
622 |
675 /* A leave station order only needs one tick to get processed, so we can |
623 /* A leave station order only needs one tick to get processed, so we can |
676 * always skip ahead. */ |
624 * always skip ahead. */ |
677 if (v->current_order.type == OT_LEAVESTATION) { |
625 if (v->current_order.IsType(OT_LEAVESTATION)) { |
678 v->current_order.Free(); |
626 v->current_order.Free(); |
679 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
627 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
680 } else if (v->dest_tile != 0) { |
628 } else if (v->dest_tile != 0) { |
681 /* We have a target, let's see if we reached it... */ |
629 /* We have a target, let's see if we reached it... */ |
682 if (v->current_order.type == OT_GOTO_STATION && |
630 if (v->current_order.IsType(OT_GOTO_STATION) && |
683 IsBuoyTile(v->dest_tile) && |
631 IsBuoyTile(v->dest_tile) && |
684 DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { |
632 DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { |
685 /* We got within 3 tiles of our target buoy, so let's skip to our |
633 /* We got within 3 tiles of our target buoy, so let's skip to our |
686 * next order */ |
634 * next order */ |
687 UpdateVehicleTimetable(v, true); |
635 UpdateVehicleTimetable(v, true); |
688 v->cur_order_index++; |
636 v->cur_order_index++; |
689 v->current_order.type = OT_DUMMY; |
637 v->current_order.MakeDummy(); |
690 InvalidateVehicleOrder(v); |
638 InvalidateVehicleOrder(v); |
691 } else { |
639 } else { |
692 /* Non-buoy orders really need to reach the tile */ |
640 /* Non-buoy orders really need to reach the tile */ |
693 if (v->dest_tile == gp.new_tile) { |
641 if (v->dest_tile == gp.new_tile) { |
694 if (v->current_order.type == OT_GOTO_DEPOT) { |
642 if (v->current_order.IsType(OT_GOTO_DEPOT)) { |
695 if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { |
643 if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { |
696 VehicleEnterDepot(v); |
644 VehicleEnterDepot(v); |
697 return; |
645 return; |
698 } |
646 } |
699 } else if (v->current_order.type == OT_GOTO_STATION) { |
647 } else if (v->current_order.IsType(OT_GOTO_STATION)) { |
700 Station *st; |
648 v->last_station_visited = v->current_order.GetDestination(); |
701 |
|
702 v->last_station_visited = v->current_order.dest; |
|
703 |
649 |
704 /* Process station in the orderlist. */ |
650 /* Process station in the orderlist. */ |
705 st = GetStation(v->current_order.dest); |
651 Station *st = GetStation(v->current_order.GetDestination()); |
706 if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations |
652 if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations |
707 ShipArrivesAt(v, st); |
653 ShipArrivesAt(v, st); |
708 v->BeginLoading(); |
654 v->BeginLoading(); |
709 } else { // leave stations without docks right aways |
655 } else { // leave stations without docks right aways |
710 v->current_order.type = OT_LEAVESTATION; |
656 v->current_order.MakeLeaveStation(); |
711 v->cur_order_index++; |
657 v->cur_order_index++; |
712 InvalidateVehicleOrder(v); |
658 InvalidateVehicleOrder(v); |
713 } |
659 } |
714 } |
660 } |
715 } |
661 } |
994 if (v->vehstatus & VS_CRASHED) return CMD_ERROR; |
940 if (v->vehstatus & VS_CRASHED) return CMD_ERROR; |
995 |
941 |
996 if (v->IsInDepot()) return CMD_ERROR; |
942 if (v->IsInDepot()) return CMD_ERROR; |
997 |
943 |
998 /* If the current orders are already goto-depot */ |
944 /* If the current orders are already goto-depot */ |
999 if (v->current_order.type == OT_GOTO_DEPOT) { |
945 if (v->current_order.IsType(OT_GOTO_DEPOT)) { |
1000 if (!!(p2 & DEPOT_SERVICE) == HasBit(v->current_order.flags, OF_HALT_IN_DEPOT)) { |
946 bool halt_in_depot = HasBit(v->current_order.GetDepotActionType(), OF_HALT_IN_DEPOT); |
|
947 if (!!(p2 & DEPOT_SERVICE) == halt_in_depot) { |
1001 /* We called with a different DEPOT_SERVICE setting. |
948 /* We called with a different DEPOT_SERVICE setting. |
1002 * Now we change the setting to apply the new one and let the vehicle head for the same depot. |
949 * Now we change the setting to apply the new one and let the vehicle head for the same depot. |
1003 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
950 * Note: the if is (true for requesting service == true for ordered to stop in depot) */ |
1004 if (flags & DC_EXEC) { |
951 if (flags & DC_EXEC) { |
1005 ClrBit(v->current_order.flags, OF_PART_OF_ORDERS); |
952 v->current_order.SetDepotOrderType(OFB_MANUAL_ORDER); |
1006 ToggleBit(v->current_order.flags, OF_HALT_IN_DEPOT); |
953 v->current_order.SetDepotActionType(halt_in_depot ? OFB_NORMAL_ACTION : OFB_HALT_IN_DEPOT); |
1007 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
954 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
1008 } |
955 } |
1009 return CommandCost(); |
956 return CommandCost(); |
1010 } |
957 } |
1011 |
958 |
1012 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
959 if (p2 & DEPOT_DONT_CANCEL) return CMD_ERROR; // Requested no cancelation of depot orders |
1013 if (flags & DC_EXEC) { |
960 if (flags & DC_EXEC) { |
1014 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
961 /* If the orders to 'goto depot' are in the orders list (forced servicing), |
1015 * then skip to the next order; effectively cancelling this forced service */ |
962 * then skip to the next order; effectively cancelling this forced service */ |
1016 if (HasBit(v->current_order.flags, OF_PART_OF_ORDERS)) |
963 if (v->current_order.GetDepotOrderType() & OFB_PART_OF_ORDERS) v->cur_order_index++; |
1017 v->cur_order_index++; |
964 |
1018 |
965 v->current_order.MakeDummy(); |
1019 v->current_order.type = OT_DUMMY; |
|
1020 v->current_order.flags = 0; |
|
1021 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
966 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
1022 } |
967 } |
1023 return CommandCost(); |
968 return CommandCost(); |
1024 } |
969 } |
1025 |
970 |
1026 dep = FindClosestShipDepot(v); |
971 dep = FindClosestShipDepot(v); |
1027 if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT); |
972 if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT); |
1028 |
973 |
1029 if (flags & DC_EXEC) { |
974 if (flags & DC_EXEC) { |
1030 if (v->current_order.type == OT_LOADING) v->LeaveStation(); |
975 if (v->current_order.IsType(OT_LOADING)) v->LeaveStation(); |
1031 |
976 |
1032 v->dest_tile = dep->xy; |
977 v->dest_tile = dep->xy; |
1033 v->current_order.type = OT_GOTO_DEPOT; |
978 v->current_order.MakeGoToDepot(dep->index, false); |
1034 v->current_order.flags = OFB_NON_STOP; |
979 if (!(p2 & DEPOT_SERVICE)) v->current_order.SetDepotActionType(OFB_HALT_IN_DEPOT); |
1035 if (!(p2 & DEPOT_SERVICE)) SetBit(v->current_order.flags, OF_HALT_IN_DEPOT); |
|
1036 v->current_order.refit_cargo = CT_INVALID; |
|
1037 v->current_order.dest = dep->index; |
|
1038 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
980 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
1039 } |
981 } |
1040 |
982 |
1041 return CommandCost(); |
983 return CommandCost(); |
1042 } |
984 } |