Add whether the vehicle is non-front to the vehicle pool pointer tag

Add iteration filters which check this
pull/661/head
Jonathan G Rennison 3 months ago
parent 05e237f8d1
commit 93bf033107

@ -117,12 +117,17 @@ struct Pool : PoolBase {
Pool(const char *name); Pool(const char *name);
void CleanPool() override; void CleanPool() override;
inline PtrType GetRaw(size_t index) inline PtrType &GetRawRef(size_t index)
{ {
dbg_assert_msg(index < this->first_unused, "index: " PRINTF_SIZE ", first_unused: " PRINTF_SIZE ", name: %s", index, this->first_unused, this->name); dbg_assert_msg(index < this->first_unused, "index: " PRINTF_SIZE ", first_unused: " PRINTF_SIZE ", name: %s", index, this->first_unused, this->name);
return this->data[index]; return this->data[index];
} }
inline PtrType GetRaw(size_t index)
{
return this->GetRawRef(index);
}
/** /**
* Returns Titem with given index * Returns Titem with given index
* @param index of item to get * @param index of item to get

@ -164,7 +164,7 @@ protected:
CompanyMask companies = 0; CompanyMask companies = 0;
int unitnumber_max[4] = { -1, -1, -1, -1 }; int unitnumber_max[4] = { -1, -1, -1, -1 };
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->type < 4 && this->show_types[v->type] && v->IsPrimaryVehicle()) { if (v->type < 4 && this->show_types[v->type] && v->IsPrimaryVehicle()) {
for(const Order *order : v->Orders()) { for(const Order *order : v->Orders()) {
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT)) if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT))

@ -368,7 +368,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
} }
n = RandomRange(n); // Choose one of them. n = RandomRange(n); // Choose one of them.
for (const RoadVehicle *u : RoadVehicle::Iterate()) { for (const RoadVehicle *u : RoadVehicle::IterateFrontOnly()) {
/* Find (n+1)-th road vehicle. */ /* Find (n+1)-th road vehicle. */
if (u->IsFrontEngine() && (n-- == 0)) { if (u->IsFrontEngine() && (n-- == 0)) {
if (u->crashed_ctr != 0 || !SetDisasterVehicleTargetingVehicle(u->index, v->index)) { if (u->crashed_ctr != 0 || !SetDisasterVehicleTargetingVehicle(u->index, v->index)) {

@ -236,7 +236,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
bool min_profit_first = true; bool min_profit_first = true;
uint num = 0; uint num = 0;
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->owner != owner) continue; if (v->owner != owner) continue;
if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) { if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) {
if (v->profit_last_year > 0) num++; // For the vehicle score only count profitable vehicles if (v->profit_last_year > 0) num++; // For the vehicle score only count profitable vehicles

@ -731,7 +731,7 @@ void SettingsDisableElrail(int32_t new_value)
} }
/* Fix the total power and acceleration for trains */ /* Fix the total power and acceleration for trains */
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
/* power and acceleration is cached only for front engines */ /* power and acceleration is cached only for front engines */
if (t->IsFrontEngine()) { if (t->IsFrontEngine()) {
t->ConsistChanged(CCF_TRACK); t->ConsistChanged(CCF_TRACK);

@ -220,7 +220,7 @@ uint16_t GroupStatistics::GetNumEngines(EngineID engine) const
g->statistics.ClearProfits(); g->statistics.ClearProfits();
} }
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) { if (v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) {
GroupStatistics::AddProfitLastYear(v); GroupStatistics::AddProfitLastYear(v);
if (v->age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedMinAge(v); if (v->age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedMinAge(v);
@ -333,7 +333,7 @@ void IterateDescendantsOfGroup(GroupID id_top, F func)
static void PropagateChildLiveryResetVehicleCache(const Group *g) static void PropagateChildLiveryResetVehicleCache(const Group *g)
{ {
/* Company colour data is indirectly cached. */ /* Company colour data is indirectly cached. */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle() && (v->group_id == g->index || IsGroupIDDescendantOfGroupID(v->group_id, g->index, g->owner))) { if (v->IsPrimaryVehicle() && (v->group_id == g->index || IsGroupIDDescendantOfGroupID(v->group_id, g->index, g->owner))) {
for (Vehicle *u = v; u != nullptr; u = u->Next()) { for (Vehicle *u = v; u != nullptr; u = u->Next()) {
u->colourmap = PAL_NONE; u->colourmap = PAL_NONE;
@ -823,7 +823,7 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
/* Find the first front engine which belong to the group id_g /* Find the first front engine which belong to the group id_g
* then add all shared vehicles of this front engine to the group id_g */ * then add all shared vehicles of this front engine to the group id_g */
for (const Vehicle *v : Vehicle::IterateType(type)) { for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (v->IsPrimaryVehicle()) { if (v->IsPrimaryVehicle()) {
if (v->group_id != id_g) continue; if (v->group_id != id_g) continue;
@ -860,7 +860,7 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
/* Find each Vehicle that belongs to the group old_g and add it to the default group */ /* Find each Vehicle that belongs to the group old_g and add it to the default group */
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) { if (v->IsPrimaryVehicle()) {
if (v->group_id != old_g) continue; if (v->group_id != old_g) continue;

@ -206,7 +206,7 @@ static void FixAllReservations()
{ {
/* if this function is called, we can safely assume that sharing of rails is being switched off */ /* if this function is called, we can safely assume that sharing of rails is being switched off */
assert(!_settings_game.economy.infrastructure_sharing[VEH_TRAIN]); assert(!_settings_game.economy.infrastructure_sharing[VEH_TRAIN]);
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue; if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
/* It might happen that the train reserved additional tracks, /* It might happen that the train reserved additional tracks,
* but FollowTrainReservation can't detect those because they are no longer reachable. * but FollowTrainReservation can't detect those because they are no longer reachable.
@ -254,9 +254,8 @@ bool CheckSharingChangePossible(VehicleType type, bool new_value)
}); });
StringID error_message = STR_NULL; StringID error_message = STR_NULL;
for (Vehicle *v : Vehicle::IterateType(type)) { for (Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (HasBit(v->subtype, GVSF_VIRTUAL)) continue; if (HasBit(v->subtype, GVSF_VIRTUAL)) continue;
if (v->Previous() != nullptr) continue;
/* Check vehicle positiion */ /* Check vehicle positiion */
if (!VehiclePositionIsAllowed(v)) { if (!VehiclePositionIsAllowed(v)) {
@ -280,7 +279,7 @@ bool CheckSharingChangePossible(VehicleType type, bool new_value)
} }
if (type == VEH_TRAIN && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) { if (type == VEH_TRAIN && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue; if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
/* It might happen that the train reserved additional tracks, /* It might happen that the train reserved additional tracks,
* but FollowTrainReservation can't detect those because they are no longer reachable. * but FollowTrainReservation can't detect those because they are no longer reachable.
@ -329,9 +328,9 @@ void HandleSharingCompanyDeletion(Owner owner)
Vehicle *si_v = nullptr; Vehicle *si_v = nullptr;
SCOPE_INFO_FMT([&si_v], "HandleSharingCompanyDeletion: veh: %s", scope_dumper().VehicleInfo(si_v)); SCOPE_INFO_FMT([&si_v], "HandleSharingCompanyDeletion: veh: %s", scope_dumper().VehicleInfo(si_v));
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v; si_v = v;
if (!IsCompanyBuildableVehicleType(v) || v->Previous() != nullptr) continue; if (!IsCompanyBuildableVehicleType(v)) continue;
/* vehicle position */ /* vehicle position */
if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) { if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
RemoveAndSellVehicle(v, v->owner != owner); RemoveAndSellVehicle(v, v->owner != owner);

@ -1759,7 +1759,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
memset(stats, 0, sizeof(*stats) * MAX_COMPANIES); memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
/* Go through all vehicles and count the type of vehicles */ /* Go through all vehicles and count the type of vehicles */
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle() || HasBit(v->subtype, GVSF_VIRTUAL)) continue; if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle() || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
byte type = 0; byte type = 0;
switch (v->type) { switch (v->type) {

@ -66,9 +66,9 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
void IntialiseOrderDestinationRefcountMap() void IntialiseOrderDestinationRefcountMap()
{ {
ClearOrderDestinationRefcountMap(); ClearOrderDestinationRefcountMap();
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v != v->FirstShared()) continue; if (v != v->FirstShared()) continue;
for(const Order *order : v->Orders()) { for (const Order *order : v->Orders()) {
if (order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT)) { if (order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT)) {
_order_destination_refcount_map[OrderDestinationRefcountMapKey(order->GetDestination(), v->owner, order->GetType(), v->type)]++; _order_destination_refcount_map[OrderDestinationRefcountMapKey(order->GetDestination(), v->owner, order->GetType(), v->type)]++;
} }
@ -2933,7 +2933,7 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool
*/ */
/* Go through all vehicles */ /* Go through all vehicles */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
Order *order = &v->current_order; Order *order = &v->current_order;
if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type && if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
(!hangar || v->type == VEH_AIRCRAFT) && order->GetDestination() == destination) { (!hangar || v->type == VEH_AIRCRAFT) && order->GetDestination() == destination) {
@ -3786,7 +3786,7 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1,
DestinationID to_dest = GB(p2, 0, 16); DestinationID to_dest = GB(p2, 0, 16);
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
for (Vehicle *v : Vehicle::IterateType(vehtype)) { for (Vehicle *v : Vehicle::IterateTypeFrontOnly(vehtype)) {
if (v->IsPrimaryVehicle() && CheckOwnership(v->owner).Succeeded() && VehicleCargoFilter(v, cargo_filter)) { if (v->IsPrimaryVehicle() && CheckOwnership(v->owner).Succeeded() && VehicleCargoFilter(v, cargo_filter)) {
int index = 0; int index = 0;
bool changed = false; bool changed = false;

@ -203,7 +203,7 @@ bool RoadVehiclesAreBuilt()
*/ */
bool RoadVehiclesExistOutsideDepots() bool RoadVehiclesExistOutsideDepots()
{ {
for (const RoadVehicle *rv : RoadVehicle::Iterate()) { for (const RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine() && !rv->IsChainInDepot()) return true; if (rv->IsFrontEngine() && !rv->IsChainInDepot()) return true;
} }
return false; return false;

@ -308,10 +308,8 @@ static void InitializeWindowsAndCaches()
it->tile = t->xy; it->tile = t->xy;
} }
} }
for (RoadVehicle *rv : RoadVehicle::Iterate()) { for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine()) { rv->CargoChanged();
rv->CargoChanged();
}
} }
RecomputePrices(); RecomputePrices();
@ -1735,7 +1733,7 @@ bool AfterLoadGame()
} }
} }
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK); if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK);
} }
@ -2370,8 +2368,8 @@ bool AfterLoadGame()
GroupStatistics::UpdateAfterLoad(); // Ensure statistics pool is initialised before trying to delete vehicles GroupStatistics::UpdateAfterLoad(); // Ensure statistics pool is initialised before trying to delete vehicles
/* Remove all trams from savegames without tram support. /* Remove all trams from savegames without tram support.
* There would be trams without tram track under causing crashes sooner or later. */ * There would be trams without tram track under causing crashes sooner or later. */
for (RoadVehicle *v : RoadVehicle::Iterate()) { for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (v->First() == v && HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) { if (HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) {
ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, WL_CRITICAL); ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, WL_CRITICAL);
delete v; delete v;
} }
@ -2466,8 +2464,8 @@ bool AfterLoadGame()
/* Reserve all tracks trains are currently on. */ /* Reserve all tracks trains are currently on. */
if (IsSavegameVersionBefore(SLV_101)) { if (IsSavegameVersionBefore(SLV_101)) {
for (const Train *t : Train::Iterate()) { for (const Train *t : Train::IterateFrontOnly()) {
if (t->First() == t) t->ReserveTrackUnderConsist(); t->ReserveTrackUnderConsist();
} }
} }
@ -3196,7 +3194,7 @@ bool AfterLoadGame()
} }
/* Fill Vehicle::cur_real_order_index */ /* Fill Vehicle::cur_real_order_index */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle()) continue; if (!v->IsPrimaryVehicle()) continue;
/* Older versions are less strict with indices being in range and fix them on the fly */ /* Older versions are less strict with indices being in range and fix them on the fly */
@ -3501,7 +3499,7 @@ bool AfterLoadGame()
* So, make articulated parts catch up. */ * So, make articulated parts catch up. */
bool roadside = _settings_game.vehicle.road_side == 1; bool roadside = _settings_game.vehicle.road_side == 1;
std::vector<uint> skip_frames; std::vector<uint> skip_frames;
for (RoadVehicle *v : RoadVehicle::Iterate()) { for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (!v->IsFrontEngine()) continue; if (!v->IsFrontEngine()) continue;
skip_frames.clear(); skip_frames.clear();
TileIndex prev_tile = v->tile; TileIndex prev_tile = v->tile;
@ -3706,7 +3704,7 @@ bool AfterLoadGame()
} }
if (!IsSavegameVersionBefore(SLV_DEPOT_UNBUNCHING)) { if (!IsSavegameVersionBefore(SLV_DEPOT_UNBUNCHING)) {
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->unbunch_state != nullptr) { if (v->unbunch_state != nullptr) {
if (v->unbunch_state->depot_unbunching_last_departure > 0) { if (v->unbunch_state->depot_unbunching_last_departure > 0) {
v->unbunch_state->depot_unbunching_last_departure += _state_ticks.base() - _tick_counter; v->unbunch_state->depot_unbunching_last_departure += _state_ticks.base() - _tick_counter;
@ -4217,7 +4215,7 @@ bool AfterLoadGame()
} }
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 5) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) { if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 5) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) { if (t->lookahead != nullptr) {
t->lookahead->SetNextExtendPosition(); t->lookahead->SetNextExtendPosition();
} }
@ -4225,7 +4223,7 @@ bool AfterLoadGame()
} }
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 6) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) { if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 6) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) { if (t->lookahead != nullptr) {
t->lookahead->cached_zpos = t->CalculateOverallZPos(); t->lookahead->cached_zpos = t->CalculateOverallZPos();
t->lookahead->zpos_refresh_remaining = t->GetZPosCacheUpdateInterval(); t->lookahead->zpos_refresh_remaining = t->GetZPosCacheUpdateInterval();
@ -4366,7 +4364,7 @@ bool AfterLoadGame()
} }
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 9) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) { if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 9) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) { if (t->lookahead != nullptr) {
t->lookahead->lookahead_end_position = t->lookahead->reservation_end_position + 1; t->lookahead->lookahead_end_position = t->lookahead->reservation_end_position + 1;
} }

