diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 55d71bf197..fba82f6be4 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -358,6 +358,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine * v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft); v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->build_year = u->build_year = _cur_year; v->sprite_seq.Set(SPR_IMG_QUERY); @@ -1669,6 +1670,7 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass * if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) { /* an excerpt of ServiceAircraft, without the invisibility stuff */ v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->breakdowns_since_last_service = 0; v->reliability = v->GetEngine()->reliability; SetWindowDirty(WC_VEHICLE_DETAILS, v->index); diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index ab8ead9a03..271f0c5a0c 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -475,6 +475,7 @@ void AddArticulatedParts(Vehicle *first) /* get common values from first engine */ v->owner = first->owner; v->date_of_last_service = first->date_of_last_service; + v->date_of_last_service_newgrf = first->date_of_last_service_newgrf; v->build_year = first->build_year; v->cargo_subtype = 0; diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 3a72de11cd..e7f20463d8 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -744,7 +744,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, } case 0x4B: // Long date of last service - return v->date_of_last_service; + return v->date_of_last_service_newgrf; case 0x4C: // Current maximum speed in NewGRF units if (!v->IsPrimaryVehicle()) return 0; @@ -927,8 +927,8 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, } return (variable - 0x80) == 0x10 ? ticks : GB(ticks, 8, 8); } - case 0x12: return ClampTo(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR); - case 0x13: return GB(ClampTo(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); + case 0x12: return ClampTo(v->date_of_last_service_newgrf - DAYS_TILL_ORIGINAL_BASE_YEAR); + case 0x13: return GB(ClampTo(v->date_of_last_service_newgrf - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); case 0x14: return v->GetServiceInterval(); case 0x15: return GB(v->GetServiceInterval(), 8, 8); case 0x16: return v->last_station_visited; diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 4bffca1b8d..8871cb6b2d 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -311,6 +311,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh); v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->build_year = _cur_year; v->sprite_seq.Set(SPR_IMG_QUERY); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index d2d1a0605f..c8ffdc2696 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -4222,6 +4222,13 @@ bool AfterLoadGame() GenerateSavegameId(); } + if (IsSavegameVersionBefore(SLV_NEWGRF_LAST_SERVICE) && SlXvIsFeatureMissing(XSLFI_NEWGRF_LAST_SERVICE)) { + /* Set service date provided to NewGRF. */ + for (Vehicle *v : Vehicle::Iterate()) { + v->date_of_last_service_newgrf = v->date_of_last_service; + } + } + InitializeRoadGUI(); /* This needs to be done after conversion. */ diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 2bf915b133..2bc2093149 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -138,6 +138,7 @@ public: SLE_CONDVAR(Vehicle, max_age, SLE_INT32, SLV_31, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLE_CONDVAR(Vehicle, date_of_last_service, SLE_INT32, SLV_31, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle, date_of_last_service_newgrf, SLE_INT32, SLV_NEWGRF_LAST_SERVICE, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SL_MIN_VERSION, SLV_31), SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U32 | SLE_VAR_U16, SLV_31, SLV_180), SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SLV_180, SL_MAX_VERSION), diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 984369c518..eb8409be0f 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -1161,6 +1161,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, V v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships); v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->build_year = _cur_year; v->sprite_seq.Set(SPR_IMG_QUERY); v->random_bits = Random(); diff --git a/src/sl/extended_ver_sl.cpp b/src/sl/extended_ver_sl.cpp index 6252a180ce..4451c91ad4 100644 --- a/src/sl/extended_ver_sl.cpp +++ b/src/sl/extended_ver_sl.cpp @@ -201,6 +201,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_EXTEND_VEHICLE_RANDOM, XSCF_NULL, 1, 1, "slv_extend_vehicle_random", nullptr, nullptr, nullptr }, { XSLFI_DISASTER_VEH_STATE, XSCF_NULL, 1, 1, "slv_disaster_veh_state", nullptr, nullptr, nullptr }, { XSLFI_SAVEGAME_ID, XSCF_NULL, 1, 1, "slv_savegame_id", nullptr, nullptr, nullptr }, + { XSLFI_NEWGRF_LAST_SERVICE, XSCF_NULL, 1, 1, "slv_newgrf_last_service", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/sl/extended_ver_sl.h b/src/sl/extended_ver_sl.h index 4749e2c932..2aa20b8ad0 100644 --- a/src/sl/extended_ver_sl.h +++ b/src/sl/extended_ver_sl.h @@ -153,6 +153,7 @@ enum SlXvFeatureIndex { XSLFI_EXTEND_VEHICLE_RANDOM, ///< See: SLV_EXTEND_VEHICLE_RANDOM (PR #10701) XSLFI_DISASTER_VEH_STATE, ///< See: SLV_DISASTER_VEH_STATE (PR #10798) XSLFI_SAVEGAME_ID, ///< See: SLV_SAVEGAME_ID (PR #10719) + XSLFI_NEWGRF_LAST_SERVICE, ///< See: SLV_NEWGRF_LAST_SERVICE (PR #11124) XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/sl/saveload_common.h b/src/sl/saveload_common.h index 6c81b6ab89..77241c0cf3 100644 --- a/src/sl/saveload_common.h +++ b/src/sl/saveload_common.h @@ -370,6 +370,7 @@ enum SaveLoadVersion : uint16 { SLV_INDUSTRY_CARGO_REORGANISE, ///< 315 PR#10853 Industry accepts/produced data reorganised. SLV_PERIODS_IN_TRANSIT_RENAME, ///< 316 PR#11112 Rename days in transit to (cargo) periods in transit. + SLV_NEWGRF_LAST_SERVICE, ///< 317 PR#11124 Added stable date_of_last_service to avoid NewGRF trouble. SL_MAX_VERSION, ///< Highest possible saveload version diff --git a/src/sl/vehicle_sl.cpp b/src/sl/vehicle_sl.cpp index 7990b3a976..2b07bbd2ab 100644 --- a/src/sl/vehicle_sl.cpp +++ b/src/sl/vehicle_sl.cpp @@ -757,6 +757,7 @@ SaveLoadTable GetVehicleDescription(VehicleType vt) SLE_CONDVAR(Vehicle, max_age, SLE_INT32, SLV_31, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, date_of_last_service, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLE_CONDVAR(Vehicle, date_of_last_service, SLE_INT32, SLV_31, SL_MAX_VERSION), + SLE_CONDVAR_X(Vehicle, date_of_last_service_newgrf, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_NEWGRF_LAST_SERVICE)), SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SL_MIN_VERSION, SLV_31), SLE_CONDVAR(Vehicle, service_interval, SLE_FILE_U32 | SLE_VAR_U16, SLV_31, SLV_180), SLE_CONDVAR(Vehicle, service_interval, SLE_UINT16, SLV_180, SL_MAX_VERSION), diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 7a846f620f..528da9f544 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1482,6 +1482,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const v->railtype = rvi->railtype; v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->build_year = _cur_year; v->sprite_seq.Set(SPR_IMG_QUERY); v->random_bits = Random(); @@ -1557,6 +1558,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v) u->reliability = v->reliability; u->reliability_spd_dec = v->reliability_spd_dec; u->date_of_last_service = v->date_of_last_service; + u->date_of_last_service_newgrf = v->date_of_last_service_newgrf; u->build_year = v->build_year; u->sprite_seq.Set(SPR_IMG_QUERY); u->random_bits = Random(); @@ -1626,6 +1628,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains); v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; v->build_year = _cur_year; v->sprite_seq.Set(SPR_IMG_QUERY); v->random_bits = Random(); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 32820df10f..4af7dd1611 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -207,6 +207,7 @@ void VehicleServiceInDepot(Vehicle *v) do { v->date_of_last_service = _date; + v->date_of_last_service_newgrf = _date; if (_settings_game.vehicle.pay_for_repair && v->breakdowns_since_last_service) { _vehicles_to_pay_repair.insert(v->index); } else { @@ -4587,6 +4588,8 @@ void ShiftVehicleDates(int interval) for (Vehicle *v : Vehicle::Iterate()) { v->date_of_last_service = std::max(v->date_of_last_service + interval, 0); } + /* date_of_last_service_newgrf is not updated here as it must stay stable + * for vehicles outside of a depot. */ } extern void VehicleDayLengthChanged(DateTicksScaled old_scaled_date_ticks, DateTicksScaled old_scaled_date_ticks_offset, uint8 old_day_length_factor) diff --git a/src/vehicle_base.h b/src/vehicle_base.h index c192abeb0d..1ef62c28cb 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -320,6 +320,7 @@ public: Date age; ///< Age in days Date max_age; ///< Maximum age Date date_of_last_service; ///< Last date the vehicle had a service at a depot. + Date date_of_last_service_newgrf; ///< Last date the vehicle had a service at a depot, unchanged by the date cheat to protect against unsafe NewGRF behavior. uint16 reliability; ///< Reliability. uint16 reliability_spd_dec; ///< Reliability decrease speed. byte breakdown_ctr; ///< Counter for managing breakdown events. @see Vehicle::HandleBreakdown