| 667 | } |
| 668 | |
| 669 | static void ShipController(Ship *v) |
| 670 | { |
| 671 | v->tick_counter++; |
| 672 | v->current_order_time++; |
| 673 | |
| 674 | if (v->HandleBreakdown()) return; |
| 675 | |
| 676 | if (v->vehstatus.Test(VehState::Stopped)) return; |
| 677 | |
| 678 | if (ProcessOrders(v) && CheckReverseShip(v)) return ReverseShip(v); |
| 679 | |
| 680 | v->HandleLoading(); |
| 681 | |
| 682 | if (v->current_order.IsType(OT_LOADING)) return; |
| 683 | |
| 684 | if (CheckShipStayInDepot(v)) return; |
| 685 | |
| 686 | v->ShowVisualEffect(); |
| 687 | |
| 688 | /* Rotating on spot */ |
| 689 | if (v->direction != v->rotation) { |
| 690 | if ((v->tick_counter & 7) == 0) { |
| 691 | DirDiff diff = DirDifference(v->direction, v->rotation); |
| 692 | v->rotation = ChangeDir(v->rotation, diff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT); |
| 693 | /* Invalidate the sprite cache direction to force recalculation of viewport */ |
| 694 | v->sprite_cache.last_direction = INVALID_DIR; |
| 695 | v->UpdateViewport(true, true); |
| 696 | } |
| 697 | return; |
| 698 | } |
| 699 | |
| 700 | if (ShipMoveUpDownOnLock(v)) return; |
| 701 | |
| 702 | const uint number_of_steps = ShipAccelerate(v); |
| 703 | for (uint i = 0; i < number_of_steps; ++i) { |
| 704 | if (ShipMoveUpDownOnLock(v)) return; |
| 705 | |
| 706 | GetNewVehiclePosResult gp = GetNewVehiclePos(v); |
| 707 | if (v->state != TRACK_BIT_WORMHOLE) { |
| 708 | /* Not on a bridge */ |
| 709 | if (gp.old_tile == gp.new_tile) { |
| 710 | /* Staying in tile */ |
| 711 | if (v->IsInDepot()) { |
| 712 | gp.x = v->x_pos; |
| 713 | gp.y = v->y_pos; |
| 714 | } else { |
| 715 | /* Not inside depot */ |
| 716 | auto vets = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); |
| 717 | if (vets.Test(VehicleEnterTileState::CannotEnter)) return ReverseShip(v); |
| 718 | |
| 719 | /* A leave station order only needs one tick to get processed, so we can |
| 720 | * always skip ahead. */ |
| 721 | if (v->current_order.IsType(OT_LEAVESTATION)) { |
| 722 | v->current_order.Free(); |
| 723 | SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP); |
| 724 | /* Test if continuing forward would lead to a dead-end, moving into the dock. */ |
| 725 | const DiagDirection exitdir = VehicleExitDir(v->direction, v->state); |
| 726 | const TileIndex tile = TileAddByDiagDir(v->tile, exitdir); |
no test coverage detected