597 if (!ShipAccelerate(v)) return; |
597 if (!ShipAccelerate(v)) return; |
598 |
598 |
599 BeginVehicleMove(v); |
599 BeginVehicleMove(v); |
600 |
600 |
601 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
601 GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
602 if (gp.old_tile == gp.new_tile) { |
602 if (v->u.ship.state != TRACK_BIT_WORMHOLE) { |
603 /* Staying in tile */ |
603 /* Not on a bridge */ |
604 if (v->IsInDepot()) { |
604 if (gp.old_tile == gp.new_tile) { |
605 gp.x = v->x_pos; |
605 /* Staying in tile */ |
606 gp.y = v->y_pos; |
606 if (v->IsInDepot()) { |
607 } else { |
607 gp.x = v->x_pos; |
608 /* Not inside depot */ |
608 gp.y = v->y_pos; |
609 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
609 } else { |
610 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
610 /* Not inside depot */ |
611 |
611 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
612 /* A leave station order only needs one tick to get processed, so we can |
612 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
613 * always skip ahead. */ |
613 |
614 if (v->current_order.IsType(OT_LEAVESTATION)) { |
614 /* A leave station order only needs one tick to get processed, so we can |
615 v->current_order.Free(); |
615 * always skip ahead. */ |
616 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
616 if (v->current_order.IsType(OT_LEAVESTATION)) { |
617 } else if (v->dest_tile != 0) { |
617 v->current_order.Free(); |
618 /* We have a target, let's see if we reached it... */ |
618 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH); |
619 if (v->current_order.IsType(OT_GOTO_STATION) && |
619 } else if (v->dest_tile != 0) { |
620 IsBuoyTile(v->dest_tile) && |
620 /* We have a target, let's see if we reached it... */ |
621 DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { |
621 if (v->current_order.IsType(OT_GOTO_STATION) && |
622 /* We got within 3 tiles of our target buoy, so let's skip to our |
622 IsBuoyTile(v->dest_tile) && |
623 * next order */ |
623 DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) { |
624 UpdateVehicleTimetable(v, true); |
624 /* We got within 3 tiles of our target buoy, so let's skip to our |
625 v->cur_order_index++; |
625 * next order */ |
626 v->current_order.MakeDummy(); |
626 UpdateVehicleTimetable(v, true); |
627 InvalidateVehicleOrder(v); |
627 v->cur_order_index++; |
628 } else { |
628 v->current_order.MakeDummy(); |
629 /* Non-buoy orders really need to reach the tile */ |
629 InvalidateVehicleOrder(v); |
630 if (v->dest_tile == gp.new_tile) { |
630 } else { |
631 if (v->current_order.IsType(OT_GOTO_DEPOT)) { |
631 /* Non-buoy orders really need to reach the tile */ |
632 if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { |
632 if (v->dest_tile == gp.new_tile) { |
633 VehicleEnterDepot(v); |
633 if (v->current_order.IsType(OT_GOTO_DEPOT)) { |
634 return; |
634 if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) { |
635 } |
635 VehicleEnterDepot(v); |
636 } else if (v->current_order.IsType(OT_GOTO_STATION)) { |
636 return; |
637 v->last_station_visited = v->current_order.GetDestination(); |
637 } |
638 |
638 } else if (v->current_order.IsType(OT_GOTO_STATION)) { |
639 /* Process station in the orderlist. */ |
639 v->last_station_visited = v->current_order.GetDestination(); |
640 Station *st = GetStation(v->current_order.GetDestination()); |
640 |
641 if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations |
641 /* Process station in the orderlist. */ |
642 ShipArrivesAt(v, st); |
642 Station *st = GetStation(v->current_order.GetDestination()); |
643 v->BeginLoading(); |
643 if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations |
644 } else { // leave stations without docks right aways |
644 ShipArrivesAt(v, st); |
645 v->current_order.MakeLeaveStation(); |
645 v->BeginLoading(); |
646 v->cur_order_index++; |
646 } else { // leave stations without docks right aways |
647 InvalidateVehicleOrder(v); |
647 v->current_order.MakeLeaveStation(); |
|
648 v->cur_order_index++; |
|
649 InvalidateVehicleOrder(v); |
|
650 } |
648 } |
651 } |
649 } |
652 } |
650 } |
653 } |
651 } |
654 } |
652 } |
655 } |
|
656 } else { |
|
657 DiagDirection diagdir; |
|
658 /* New tile */ |
|
659 if (TileX(gp.new_tile) >= MapMaxX() || TileY(gp.new_tile) >= MapMaxY()) { |
|
660 goto reverse_direction; |
|
661 } |
|
662 |
|
663 dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile); |
|
664 assert(dir == DIR_NE || dir == DIR_SE || dir == DIR_SW || dir == DIR_NW); |
|
665 diagdir = DirToDiagDir(dir); |
|
666 tracks = GetAvailShipTracks(gp.new_tile, diagdir); |
|
667 if (tracks == TRACK_BIT_NONE) goto reverse_direction; |
|
668 |
|
669 /* Choose a direction, and continue if we find one */ |
|
670 track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks); |
|
671 if (track == INVALID_TRACK) goto reverse_direction; |
|
672 |
|
673 b = _ship_subcoord[diagdir][track]; |
|
674 |
|
675 gp.x = (gp.x & ~0xF) | b[0]; |
|
676 gp.y = (gp.y & ~0xF) | b[1]; |
|
677 |
|
678 /* Call the landscape function and tell it that the vehicle entered the tile */ |
|
679 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
680 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
|
681 |
|
682 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { |
|
683 v->tile = gp.new_tile; |
|
684 v->u.ship.state = TrackToTrackBits(track); |
|
685 } |
|
686 |
|
687 v->direction = (Direction)b[2]; |
653 } |
688 } |
654 } else { |
689 } else { |
655 DiagDirection diagdir; |
690 /* On a bridge */ |
656 /* New tile */ |
691 if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { |
657 if (TileX(gp.new_tile) >= MapMaxX() || TileY(gp.new_tile) >= MapMaxY()) { |
692 v->x_pos = gp.x; |
658 goto reverse_direction; |
693 v->y_pos = gp.y; |
|
694 VehiclePositionChanged(v); |
|
695 if (!(v->vehstatus & VS_HIDDEN)) EndVehicleMove(v); |
|
696 return; |
659 } |
697 } |
660 |
|
661 dir = ShipGetNewDirectionFromTiles(gp.new_tile, gp.old_tile); |
|
662 assert(dir == DIR_NE || dir == DIR_SE || dir == DIR_SW || dir == DIR_NW); |
|
663 diagdir = DirToDiagDir(dir); |
|
664 tracks = GetAvailShipTracks(gp.new_tile, diagdir); |
|
665 if (tracks == TRACK_BIT_NONE) goto reverse_direction; |
|
666 |
|
667 /* Choose a direction, and continue if we find one */ |
|
668 track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks); |
|
669 if (track == INVALID_TRACK) goto reverse_direction; |
|
670 |
|
671 b = _ship_subcoord[diagdir][track]; |
|
672 |
|
673 gp.x = (gp.x & ~0xF) | b[0]; |
|
674 gp.y = (gp.y & ~0xF) | b[1]; |
|
675 |
|
676 /* Call the landscape function and tell it that the vehicle entered the tile */ |
|
677 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
|
678 if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
|
679 |
|
680 if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { |
|
681 v->tile = gp.new_tile; |
|
682 v->u.ship.state = TrackToTrackBits(track); |
|
683 } |
|
684 |
|
685 v->direction = (Direction)b[2]; |
|
686 } |
698 } |
687 |
699 |
688 /* update image of ship, as well as delta XY */ |
700 /* update image of ship, as well as delta XY */ |
689 dir = ShipGetNewDirection(v, gp.x, gp.y); |
701 dir = ShipGetNewDirection(v, gp.x, gp.y); |
690 v->x_pos = gp.x; |
702 v->x_pos = gp.x; |