diff --git a/src/aircraft.h b/src/aircraft.h index 9e9d3106ed..6b16392c0c 100644 --- a/src/aircraft.h +++ b/src/aircraft.h @@ -111,6 +111,7 @@ struct Aircraft FINAL : public SpecializedVehicle { bool Tick(); void OnNewDay(); + void OnPeriodic(); uint Crash(bool flooded = false); TileIndex GetOrderStationLocation(StationID station); bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index af24164f86..9332a7f29c 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -483,10 +483,16 @@ void Aircraft::OnNewDay() if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); + AgeVehicle(this); +} + +void Aircraft::OnPeriodic() +{ + if (!this->IsNormalAircraft()) return; + CheckOrders(this); CheckVehicleBreakdown(this); - AgeVehicle(this); CheckIfAircraftNeedsService(this); if (this->running_ticks == 0) return; diff --git a/src/roadveh.h b/src/roadveh.h index 50d57d052a..7014061bc3 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -139,6 +139,7 @@ struct RoadVehicle FINAL : public GroundVehicle { bool IsInDepot() const { return this->state == RVSB_IN_DEPOT; } bool Tick(); void OnNewDay(); + void OnPeriodic(); uint Crash(bool flooded = false); Trackdir GetVehicleTrackdir() const; TileIndex GetOrderStationLocation(StationID station); diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 9ec01ab4b6..617165a828 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -2228,6 +2228,12 @@ void RoadVehicle::OnNewDay() if (!this->IsFrontEngine()) return; if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); +} + +void RoadVehicle::OnPeriodic() +{ + if (!this->IsFrontEngine()) return; + if (this->blocked_ctr == 0) CheckVehicleBreakdown(this); CheckIfRoadVehNeedsService(this); diff --git a/src/ship.h b/src/ship.h index 2993898bf9..9aacb5ddeb 100644 --- a/src/ship.h +++ b/src/ship.h @@ -55,6 +55,7 @@ struct Ship FINAL : public SpecializedVehicle { bool IsInDepot() const { return this->state == TRACK_BIT_DEPOT; } bool Tick(); void OnNewDay(); + void OnPeriodic(); Trackdir GetVehicleTrackdir() const; TileIndex GetOrderStationLocation(StationID station); bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 1f7914bf40..b2e6e65bae 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -248,9 +248,12 @@ void Ship::OnNewDay() if ((++this->day_counter & 7) == 0) { DecreaseVehicleValue(this); } + AgeVehicle(this); +} +void Ship::OnPeriodic() +{ CheckVehicleBreakdown(this); - AgeVehicle(this); CheckIfShipNeedsService(this); CheckOrders(this); diff --git a/src/train.h b/src/train.h index aeee416ce0..c50b52b9d3 100644 --- a/src/train.h +++ b/src/train.h @@ -170,6 +170,7 @@ struct Train FINAL : public GroundVehicle { bool IsInDepot() const { return this->track == TRACK_BIT_DEPOT; } bool Tick(); void OnNewDay(); + void OnPeriodic(); uint Crash(bool flooded = false); Money CalculateCurrentOverallValue() const; Trackdir GetVehicleTrackdir() const; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 03f316e057..f2511c0378 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -6598,7 +6598,10 @@ void Train::OnNewDay() AgeVehicle(this); if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); +} +void Train::OnPeriodic() +{ if (this->IsFrontEngine()) { CheckIfTrainNeedsService(this); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a62ae71e1d..25b1503c92 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1245,6 +1245,9 @@ template void CallVehicleOnNewDay(Vehicle *v) { T::From(v)->T::OnNewDay(); + + /* Vehicle::OnPeriodic is decoupled from Vehicle::OnNewDay at day lengths >= 8 */ + if (_settings_game.economy.day_length_factor < 8) T::From(v)->T::OnPeriodic(); } /** @@ -1460,6 +1463,38 @@ void CallVehicleTicks() if (_tick_skip_counter == 0) RunVehicleDayProc(); + if (_settings_game.economy.day_length_factor >= 8 && _game_mode == GM_NORMAL) { + /* + * Vehicle::OnPeriodic is decoupled from Vehicle::OnNewDay at day lengths >= 8 + * Use a fixed interval of 512 ticks (unscaled) instead + */ + + Vehicle *v = nullptr; + SCOPE_INFO_FMT([&v], "CallVehicleTicks -> OnPeriodic: %s", scope_dumper().VehicleInfo(v)); + for (size_t i = _scaled_tick_counter & 0x1FF; i < Vehicle::GetPoolSize(); i += 0x200) { + v = Vehicle::Get(i); + if (v == nullptr) continue; + + /* This is called once per day for each vehicle, but not in the first tick of the day */ + switch (v->type) { + case VEH_TRAIN: + Train::From(v)->Train::OnPeriodic(); + break; + case VEH_ROAD: + RoadVehicle::From(v)->RoadVehicle::OnPeriodic(); + break; + case VEH_SHIP: + Ship::From(v)->Ship::OnPeriodic(); + break; + case VEH_AIRCRAFT: + Aircraft::From(v)->Aircraft::OnPeriodic(); + break; + default: + break; + } + } + } + { PerformanceMeasurer framerate(PFE_GL_ECONOMY); Station *si_st = nullptr; diff --git a/src/vehicle_base.h b/src/vehicle_base.h index eedfe3f27b..dec317b7a1 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -615,6 +615,12 @@ public: */ virtual void OnNewDay() {}; + /** + * Calls the periodic handler of the vehicle + * OnPeriodic is decoupled from OnNewDay at day lengths >= 8 + */ + virtual void OnPeriodic() {}; + /** * Crash the (whole) vehicle chain. * @param flooded whether the cause of the crash is flooding or not.