262 if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0; |
262 if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0; |
263 |
263 |
264 order = GetVehicleOrder(v, v->cur_order_index); |
264 order = GetVehicleOrder(v, v->cur_order_index); |
265 |
265 |
266 if (order == NULL) { |
266 if (order == NULL) { |
267 v->current_order.type = OT_NOTHING; |
267 v->current_order.Free(); |
268 v->current_order.flags = 0; |
|
269 v->dest_tile = 0; |
268 v->dest_tile = 0; |
270 return; |
269 return; |
271 } |
270 } |
272 |
271 |
273 if (order->type == v->current_order.type && |
272 if (order->type == v->current_order.type && |
445 v->index, |
444 v->index, |
446 0); |
445 0); |
447 } |
446 } |
448 } |
447 } |
449 |
448 |
450 typedef struct { |
449 struct PathFindShip { |
451 TileIndex skiptile; |
450 TileIndex skiptile; |
452 TileIndex dest_coords; |
451 TileIndex dest_coords; |
453 uint best_bird_dist; |
452 uint best_bird_dist; |
454 uint best_length; |
453 uint best_length; |
455 } PathFindShip; |
454 }; |
456 |
455 |
457 static bool ShipTrackFollower(TileIndex tile, PathFindShip *pfs, int track, uint length, byte *state) |
456 static bool ShipTrackFollower(TileIndex tile, PathFindShip *pfs, int track, uint length, byte *state) |
458 { |
457 { |
459 // Found dest? |
458 // Found dest? |
460 if (tile == pfs->dest_coords) { |
459 if (tile == pfs->dest_coords) { |
703 if (HASBIT(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
702 if (HASBIT(r, VETS_CANNOT_ENTER)) goto reverse_direction; |
704 |
703 |
705 /* A leave station order only needs one tick to get processed, so we can |
704 /* A leave station order only needs one tick to get processed, so we can |
706 * always skip ahead. */ |
705 * always skip ahead. */ |
707 if (v->current_order.type == OT_LEAVESTATION) { |
706 if (v->current_order.type == OT_LEAVESTATION) { |
708 v->current_order.type = OT_NOTHING; |
707 v->current_order.Free(); |
709 v->current_order.flags = 0; |
|
710 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
708 InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR); |
711 } else if (v->dest_tile != 0) { |
709 } else if (v->dest_tile != 0) { |
712 /* We have a target, let's see if we reached it... */ |
710 /* We have a target, let's see if we reached it... */ |
713 if (v->current_order.type == OT_GOTO_STATION && |
711 if (v->current_order.type == OT_GOTO_STATION && |
714 IsBuoyTile(v->dest_tile) && |
712 IsBuoyTile(v->dest_tile) && |
819 AgeShipCargo(v); |
817 AgeShipCargo(v); |
820 ShipController(v); |
818 ShipController(v); |
821 } |
819 } |
822 |
820 |
823 |
821 |
824 void ShipsYearlyLoop(void) |
822 void ShipsYearlyLoop() |
825 { |
823 { |
826 Vehicle *v; |
824 Vehicle *v; |
827 |
825 |
828 FOR_ALL_VEHICLES(v) { |
826 FOR_ALL_VEHICLES(v) { |
829 if (v->type == VEH_Ship) { |
827 if (v->type == VEH_SHIP) { |
830 v->profit_last_year = v->profit_this_year; |
828 v->profit_last_year = v->profit_this_year; |
831 v->profit_this_year = 0; |
829 v->profit_this_year = 0; |
832 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
830 InvalidateWindow(WC_VEHICLE_DETAILS, v->index); |
833 } |
831 } |
834 } |
832 } |
844 int32 value; |
842 int32 value; |
845 Vehicle *v; |
843 Vehicle *v; |
846 UnitID unit_num; |
844 UnitID unit_num; |
847 Engine *e; |
845 Engine *e; |
848 |
846 |
849 if (!IsEngineBuildable(p1, VEH_Ship, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE); |
847 if (!IsEngineBuildable(p1, VEH_SHIP, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE); |
850 |
848 |
851 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
849 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
852 |
850 |
853 value = EstimateShipCost(p1); |
851 value = EstimateShipCost(p1); |
854 if (flags & DC_QUERY_COST) return value; |
852 if (flags & DC_QUERY_COST) return value; |
857 * so we must check against cheaters no sooner than now. --pasky */ |
855 * so we must check against cheaters no sooner than now. --pasky */ |
858 if (!IsTileDepotType(tile, TRANSPORT_WATER)) return CMD_ERROR; |
856 if (!IsTileDepotType(tile, TRANSPORT_WATER)) return CMD_ERROR; |
859 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
857 if (!IsTileOwner(tile, _current_player)) return CMD_ERROR; |
860 |
858 |
861 v = AllocateVehicle(); |
859 v = AllocateVehicle(); |
862 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_Ship); |
860 unit_num = HASBIT(p2, 0) ? 0 : GetFreeUnitNumber(VEH_SHIP); |
863 |
861 |
864 if (v == NULL || unit_num > _patches.max_ships) |
862 if (v == NULL || unit_num > _patches.max_ships) |
865 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
863 return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); |
866 |
864 |
867 if (flags & DC_EXEC) { |
865 if (flags & DC_EXEC) { |
908 |
906 |
909 v->service_interval = _patches.servint_ships; |
907 v->service_interval = _patches.servint_ships; |
910 v->date_of_last_service = _date; |
908 v->date_of_last_service = _date; |
911 v->build_year = _cur_year; |
909 v->build_year = _cur_year; |
912 v->cur_image = 0x0E5E; |
910 v->cur_image = 0x0E5E; |
913 v->type = VEH_Ship; |
911 v->type = VEH_SHIP; |
914 v->random_bits = VehicleRandomBits(); |
912 v->random_bits = VehicleRandomBits(); |
915 |
913 |
916 v->vehicle_flags = 0; |
914 v->vehicle_flags = 0; |
917 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
915 if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE); |
918 |
916 |
920 |
918 |
921 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
919 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
922 RebuildVehicleLists(); |
920 RebuildVehicleLists(); |
923 InvalidateWindow(WC_COMPANY, v->owner); |
921 InvalidateWindow(WC_COMPANY, v->owner); |
924 if (IsLocalPlayer()) |
922 if (IsLocalPlayer()) |
925 InvalidateAutoreplaceWindow(VEH_Ship); // updates the replace Ship window |
923 InvalidateAutoreplaceWindow(VEH_SHIP); // updates the replace Ship window |
926 |
924 |
927 GetPlayer(_current_player)->num_engines[p1]++; |
925 GetPlayer(_current_player)->num_engines[p1]++; |
928 } |
926 } |
929 |
927 |
930 return value; |
928 return value; |
941 |
939 |
942 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
940 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
943 |
941 |
944 v = GetVehicle(p1); |
942 v = GetVehicle(p1); |
945 |
943 |
946 if (v->type != VEH_Ship || !CheckOwnership(v->owner)) return CMD_ERROR; |
944 if (v->type != VEH_SHIP || !CheckOwnership(v->owner)) return CMD_ERROR; |
947 |
945 |
948 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
946 SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES); |
949 |
947 |
950 if (!IsShipInDepotStopped(v)) { |
948 if (!IsShipInDepotStopped(v)) { |
951 return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); |
949 return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); |
975 |
973 |
976 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
974 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
977 |
975 |
978 v = GetVehicle(p1); |
976 v = GetVehicle(p1); |
979 |
977 |
980 if (v->type != VEH_Ship || !CheckOwnership(v->owner)) return CMD_ERROR; |
978 if (v->type != VEH_SHIP || !CheckOwnership(v->owner)) return CMD_ERROR; |
981 |
979 |
982 /* Check if this ship can be started/stopped. The callback will fail or |
980 /* Check if this ship can be started/stopped. The callback will fail or |
983 * return 0xFF if it can. */ |
981 * return 0xFF if it can. */ |
984 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v); |
982 callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v); |
985 if (callback != CALLBACK_FAILED && callback != 0xFF) { |
983 if (callback != CALLBACK_FAILED && callback != 0xFF) { |
1014 const Depot *dep; |
1012 const Depot *dep; |
1015 |
1013 |
1016 if (p2 & DEPOT_MASS_SEND) { |
1014 if (p2 & DEPOT_MASS_SEND) { |
1017 /* Mass goto depot requested */ |
1015 /* Mass goto depot requested */ |
1018 if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR; |
1016 if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR; |
1019 return SendAllVehiclesToDepot(VEH_Ship, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1); |
1017 return SendAllVehiclesToDepot(VEH_SHIP, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1); |
1020 } |
1018 } |
1021 |
1019 |
1022 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
1020 if (!IsValidVehicleID(p1)) return CMD_ERROR; |
1023 |
1021 |
1024 v = GetVehicle(p1); |
1022 v = GetVehicle(p1); |
1025 |
1023 |
1026 if (v->type != VEH_Ship || !CheckOwnership(v->owner)) return CMD_ERROR; |
1024 if (v->type != VEH_SHIP || !CheckOwnership(v->owner)) return CMD_ERROR; |
1027 |
1025 |
1028 if (v->vehstatus & VS_CRASHED) return CMD_ERROR; |
1026 if (v->vehstatus & VS_CRASHED) return CMD_ERROR; |
1029 |
1027 |
1030 if (IsShipInDepot(v)) return CMD_ERROR; |
1028 if (IsShipInDepot(v)) return CMD_ERROR; |
1031 |
1029 |