@ -180,7 +180,7 @@
Money profit = 0; Money profit = 0;
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->group_id != group_id) continue; if (v->group_id != group_id) continue;
if (!v->IsPrimaryVehicle()) continue; if (!v->IsPrimaryVehicle()) continue;
@ -204,7 +204,7 @@
uint32_t occupancy = 0; uint32_t occupancy = 0;
uint32_t vehicle_count = 0; uint32_t vehicle_count = 0;
for (const Vehicle *v : Vehicle::Iterate()) { for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->group_id != group_id) continue; if (v->group_id != group_id) continue;
if (!v->IsPrimaryVehicle()) continue; if (!v->IsPrimaryVehicle()) continue;

@ -1141,7 +1141,7 @@ static void StationSpreadChanged(int32_t new_value)
static void UpdateConsists(int32_t new_value) static void UpdateConsists(int32_t new_value)
{ {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
/* Update the consist of all trains so the maximum speed is set correctly. */ /* Update the consist of all trains so the maximum speed is set correctly. */
if (t->IsFrontEngine() || t->IsFreeWagon()) { if (t->IsFrontEngine() || t->IsFreeWagon()) {
t->ConsistChanged(CCF_TRACK); t->ConsistChanged(CCF_TRACK);
@ -1196,7 +1196,7 @@ static void UpdateAllServiceInterval(int32_t new_value)
if (update_vehicles) { if (update_vehicles) {
const Company *c = Company::Get(_current_company); const Company *c = Company::Get(_current_company);
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) {
v->SetServiceInterval(CompanyServiceInterval(c, v->type)); v->SetServiceInterval(CompanyServiceInterval(c, v->type));
v->SetServiceIntervalIsPercent(new_value != 0); v->SetServiceIntervalIsPercent(new_value != 0);
@ -1224,7 +1224,7 @@ static bool CanUpdateServiceInterval(VehicleType type, int32_t &new_value)
static void UpdateServiceInterval(VehicleType type, int32_t new_value) static void UpdateServiceInterval(VehicleType type, int32_t new_value)
{ {
if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) { if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) {
for (Vehicle *v : Vehicle::IterateType(type)) { for (Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) { if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) {
v->SetServiceInterval(new_value); v->SetServiceInterval(new_value);
} }
@ -1330,7 +1330,7 @@ static void ChangeMinutesPerYear(int32_t new_value)
static void TrainAccelerationModelChanged(int32_t new_value) static void TrainAccelerationModelChanged(int32_t new_value)
{ {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine()) { if (t->IsFrontEngine()) {
t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit(); t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit();
t->UpdateAcceleration(); t->UpdateAcceleration();
@ -1406,13 +1406,13 @@ static void TrainBrakingModelChanged(int32_t new_value)
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur)); SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
extern bool _long_reserve_disabled; extern bool _long_reserve_disabled;
_long_reserve_disabled = true; _long_reserve_disabled = true;
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
v_cur = v; v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue; if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, true, HasStationTileRail(v->tile)); TryPathReserve(v, true, HasStationTileRail(v->tile));
} }
_long_reserve_disabled = false; _long_reserve_disabled = false;
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
v_cur = v; v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue; if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, true, HasStationTileRail(v->tile)); TryPathReserve(v, true, HasStationTileRail(v->tile));
@ -1421,7 +1421,7 @@ static void TrainBrakingModelChanged(int32_t new_value)
} else if (new_value == TBM_ORIGINAL && (_game_mode == GM_NORMAL || _game_mode == GM_EDITOR)) { } else if (new_value == TBM_ORIGINAL && (_game_mode == GM_NORMAL || _game_mode == GM_EDITOR)) {
Train *v_cur = nullptr; Train *v_cur = nullptr;
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur)); SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
v_cur = v; v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) { if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) {
v->lookahead.reset(); v->lookahead.reset();
@ -1451,7 +1451,7 @@ static void TrainBrakingModelChanged(int32_t new_value)
*/ */
static void TrainSlopeSteepnessChanged(int32_t new_value) static void TrainSlopeSteepnessChanged(int32_t new_value)
{ {
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine()) { if (t->IsFrontEngine()) {
t->CargoChanged(); t->CargoChanged();
if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY); if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY);
@ -1466,17 +1466,13 @@ static void TrainSlopeSteepnessChanged(int32_t new_value)
static void RoadVehAccelerationModelChanged(int32_t new_value) static void RoadVehAccelerationModelChanged(int32_t new_value)
{ {
if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) { if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) {
for (RoadVehicle *rv : RoadVehicle::Iterate()) { for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine()) { rv->CargoChanged();
rv->CargoChanged();
}
} }
} }
if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL || !_settings_game.vehicle.improved_breakdowns) { if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL || !_settings_game.vehicle.improved_breakdowns) {
for (RoadVehicle *rv : RoadVehicle::Iterate()) { for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine()) { rv->breakdown_chance_factor = 128;
rv->breakdown_chance_factor = 128;
}
} }
} }
@ -1493,8 +1489,8 @@ static void RoadVehAccelerationModelChanged(int32_t new_value)
*/ */
static void RoadVehSlopeSteepnessChanged(int32_t new_value) static void RoadVehSlopeSteepnessChanged(int32_t new_value)
{ {
for (RoadVehicle *rv : RoadVehicle::Iterate()) { for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine()) rv->CargoChanged(); rv->CargoChanged();
} }
} }
@ -2022,8 +2018,8 @@ static void ImprovedBreakdownsSettingChanged(int32_t new_value)
{ {
if (!_settings_game.vehicle.improved_breakdowns) return; if (!_settings_game.vehicle.improved_breakdowns) return;
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
switch(v->type) { switch (v->type) {
case VEH_TRAIN: case VEH_TRAIN:
if (v->IsFrontEngine()) { if (v->IsFrontEngine()) {
v->breakdown_chance_factor = 128; v->breakdown_chance_factor = 128;

@ -273,6 +273,9 @@ void AfterLoadVehicles(bool part_of_load)
/* Reinstate the previous pointer */ /* Reinstate the previous pointer */
if (v->Next() != nullptr) { if (v->Next() != nullptr) {
v->Next()->previous = v; v->Next()->previous = v;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(v->Next()->index), true);
#endif
if (v->type == VEH_TRAIN && (HasBit(v->subtype, GVSF_VIRTUAL) != HasBit(v->Next()->subtype, GVSF_VIRTUAL))) { if (v->type == VEH_TRAIN && (HasBit(v->subtype, GVSF_VIRTUAL) != HasBit(v->Next()->subtype, GVSF_VIRTUAL))) {
SlErrorCorrupt("Mixed virtual/non-virtual train consist"); SlErrorCorrupt("Mixed virtual/non-virtual train consist");
} }
@ -387,7 +390,7 @@ void AfterLoadVehicles(bool part_of_load)
if (IsSavegameVersionBefore(SLV_180)) { if (IsSavegameVersionBefore(SLV_180)) {
/* Set service interval flags */ /* Set service interval flags */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v; si_v = v;
if (!v->IsPrimaryVehicle()) continue; if (!v->IsPrimaryVehicle()) continue;
@ -429,7 +432,7 @@ void AfterLoadVehicles(bool part_of_load)
CheckValidVehicles(); CheckValidVehicles();
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v; si_v = v;
assert(v->first != nullptr); assert(v->first != nullptr);
@ -595,7 +598,7 @@ void FixupTrainLengths()
{ {
/* Vehicle center was moved from 4 units behind the front to half the length /* Vehicle center was moved from 4 units behind the front to half the length
* behind the front. Move vehicles so they end up on the same spot. */ * behind the front. Move vehicles so they end up on the same spot. */
for (Train *v : Train::Iterate()) { for (Train *v : Train::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) { if (v->IsPrimaryVehicle()) {
/* The vehicle center is now more to the front depending on vehicle length, /* The vehicle center is now more to the front depending on vehicle length,
* so we need to move all vehicles forward to cover the difference to the * so we need to move all vehicles forward to cover the difference to the
@ -1622,7 +1625,7 @@ const SaveLoadTable GetVehicleUnbunchStateDescription()
void Save_VUBS() void Save_VUBS()
{ {
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->unbunch_state != nullptr) { if (v->unbunch_state != nullptr) {
SlSetArrayIndex(v->index); SlSetArrayIndex(v->index);
SlObject(v->unbunch_state.get(), GetVehicleUnbunchStateDescription()); SlObject(v->unbunch_state.get(), GetVehicleUnbunchStateDescription());

@ -2456,9 +2456,8 @@ CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags, int replacement_
delete cur_stop; delete cur_stop;
/* Make sure no vehicle is going to the old roadstop */ /* Make sure no vehicle is going to the old roadstop */
for (RoadVehicle *v : RoadVehicle::Iterate()) { for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) && if (v->current_order.IsType(OT_GOTO_STATION) && v->dest_tile == tile) {
v->dest_tile == tile) {
v->SetDestTile(v->GetOrderStationLocation(st->index)); v->SetDestTile(v->GetOrderStationLocation(st->index));
} }
} }
@ -3236,9 +3235,7 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
ClearDockingTilesCheckingNeighbours(tile1); ClearDockingTilesCheckingNeighbours(tile1);
ClearDockingTilesCheckingNeighbours(tile2); ClearDockingTilesCheckingNeighbours(tile2);
for (Ship *s : Ship::Iterate()) { for (Ship *s : Ship::IterateFrontOnly()) {
if (!s->IsPrimaryVehicle()) continue;
/* Find all ships going to our dock. */ /* Find all ships going to our dock. */
if (s->current_order.GetDestination() != st->index) { if (s->current_order.GetDestination() != st->index) {
continue; continue;

@ -204,7 +204,7 @@ static void MarkTrainsInGroupAsPendingTemplateReplacement(GroupID gid, const Tem
std::sort(groups.begin(), groups.end()); std::sort(groups.begin(), groups.end());
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue; if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue;
if (std::binary_search(groups.begin(), groups.end(), t->group_id)) { if (std::binary_search(groups.begin(), groups.end(), t->group_id)) {
@ -217,7 +217,7 @@ void MarkTrainsUsingTemplateAsPendingTemplateReplacement(const TemplateVehicle *
{ {
Owner owner = tv->owner; Owner owner = tv->owner;
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue; if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue;
if (GetTemplateIDByGroupIDRecursive(t->group_id) == tv->index) { if (GetTemplateIDByGroupIDRecursive(t->group_id) == tv->index) {

@ -327,7 +327,7 @@ uint CountsTrainsNeedingTemplateReplacement(GroupID g_id, const TemplateVehicle
uint count = 0; uint count = 0;
if (!tv) return count; if (!tv) return count;
for (Train *t : Train::Iterate()) { for (Train *t : Train::IterateFrontOnly()) {
if (t->IsPrimaryVehicle() && t->group_id == g_id && TrainTemplateDifference(t, tv) != TBTRDF_NONE) { if (t->IsPrimaryVehicle() && t->group_id == g_id && TrainTemplateDifference(t, tv) != TBTRDF_NONE) {
count++; count++;
} }

@ -170,8 +170,8 @@ void CheckTrainsLengths()
{ {
bool first = true; bool first = true;
for (const Train *v : Train::Iterate()) { for (const Train *v : Train::IterateFrontOnly()) {
if (v->First() == v && !(v->vehstatus & VS_CRASHED) && !v->IsVirtual()) { if (!(v->vehstatus & VS_CRASHED) && !v->IsVirtual()) {
for (const Train *u = v, *w = v->Next(); w != nullptr; u = w, w = w->Next()) { for (const Train *u = v, *w = v->Next(); w != nullptr; u = w, w = w->Next()) {
if (u->track != TRACK_BIT_DEPOT) { if (u->track != TRACK_BIT_DEPOT) {
if ((w->track != TRACK_BIT_DEPOT && if ((w->track != TRACK_BIT_DEPOT &&
@ -1503,7 +1503,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
CheckConsistencyOfArticulatedVehicle(v); CheckConsistencyOfArticulatedVehicle(v);
/* Try to connect the vehicle to one of free chains of wagons. */ /* Try to connect the vehicle to one of free chains of wagons. */
for (Train *w : Train::Iterate()) { for (Train *w : Train::IterateFrontOnly()) {
if (w->tile == tile && ///< Same depot if (w->tile == tile && ///< Same depot
w->IsFreeWagon() && ///< A free wagon chain w->IsFreeWagon() && ///< A free wagon chain
w->engine_type == e->index && ///< Same type w->engine_type == e->index && ///< Same type
@ -1527,7 +1527,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
void NormalizeTrainVehInDepot(const Train *u) void NormalizeTrainVehInDepot(const Train *u)
{ {
assert(u->IsEngine()); assert(u->IsEngine());
for (const Train *v : Train::Iterate()) { for (const Train *v : Train::IterateFrontOnly()) {
if (v->IsFreeWagon() && v->tile == u->tile && if (v->IsFreeWagon() && v->tile == u->tile &&
v->track == TRACK_BIT_DEPOT && v->track == TRACK_BIT_DEPOT &&
v->owner == u->owner && v->owner == u->owner &&
@ -1674,7 +1674,7 @@ static Train *FindGoodVehiclePos(const Train *src)
EngineID eng = src->engine_type; EngineID eng = src->engine_type;
TileIndex tile = src->tile; TileIndex tile = src->tile;
for (Train *dst : Train::Iterate()) { for (Train *dst : Train::IterateFrontOnly()) {
if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED) && dst->owner == src->owner && !dst->IsVirtual()) { if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED) && dst->owner == src->owner && !dst->IsVirtual()) {
/* check so all vehicles in the line have the same engine. */ /* check so all vehicles in the line have the same engine. */
Train *t = dst; Train *t = dst;

@ -36,7 +36,7 @@ void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32_t p1, uint32
/* find a locomotive in the depot. */ /* find a locomotive in the depot. */
const Vehicle *found = nullptr; const Vehicle *found = nullptr;
for (const Train *t : Train::Iterate()) { for (const Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine() && t->tile == tile && t->IsStoppedInDepot() && !t->IsVirtual()) { if (t->IsFrontEngine() && t->tile == tile && t->IsStoppedInDepot() && !t->IsVirtual()) {
if (found != nullptr) return; // must be exactly one. if (found != nullptr) return; // must be exactly one.
found = t; found = t;

@ -2861,7 +2861,7 @@ static bool ClickTile_TunnelBridge(TileIndex tile)
if (IsTunnelTile(tile)) { if (IsTunnelTile(tile)) {
int count = 0; int count = 0;
TileIndex tile_end = GetOtherTunnelBridgeEnd(tile); TileIndex tile_end = GetOtherTunnelBridgeEnd(tile);
for (const Train *t : Train::Iterate()) { for (const Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine()) continue; if (!t->IsFrontEngine()) continue;
if (tile == t->tile || tile_end == t->tile) { if (tile == t->tile || tile_end == t->tile) {
ShowVehicleViewWindow(t); ShowVehicleViewWindow(t);

@ -4317,6 +4317,9 @@ void Vehicle::SetNext(Vehicle *next)
v->first = this->next; v->first = this->next;
} }
this->next->previous = nullptr; this->next->previous = nullptr;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(this->next->index), false);
#endif
} }
this->next = next; this->next = next;
@ -4325,6 +4328,9 @@ void Vehicle::SetNext(Vehicle *next)
/* A new next vehicle. Update the first and previous pointers */ /* A new next vehicle. Update the first and previous pointers */
if (this->next->previous != nullptr) this->next->previous->next = nullptr; if (this->next->previous != nullptr) this->next->previous->next = nullptr;
this->next->previous = this; this->next->previous = this;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(this->next->index), true);
#endif
for (Vehicle *v = this->next; v != nullptr; v = v->Next()) { for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
v->first = this->first; v->first = this->first;
} }
@ -4549,7 +4555,7 @@ char *Vehicle::DumpVehicleFlagsMultiline(char *b, const char *last, const char *
void VehiclesYearlyLoop() void VehiclesYearlyLoop()
{ {
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) { if (v->IsPrimaryVehicle()) {
/* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */ /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
Money profit = v->GetDisplayProfitThisYear(); Money profit = v->GetDisplayProfitThisYear();

@ -255,6 +255,9 @@ struct VehiclePoolOps {
static constexpr VehicleType DefaultItemParam() { return VEH_INVALID; } static constexpr VehicleType DefaultItemParam() { return VEH_INVALID; }
static constexpr VehicleType GetVehicleType(uintptr_t ptr) { return static_cast<VehicleType>(GB(ptr, 60, 3)); } static constexpr VehicleType GetVehicleType(uintptr_t ptr) { return static_cast<VehicleType>(GB(ptr, 60, 3)); }
static constexpr bool IsNonFrontVehiclePtr(uintptr_t ptr) { return HasBit(ptr, 63); }
static constexpr void SetIsNonFrontVehiclePtr(uintptr_t &ptr, bool non_front) { SB(ptr, 63, 1, non_front ? 1 : 0); }
}; };
typedef Pool<Vehicle, VehicleID, 512, 0xFF000, PT_NORMAL, false, true, VehiclePoolOps> VehiclePool; typedef Pool<Vehicle, VehicleID, 512, 0xFF000, PT_NORMAL, false, true, VehiclePoolOps> VehiclePool;
@ -1303,6 +1306,32 @@ public:
} }
}; };
struct VehicleFrontOnlyFilter {
bool operator() (size_t index)
{
#if OTTD_UPPER_TAGGED_PTR
return !VehiclePoolOps::IsNonFrontVehiclePtr(_vehicle_pool.GetRaw(index));
#else
return Vehicle::Get(index)->Previous() == nullptr;
#endif
}
};
struct VehicleFrontOnlyTypeFilter {
VehicleType vt;
bool operator() (size_t index)
{
#if OTTD_UPPER_TAGGED_PTR
uintptr_t vptr = _vehicle_pool.GetRaw(index);
return !VehiclePoolOps::IsNonFrontVehiclePtr(vptr) && VehiclePoolOps::GetVehicleType(vptr) == this->vt;
#else
const Vehicle *v = Vehicle::Get(index);
return v->type == this->vt && v->Previous() == nullptr;
#endif
}
};
/** /**
* Returns an iterable ensemble of all valid vehicles of the given type * Returns an iterable ensemble of all valid vehicles of the given type
* @param vt the VehicleType to filter * @param vt the VehicleType to filter
@ -1313,6 +1342,27 @@ public:
{ {
return Pool::IterateWrapperFiltered<Vehicle, VehicleTypeFilter>(from, VehicleTypeFilter{ vt }); return Pool::IterateWrapperFiltered<Vehicle, VehicleTypeFilter>(from, VehicleTypeFilter{ vt });
} }
/**
* Returns an iterable ensemble of all valid front vehicles (i.e. Previous() == nullptr)
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles
*/
static Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyFilter> IterateFrontOnly(size_t from = 0)
{
return Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyFilter>(from, VehicleFrontOnlyFilter{});
}
/**
* Returns an iterable ensemble of all valid front vehicles of the given type
* @param vt the VehicleType to filter
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles of the given type
*/
static Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyTypeFilter> IterateTypeFrontOnly(VehicleType vt, size_t from = 0)
{
return Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyTypeFilter>(from, VehicleFrontOnlyTypeFilter{ vt });
}
}; };
inline bool IsPointInViewportVehicleRedrawArea(const std::vector<Rect> &viewport_redraw_rects, const Point &pt) inline bool IsPointInViewportVehicleRedrawArea(const std::vector<Rect> &viewport_redraw_rects, const Point &pt)
@ -1608,6 +1658,16 @@ public:
* @return an iterable ensemble of all valid vehicles of type T * @return an iterable ensemble of all valid vehicles of type T
*/ */
static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); } static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); }
/**
* Returns an iterable ensemble of all valid front vehicles (i.e. Previous() == nullptr) of type T
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles of type T
*/
static Pool::IterateWrapperFiltered<T, VehicleFrontOnlyFilter> IterateFrontOnly(size_t from = 0)
{
return Pool::IterateWrapperFiltered<T, VehicleFrontOnlyFilter>(from, VehicleFrontOnlyFilter{});
}
}; };
/** Generates sequence of free UnitID numbers */ /** Generates sequence of free UnitID numbers */

@ -155,7 +155,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli
}; };
auto fill_all_vehicles = [&]() { auto fill_all_vehicles = [&]() {
for (const Vehicle *v : Vehicle::IterateType(vli.vtype)) { for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(vli.vtype)) {
if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->owner == vli.company && v->IsPrimaryVehicle()) { if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->owner == vli.company && v->IsPrimaryVehicle()) {
add_veh(v); add_veh(v);
} }
@ -184,7 +184,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli
case VL_GROUP_LIST: case VL_GROUP_LIST:
if (vli.index != ALL_GROUP) { if (vli.index != ALL_GROUP) {
for (const Vehicle *v : Vehicle::IterateType(vli.vtype)) { for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(vli.vtype)) {
if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->IsPrimaryVehicle() && if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->IsPrimaryVehicle() &&
v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) { v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) {
add_veh(v); add_veh(v);

Loading…
Cancel
Save