diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 1f5f986282..ae13bcd433 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -2099,8 +2099,6 @@ bool Aircraft::Tick() { if (!this->IsNormalAircraft()) return true; - PerformanceAccumulator framerate(PFE_GL_AIRCRAFT); - this->tick_counter++; if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 52e1e4ac58..020a72f4d0 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1643,8 +1643,6 @@ Money RoadVehicle::GetRunningCost() const bool RoadVehicle::Tick() { - PerformanceAccumulator framerate(PFE_GL_ROADVEHS); - this->tick_counter++; if (this->IsFrontEngine()) { diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 2e0186d714..cf9ebfe2f5 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -839,8 +839,6 @@ static void ShipController(Ship *v) bool Ship::Tick() { - PerformanceAccumulator framerate(PFE_GL_SHIPS); - if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; ShipController(this); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 544cd35ef9..a24d238a11 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -4097,8 +4097,6 @@ bool Train::Tick() this->tick_counter++; if (this->IsFrontEngine()) { - PerformanceAccumulator framerate(PFE_GL_TRAINS); - if (!(this->vehstatus & VS_STOPPED) || this->cur_speed > 0) this->running_ticks++; this->current_order_time++; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a383de7a44..e0628f5801 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "error.h" +#include "disaster_vehicle.h" #include "roadveh.h" #include "ship.h" #include "spritecache.h" @@ -950,6 +951,96 @@ static void RunVehicleDayProc() } } +static void SpecialVehicleTick(Vehicle *v) +{ + [[maybe_unused]] size_t vehicle_index = v->index; + + /* Vehicle could be deleted in this tick */ + if (!v->Tick()) { + assert(Vehicle::Get(vehicle_index) == nullptr); + return; + } + + assert(Vehicle::Get(vehicle_index) == v); +} + +static void CommonVehicleTick(Vehicle *v) +{ + [[maybe_unused]] size_t vehicle_index = v->index; + + /* Vehicle could be deleted in this tick */ + if (!v->Tick()) { + assert(Vehicle::Get(vehicle_index) == nullptr); + return; + } + + assert(Vehicle::Get(vehicle_index) == v); + + Vehicle *front = v->First(); + + if (v->vcache.cached_cargo_age_period != 0) { + v->cargo_age_counter = std::min(v->cargo_age_counter, v->vcache.cached_cargo_age_period); + if (--v->cargo_age_counter == 0) { + v->cargo.AgeCargo(); + v->cargo_age_counter = v->vcache.cached_cargo_age_period; + } + } + + /* Do not play any sound when crashed */ + if (front->vehstatus & VS_CRASHED) return; + + /* Do not play any sound when in depot or tunnel */ + if (v->vehstatus & VS_HIDDEN) return; + + /* Do not play any sound when stopped */ + if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) return; + + /* Check vehicle type specifics */ + switch (v->type) { + case VEH_TRAIN: + if (Train::From(v)->IsWagon()) return; + break; + + case VEH_ROAD: + if (!RoadVehicle::From(v)->IsFrontEngine()) return; + break; + + case VEH_AIRCRAFT: + if (!Aircraft::From(v)->IsNormalAircraft()) return; + break; + + default: + break; + } + + v->motion_counter += front->cur_speed; + /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */ + if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING); + + /* Play an alternating running sound every 16 ticks */ + if (GB(v->tick_counter, 0, 4) == 0) { + /* Play running sound when speed > 0 and not braking */ + bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING)); + PlayVehicleSound(v, running ? VSE_RUNNING_16 : VSE_STOPPED_16); + } +} + +template +static void IterateTickable(Pred pred) +{ + for (auto it = std::begin(T::tickable_vehicles), next_it = it; it != std::end(T::tickable_vehicles); it = next_it) { + ++next_it; + pred(it->second); + } +} + +template +static void IterateTickable(PerformanceElement pfe, Pred pred) +{ + PerformanceMeasurer framerate(pfe); + IterateTickable(pred); +} + void CallVehicleTicks() { _vehicles_to_autoreplace.clear(); @@ -960,81 +1051,14 @@ void CallVehicleTicks() PerformanceMeasurer framerate(PFE_GL_ECONOMY); for (Station *st : Station::Iterate()) LoadUnloadStation(st); } - PerformanceAccumulator::Reset(PFE_GL_TRAINS); - PerformanceAccumulator::Reset(PFE_GL_ROADVEHS); - PerformanceAccumulator::Reset(PFE_GL_SHIPS); - PerformanceAccumulator::Reset(PFE_GL_AIRCRAFT); - for (Vehicle *v : Vehicle::Iterate()) { - [[maybe_unused]] size_t vehicle_index = v->index; + IterateTickable(SpecialVehicleTick); + IterateTickable(SpecialVehicleTick); - /* Vehicle could be deleted in this tick */ - if (!v->Tick()) { - assert(Vehicle::Get(vehicle_index) == nullptr); - continue; - } - - assert(Vehicle::Get(vehicle_index) == v); - - switch (v->type) { - default: break; - - case VEH_TRAIN: - case VEH_ROAD: - case VEH_AIRCRAFT: - case VEH_SHIP: { - Vehicle *front = v->First(); - - if (v->vcache.cached_cargo_age_period != 0) { - v->cargo_age_counter = std::min(v->cargo_age_counter, v->vcache.cached_cargo_age_period); - if (--v->cargo_age_counter == 0) { - v->cargo.AgeCargo(); - v->cargo_age_counter = v->vcache.cached_cargo_age_period; - } - } - - /* Do not play any sound when crashed */ - if (front->vehstatus & VS_CRASHED) continue; - - /* Do not play any sound when in depot or tunnel */ - if (v->vehstatus & VS_HIDDEN) continue; - - /* Do not play any sound when stopped */ - if ((front->vehstatus & VS_STOPPED) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue; - - /* Check vehicle type specifics */ - switch (v->type) { - case VEH_TRAIN: - if (Train::From(v)->IsWagon()) continue; - break; - - case VEH_ROAD: - if (!RoadVehicle::From(v)->IsFrontEngine()) continue; - break; - - case VEH_AIRCRAFT: - if (!Aircraft::From(v)->IsNormalAircraft()) continue; - break; - - default: - break; - } - - v->motion_counter += front->cur_speed; - /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */ - if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING); - - /* Play an alternating running sound every 16 ticks */ - if (GB(v->tick_counter, 0, 4) == 0) { - /* Play running sound when speed > 0 and not braking */ - bool running = (front->cur_speed > 0) && !(front->vehstatus & (VS_STOPPED | VS_TRAIN_SLOWING)); - PlayVehicleSound(v, running ? VSE_RUNNING_16 : VSE_STOPPED_16); - } - - break; - } - } - } + IterateTickable(PFE_GL_TRAINS, CommonVehicleTick); + IterateTickable(PFE_GL_ROADVEHS, CommonVehicleTick); + IterateTickable(PFE_GL_SHIPS, CommonVehicleTick); + IterateTickable(PFE_GL_AIRCRAFT, CommonVehicleTick); Backup cur_company(_current_company, FILE_LINE); for (auto &it : _vehicles_to_autoreplace) { diff --git a/src/vehicle_base.h b/src/vehicle_base.h index b1ddea8a61..c85454d667 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -1062,6 +1062,9 @@ public: uint32_t GetDisplayMaxWeight() const; uint32_t GetDisplayMinPowerToWeight() const; + + virtual void AddTickable() {} + virtual void RemoveTickable() {} }; /** @@ -1080,6 +1083,12 @@ struct SpecializedVehicle : public Vehicle { inline SpecializedVehicle() : Vehicle(Type) { this->sprite_cache.sprite_seq.count = 1; + this->AddTickable(); + } + + inline ~SpecializedVehicle() + { + this->RemoveTickable(); } /** @@ -1259,6 +1268,21 @@ struct SpecializedVehicle : public Vehicle { * @return an iterable ensemble of all valid vehicles of type T */ static Pool::IterateWrapper Iterate(size_t from = 0) { return Pool::IterateWrapper(from); } + + /** + * List of tickable vehicles for this type. + */ + static inline std::map *> tickable_vehicles; + + void AddTickable() override + { + tickable_vehicles.insert(std::make_pair(this->index, this)); + } + + void RemoveTickable() override + { + tickable_vehicles.erase(this->index); + } }; /** Generates sequence of free UnitID numbers */