mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
5 Commits
ea2bed747b
...
2014af46e3
Author | SHA1 | Date |
---|---|---|
|
2014af46e3 | |
|
a8650c6b06 | |
|
b9eac1ee78 | |
|
329a2da122 | |
|
98430f99d1 |
|
@ -454,6 +454,7 @@ add_files(
|
|||
spritecache.cpp
|
||||
spritecache.h
|
||||
spritecache_internal.h
|
||||
spritecache_type.h
|
||||
station.cpp
|
||||
station_base.h
|
||||
station_cmd.cpp
|
||||
|
|
|
@ -117,12 +117,12 @@ static inline std::pair<CargoType, uint16_t> GetVehicleDefaultCapacity(EngineID
|
|||
static inline CargoTypes GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
|
||||
{
|
||||
const Engine *e = Engine::Get(engine);
|
||||
if (!e->CanCarryCargo()) return 0;
|
||||
if (!e->CanCarryCargo()) return {};
|
||||
|
||||
CargoTypes cargoes = e->info.refit_mask;
|
||||
|
||||
if (include_initial_cargo_type) {
|
||||
SetBit(cargoes, e->GetDefaultCargoType());
|
||||
cargoes.Set(e->GetDefaultCargoType());
|
||||
}
|
||||
|
||||
return cargoes;
|
||||
|
@ -165,11 +165,11 @@ CargoArray GetCapacityOfArticulatedParts(EngineID engine)
|
|||
*/
|
||||
CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
|
||||
{
|
||||
CargoTypes cargoes = 0;
|
||||
CargoTypes cargoes{};
|
||||
const Engine *e = Engine::Get(engine);
|
||||
|
||||
if (auto [cargo, cap] = GetVehicleDefaultCapacity(engine); IsValidCargoType(cargo) && cap > 0) {
|
||||
SetBit(cargoes, cargo);
|
||||
cargoes.Set(cargo);
|
||||
}
|
||||
|
||||
if (!e->IsGroundVehicle()) return cargoes;
|
||||
|
@ -181,7 +181,7 @@ CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
|
|||
if (artic_engine == EngineID::Invalid()) break;
|
||||
|
||||
if (auto [cargo, cap] = GetVehicleDefaultCapacity(artic_engine); IsValidCargoType(cargo) && cap > 0) {
|
||||
SetBit(cargoes, cargo);
|
||||
cargoes.Set(cargo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +224,7 @@ void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type,
|
|||
const Engine *e = Engine::Get(engine);
|
||||
CargoTypes veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type);
|
||||
*union_mask = veh_cargoes;
|
||||
*intersection_mask = (veh_cargoes != 0) ? veh_cargoes : ALL_CARGOTYPES;
|
||||
*intersection_mask = veh_cargoes.Any() ? veh_cargoes : ALL_CARGOTYPES;
|
||||
|
||||
if (!e->IsGroundVehicle()) return;
|
||||
if (!e->info.callback_mask.Test(VehicleCallbackMask::ArticEngine)) return;
|
||||
|
@ -234,8 +234,8 @@ void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type,
|
|||
if (artic_engine == EngineID::Invalid()) break;
|
||||
|
||||
veh_cargoes = GetAvailableVehicleCargoTypes(artic_engine, include_initial_cargo_type);
|
||||
*union_mask |= veh_cargoes;
|
||||
if (veh_cargoes != 0) *intersection_mask &= veh_cargoes;
|
||||
union_mask->Set(veh_cargoes);
|
||||
if (veh_cargoes.Any()) *intersection_mask = *intersection_mask & veh_cargoes;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,12 +261,12 @@ CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial
|
|||
*/
|
||||
CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoType *cargo_type)
|
||||
{
|
||||
CargoTypes cargoes = 0;
|
||||
CargoTypes cargoes{};
|
||||
CargoType first_cargo = INVALID_CARGO;
|
||||
|
||||
do {
|
||||
if (IsValidCargoType(v->cargo_type) && v->GetEngine()->CanCarryCargo()) {
|
||||
SetBit(cargoes, v->cargo_type);
|
||||
cargoes.Set(v->cargo_type);
|
||||
if (!IsValidCargoType(first_cargo)) first_cargo = v->cargo_type;
|
||||
if (first_cargo != v->cargo_type) {
|
||||
if (cargo_type != nullptr) {
|
||||
|
@ -299,24 +299,24 @@ void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
|
|||
GetArticulatedRefitMasks(v->engine_type, true, &purchase_refit_union, &purchase_refit_intersection);
|
||||
CargoArray purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type);
|
||||
|
||||
CargoTypes real_refit_union = 0;
|
||||
CargoTypes real_refit_union{};
|
||||
CargoTypes real_refit_intersection = ALL_CARGOTYPES;
|
||||
CargoTypes real_default_cargoes = 0;
|
||||
CargoTypes real_default_cargoes{};
|
||||
|
||||
do {
|
||||
CargoTypes refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true);
|
||||
real_refit_union |= refit_mask;
|
||||
if (refit_mask != 0) real_refit_intersection &= refit_mask;
|
||||
real_refit_union.Set(refit_mask);
|
||||
if (refit_mask.Any()) real_refit_intersection = real_refit_intersection & refit_mask;
|
||||
|
||||
assert(v->cargo_type < NUM_CARGO);
|
||||
if (v->cargo_cap > 0) SetBit(real_default_cargoes, v->cargo_type);
|
||||
if (v->cargo_cap > 0) real_default_cargoes.Set(v->cargo_type);
|
||||
|
||||
v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr;
|
||||
} while (v != nullptr);
|
||||
|
||||
/* Check whether the vehicle carries more cargoes than expected */
|
||||
bool carries_more = false;
|
||||
for (CargoType cargo_type : SetCargoBitIterator(real_default_cargoes)) {
|
||||
for (CargoType cargo_type : real_default_cargoes) {
|
||||
if (purchase_default_capacity[cargo_type] == 0) {
|
||||
carries_more = true;
|
||||
break;
|
||||
|
|
|
@ -47,7 +47,7 @@ static bool EnginesHaveCargoInCommon(EngineID engine_a, EngineID engine_b)
|
|||
{
|
||||
CargoTypes available_cargoes_a = GetUnionOfArticulatedRefitMasks(engine_a, true);
|
||||
CargoTypes available_cargoes_b = GetUnionOfArticulatedRefitMasks(engine_b, true);
|
||||
return (available_cargoes_a == 0 || available_cargoes_b == 0 || (available_cargoes_a & available_cargoes_b) != 0);
|
||||
return available_cargoes_a.None() || available_cargoes_b.None() || available_cargoes_a.Any(available_cargoes_b);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -189,8 +189,8 @@ static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_ty
|
|||
if (!o.IsRefit() || o.IsAutoRefit()) continue;
|
||||
CargoType cargo_type = o.GetRefitCargo();
|
||||
|
||||
if (!HasBit(union_refit_mask_a, cargo_type)) continue;
|
||||
if (!HasBit(union_refit_mask_b, cargo_type)) return false;
|
||||
if (!union_refit_mask_a.Test(cargo_type)) continue;
|
||||
if (!union_refit_mask_b.Test(cargo_type)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -213,7 +213,7 @@ static int GetIncompatibleRefitOrderIdForAutoreplace(const Vehicle *v, EngineID
|
|||
for (VehicleOrderID i = 0; i < orders->GetNumOrders(); i++) {
|
||||
const Order *o = orders->GetOrderAt(i);
|
||||
if (!o->IsRefit()) continue;
|
||||
if (!HasBit(union_refit_mask, o->GetRefitCargo())) return i;
|
||||
if (!union_refit_mask.Test(o->GetRefitCargo())) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
@ -233,11 +233,11 @@ static CargoType GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, boo
|
|||
CargoTypes available_cargo_types, union_mask;
|
||||
GetArticulatedRefitMasks(engine_type, true, &union_mask, &available_cargo_types);
|
||||
|
||||
if (union_mask == 0) return CARGO_NO_REFIT; // Don't try to refit an engine with no cargo capacity
|
||||
if (union_mask.None()) return CARGO_NO_REFIT; // Don't try to refit an engine with no cargo capacity
|
||||
|
||||
CargoType cargo_type;
|
||||
CargoTypes cargo_mask = GetCargoTypesOfArticulatedVehicle(v, &cargo_type);
|
||||
if (!HasAtMostOneBit(cargo_mask)) {
|
||||
if (!HasAtMostOneBit(cargo_mask.base())) {
|
||||
CargoTypes new_engine_default_cargoes = GetCargoTypesOfArticulatedParts(engine_type);
|
||||
if ((cargo_mask & new_engine_default_cargoes) == cargo_mask) {
|
||||
return CARGO_NO_REFIT; // engine_type is already a mixed cargo type which matches the incoming vehicle by default, no refit required
|
||||
|
@ -257,12 +257,12 @@ static CargoType GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, boo
|
|||
for (v = v->First(); v != nullptr; v = v->Next()) {
|
||||
if (!v->GetEngine()->CanCarryCargo()) continue;
|
||||
/* Now we found a cargo type being carried on the train and we will see if it is possible to carry to this one */
|
||||
if (HasBit(available_cargo_types, v->cargo_type)) return v->cargo_type;
|
||||
if (available_cargo_types.Test(v->cargo_type)) return v->cargo_type;
|
||||
}
|
||||
|
||||
return CARGO_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one
|
||||
} else {
|
||||
if (!HasBit(available_cargo_types, cargo_type)) return INVALID_CARGO; // We can't refit the vehicle to carry the cargo we want
|
||||
if (!available_cargo_types.Test(cargo_type)) return INVALID_CARGO; // We can't refit the vehicle to carry the cargo we want
|
||||
|
||||
if (part_of_chain && !VerifyAutoreplaceRefitForOrders(v, engine_type)) return INVALID_CARGO; // Some refit orders lose their effect
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ static bool CargoAndEngineFilter(const GUIEngineListItem *item, const CargoType
|
|||
return Engine::Get(item->engine_id)->GetPower() != 0;
|
||||
} else {
|
||||
CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(item->engine_id, true) & _standard_cargo_mask;
|
||||
return (cargo_type == CargoFilterCriteria::CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cargo_type));
|
||||
return (cargo_type == CargoFilterCriteria::CF_NONE ? refit_mask.None() : refit_mask.Test(cargo_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -557,7 +557,7 @@ static GUIEngineList::FilterFunction * const _engine_filter_funcs[] = {
|
|||
static uint GetCargoWeight(const CargoArray &cap, VehicleType vtype)
|
||||
{
|
||||
uint weight = 0;
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
if (cap[cargo] != 0) {
|
||||
if (vtype == VEH_TRAIN) {
|
||||
weight += CargoSpec::Get(cargo)->WeightOfNUnitsInTrain(cap[cargo]);
|
||||
|
@ -1261,10 +1261,10 @@ struct BuildVehicleWindow : Window {
|
|||
|
||||
StringID GetCargoFilterLabel(CargoType cargo_type) const
|
||||
{
|
||||
switch (cargo_type) {
|
||||
case CargoFilterCriteria::CF_ANY: return STR_PURCHASE_INFO_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_ENGINES: return STR_PURCHASE_INFO_ENGINES_ONLY;
|
||||
case CargoFilterCriteria::CF_NONE: return STR_PURCHASE_INFO_NONE;
|
||||
switch (cargo_type.base()) {
|
||||
case CargoFilterCriteria::CF_ANY.base(): return STR_PURCHASE_INFO_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_ENGINES.base(): return STR_PURCHASE_INFO_ENGINES_ONLY;
|
||||
case CargoFilterCriteria::CF_NONE.base(): return STR_PURCHASE_INFO_NONE;
|
||||
default: return CargoSpec::Get(cargo_type)->name;
|
||||
}
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@ struct BuildVehicleWindow : Window {
|
|||
{
|
||||
/* Set the last cargo filter criteria. */
|
||||
this->cargo_filter_criteria = _engine_sort_last_cargo_criteria[this->vehicle_type];
|
||||
if (this->cargo_filter_criteria < NUM_CARGO && !HasBit(_standard_cargo_mask, this->cargo_filter_criteria)) this->cargo_filter_criteria = CargoFilterCriteria::CF_ANY;
|
||||
if (this->cargo_filter_criteria < NUM_CARGO && !_standard_cargo_mask.Test(this->cargo_filter_criteria)) this->cargo_filter_criteria = CargoFilterCriteria::CF_ANY;
|
||||
|
||||
this->eng_list.SetFilterFuncs(_engine_filter_funcs);
|
||||
this->eng_list.SetFilterState(this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY);
|
||||
|
@ -1570,20 +1570,20 @@ struct BuildVehicleWindow : Window {
|
|||
DropDownList list;
|
||||
|
||||
/* Add item for disabling filtering. */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY.base()));
|
||||
/* Specific filters for trains. */
|
||||
if (this->vehicle_type == VEH_TRAIN) {
|
||||
/* Add item for locomotives only in case of trains. */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ENGINES), CargoFilterCriteria::CF_ENGINES));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ENGINES), CargoFilterCriteria::CF_ENGINES.base()));
|
||||
/* Add item for vehicles not carrying anything, e.g. train engines.
|
||||
* This could also be useful for eyecandy vehicles of other types, but is likely too confusing for joe, */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE.base()));
|
||||
}
|
||||
|
||||
/* Add cargos */
|
||||
Dimension d = GetLargestCargoIconSize();
|
||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index()));
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index().base()));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -1675,7 +1675,7 @@ struct BuildVehicleWindow : Window {
|
|||
break;
|
||||
|
||||
case WID_BV_CARGO_FILTER_DROPDOWN: // Select cargo filtering criteria dropdown menu
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->cargo_filter_criteria, widget);
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->cargo_filter_criteria.base(), widget);
|
||||
break;
|
||||
|
||||
case WID_BV_CONFIGURE_BADGES:
|
||||
|
@ -1884,7 +1884,7 @@ struct BuildVehicleWindow : Window {
|
|||
|
||||
case WID_BV_CARGO_FILTER_DROPDOWN: // Select a cargo filter criteria
|
||||
if (this->cargo_filter_criteria != index) {
|
||||
this->cargo_filter_criteria = index;
|
||||
this->cargo_filter_criteria = static_cast<CargoType>(index);
|
||||
_engine_sort_last_cargo_criteria[this->vehicle_type] = this->cargo_filter_criteria;
|
||||
/* deactivate filter if criteria is 'Show All', activate it otherwise */
|
||||
this->eng_list.SetFilterState(this->cargo_filter_criteria != CargoFilterCriteria::CF_ANY);
|
||||
|
|
|
@ -12,15 +12,19 @@
|
|||
|
||||
#include "core/enum_type.hpp"
|
||||
#include "core/strong_typedef_type.hpp"
|
||||
#include "core/strong_bitset_type.hpp"
|
||||
#include "core/convertible_through_base.hpp"
|
||||
|
||||
/** Globally unique label of a cargo type. */
|
||||
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongType::Compare>;
|
||||
|
||||
static constexpr uint NUM_ORIGINAL_CARGO = 12; ///< Original number of cargo types.
|
||||
static constexpr uint NUM_CARGO = 64; ///< Maximum number of cargo types in a game.
|
||||
|
||||
/**
|
||||
* Cargo slots to indicate a cargo type within a game.
|
||||
*/
|
||||
using CargoType = uint8_t;
|
||||
using CargoType = StrongType::Typedef<uint8_t, struct CargoTypeTag, StrongType::Compare, StrongType::Integer>;
|
||||
|
||||
/**
|
||||
* Available types of cargo
|
||||
|
@ -71,14 +75,11 @@ static constexpr CargoLabel CT_NONE = CT_PASSENGERS;
|
|||
|
||||
static constexpr CargoLabel CT_INVALID{UINT32_MAX}; ///< Invalid cargo type.
|
||||
|
||||
static const CargoType NUM_ORIGINAL_CARGO = 12; ///< Original number of cargo types.
|
||||
static const CargoType NUM_CARGO = 64; ///< Maximum number of cargo types in a game.
|
||||
|
||||
/* CARGO_AUTO_REFIT and CARGO_NO_REFIT are stored in save-games for refit-orders, so should not be changed. */
|
||||
static const CargoType CARGO_AUTO_REFIT = 0xFD; ///< Automatically choose cargo type when doing auto refitting.
|
||||
static const CargoType CARGO_NO_REFIT = 0xFE; ///< Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-renew).
|
||||
static constexpr CargoType CARGO_AUTO_REFIT{0xFD}; ///< Automatically choose cargo type when doing auto refitting.
|
||||
static constexpr CargoType CARGO_NO_REFIT{0xFE}; ///< Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-renew).
|
||||
|
||||
static const CargoType INVALID_CARGO = UINT8_MAX;
|
||||
static constexpr CargoType INVALID_CARGO{UINT8_MAX};
|
||||
|
||||
/** Mixed cargo types for definitions with cargo that can vary depending on climate. */
|
||||
enum MixedCargoType : uint8_t {
|
||||
|
@ -92,25 +93,25 @@ enum MixedCargoType : uint8_t {
|
|||
* These are used by user interface code only and must not be assigned to any entity. Not all values are valid for every UI filter.
|
||||
*/
|
||||
namespace CargoFilterCriteria {
|
||||
static constexpr CargoType CF_ANY = NUM_CARGO; ///< Show all items independent of carried cargo (i.e. no filtering)
|
||||
static constexpr CargoType CF_NONE = NUM_CARGO + 1; ///< Show only items which do not carry cargo (e.g. train engines)
|
||||
static constexpr CargoType CF_ENGINES = NUM_CARGO + 2; ///< Show only engines (for rail vehicles only)
|
||||
static constexpr CargoType CF_FREIGHT = NUM_CARGO + 3; ///< Show only vehicles which carry any freight (non-passenger) cargo
|
||||
static constexpr CargoType CF_ANY{NUM_CARGO}; ///< Show all items independent of carried cargo (i.e. no filtering)
|
||||
static constexpr CargoType CF_NONE{NUM_CARGO + 1}; ///< Show only items which do not carry cargo (e.g. train engines)
|
||||
static constexpr CargoType CF_ENGINES{NUM_CARGO + 2}; ///< Show only engines (for rail vehicles only)
|
||||
static constexpr CargoType CF_FREIGHT{NUM_CARGO + 3}; ///< Show only vehicles which carry any freight (non-passenger) cargo
|
||||
|
||||
static constexpr CargoType CF_NO_RATING = NUM_CARGO + 4; ///< Show items with no rating (station list)
|
||||
static constexpr CargoType CF_SELECT_ALL = NUM_CARGO + 5; ///< Select all items (station list)
|
||||
static constexpr CargoType CF_EXPAND_LIST = NUM_CARGO + 6; ///< Expand list to show all items (station list)
|
||||
static constexpr CargoType CF_NO_RATING{NUM_CARGO + 4}; ///< Show items with no rating (station list)
|
||||
static constexpr CargoType CF_SELECT_ALL{NUM_CARGO + 5}; ///< Select all items (station list)
|
||||
static constexpr CargoType CF_EXPAND_LIST{NUM_CARGO + 6}; ///< Expand list to show all items (station list)
|
||||
};
|
||||
|
||||
/** Test whether cargo type is not INVALID_CARGO */
|
||||
inline bool IsValidCargoType(CargoType cargo) { return cargo != INVALID_CARGO; }
|
||||
|
||||
typedef uint64_t CargoTypes;
|
||||
using CargoTypes = StrongBitSet<CargoType, uint64_t>;
|
||||
|
||||
static const CargoTypes ALL_CARGOTYPES = (CargoTypes)UINT64_MAX;
|
||||
static constexpr CargoTypes ALL_CARGOTYPES{UINT64_MAX};
|
||||
|
||||
/** Class for storing amounts of cargo */
|
||||
struct CargoArray : std::array<uint, NUM_CARGO> {
|
||||
struct CargoArray : TypedIndexContainer<std::array<uint, NUM_CARGO>, CargoType> {
|
||||
/**
|
||||
* Get the sum of all cargo amounts.
|
||||
* @return The sum.
|
||||
|
|
|
@ -63,7 +63,7 @@ inline CargoMonitorID EncodeCargoIndustryMonitor(CompanyID company, CargoType ct
|
|||
uint32_t ret = 0;
|
||||
SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, ind.base());
|
||||
SetBit(ret, CCB_IS_INDUSTRY_BIT);
|
||||
SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype);
|
||||
SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype.base());
|
||||
SB(ret, CCB_COMPANY_START, CCB_COMPANY_LENGTH, company.base());
|
||||
return ret;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ inline CargoMonitorID EncodeCargoTownMonitor(CompanyID company, CargoType ctype,
|
|||
|
||||
uint32_t ret = 0;
|
||||
SB(ret, CCB_TOWN_IND_NUMBER_START, CCB_TOWN_IND_NUMBER_LENGTH, town.base());
|
||||
SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype);
|
||||
SB(ret, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH, ctype.base());
|
||||
SB(ret, CCB_COMPANY_START, CCB_COMPANY_LENGTH, company.base());
|
||||
return ret;
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ inline CompanyID DecodeMonitorCompany(CargoMonitorID num)
|
|||
*/
|
||||
inline CargoType DecodeMonitorCargoType(CargoMonitorID num)
|
||||
{
|
||||
return GB(num, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH);
|
||||
return static_cast<CargoType>(GB(num, CCB_CARGO_TYPE_START, CCB_CARGO_TYPE_LENGTH));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "safeguards.h"
|
||||
|
||||
CargoSpec CargoSpec::array[NUM_CARGO];
|
||||
TypedIndexContainer<std::array<CargoSpec, NUM_CARGO>, CargoType> CargoSpec::array{};
|
||||
std::array<std::vector<const CargoSpec *>, NUM_TPE> CargoSpec::town_production_cargoes{};
|
||||
|
||||
/**
|
||||
|
@ -63,7 +63,7 @@ void SetupCargoForClimate(LandscapeType l)
|
|||
{
|
||||
assert(to_underlying(l) < std::size(_default_climate_cargo));
|
||||
|
||||
_cargo_mask = 0;
|
||||
_cargo_mask.Reset();
|
||||
_default_cargo_labels.clear();
|
||||
_climate_dependent_cargo_labels.fill(CT_INVALID);
|
||||
_climate_independent_cargo_labels.fill(CT_INVALID);
|
||||
|
@ -92,9 +92,9 @@ void SetupCargoForClimate(LandscapeType l)
|
|||
*insert = std::visit(visitor{}, cl);
|
||||
|
||||
if (insert->IsValid()) {
|
||||
SetBit(_cargo_mask, insert->Index());
|
||||
_cargo_mask.Set(insert->Index());
|
||||
_default_cargo_labels.push_back(insert->label);
|
||||
_climate_dependent_cargo_labels[insert->Index()] = insert->label;
|
||||
_climate_dependent_cargo_labels[insert->Index().base()] = insert->label;
|
||||
_climate_independent_cargo_labels[insert->bitnum] = insert->label;
|
||||
}
|
||||
++insert;
|
||||
|
@ -186,7 +186,7 @@ SpriteID CargoSpec::GetCargoIcon() const
|
|||
return sprite;
|
||||
}
|
||||
|
||||
std::array<uint8_t, NUM_CARGO> _sorted_cargo_types; ///< Sort order of cargoes by cargo type.
|
||||
TypedIndexContainer<std::array<uint8_t, NUM_CARGO>, CargoType> _sorted_cargo_types; ///< Sort order of cargoes by cargo type.
|
||||
std::vector<const CargoSpec *> _sorted_cargo_specs; ///< Cargo specifications sorted alphabetically by name.
|
||||
std::span<const CargoSpec *> _sorted_standard_cargo_specs; ///< Standard cargo specifications sorted alphabetically by name.
|
||||
|
||||
|
@ -238,14 +238,14 @@ void InitializeSortedCargoSpecs()
|
|||
}
|
||||
|
||||
/* Count the number of standard cargos and fill the mask. */
|
||||
_standard_cargo_mask = 0;
|
||||
_standard_cargo_mask.Reset();
|
||||
uint8_t nb_standard_cargo = 0;
|
||||
for (const auto &cargo : _sorted_cargo_specs) {
|
||||
assert(cargo->town_production_effect != INVALID_TPE);
|
||||
CargoSpec::town_production_cargoes[cargo->town_production_effect].push_back(cargo);
|
||||
if (cargo->classes.Test(CargoClass::Special)) break;
|
||||
nb_standard_cargo++;
|
||||
SetBit(_standard_cargo_mask, cargo->Index());
|
||||
_standard_cargo_mask.Set(cargo->Index());
|
||||
}
|
||||
|
||||
/* _sorted_standard_cargo_specs is a subset of _sorted_cargo_specs. */
|
||||
|
|
|
@ -107,7 +107,7 @@ struct CargoSpec {
|
|||
*/
|
||||
inline CargoType Index() const
|
||||
{
|
||||
return this - CargoSpec::array;
|
||||
return static_cast<CargoType>(this - CargoSpec::array.data());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +126,7 @@ struct CargoSpec {
|
|||
*/
|
||||
static inline size_t GetArraySize()
|
||||
{
|
||||
return lengthof(CargoSpec::array);
|
||||
return std::size(CargoSpec::array);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,9 +134,9 @@ struct CargoSpec {
|
|||
* @param index ID of cargo
|
||||
* @pre index is a valid cargo type
|
||||
*/
|
||||
static inline CargoSpec *Get(size_t index)
|
||||
static inline CargoSpec *Get(CargoType index)
|
||||
{
|
||||
assert(index < lengthof(CargoSpec::array));
|
||||
assert(index.base() < std::size(CargoSpec::array));
|
||||
return &CargoSpec::array[index];
|
||||
}
|
||||
|
||||
|
@ -165,12 +165,12 @@ struct CargoSpec {
|
|||
};
|
||||
|
||||
bool operator==(const Iterator &other) const { return this->index == other.index; }
|
||||
CargoSpec * operator*() const { return CargoSpec::Get(this->index); }
|
||||
CargoSpec * operator*() const { return CargoSpec::Get(CargoType{static_cast<CargoType::BaseType>(this->index)}); }
|
||||
Iterator & operator++() { this->index++; this->ValidateIndex(); return *this; }
|
||||
|
||||
private:
|
||||
size_t index;
|
||||
void ValidateIndex() { while (this->index < CargoSpec::GetArraySize() && !(CargoSpec::Get(this->index)->IsValid())) this->index++; }
|
||||
void ValidateIndex() { while (this->index < CargoSpec::GetArraySize() && !(**this)->IsValid()) this->index++; }
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -195,7 +195,7 @@ struct CargoSpec {
|
|||
static std::array<std::vector<const CargoSpec *>, NUM_TPE> town_production_cargoes;
|
||||
|
||||
private:
|
||||
static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
|
||||
static TypedIndexContainer<std::array<CargoSpec, NUM_CARGO>, CargoType> array; ///< Array holding all CargoSpecs
|
||||
static inline std::map<CargoLabel, CargoType> label_map{}; ///< Translation map from CargoLabel to Cargo type.
|
||||
|
||||
friend void SetupCargoForClimate(LandscapeType l);
|
||||
|
@ -223,7 +223,7 @@ inline CargoType GetCargoTypeByLabel(CargoLabel label)
|
|||
Dimension GetLargestCargoIconSize();
|
||||
|
||||
void InitializeSortedCargoSpecs();
|
||||
extern std::array<uint8_t, NUM_CARGO> _sorted_cargo_types;
|
||||
extern TypedIndexContainer<std::array<uint8_t, NUM_CARGO>, CargoType> _sorted_cargo_types;
|
||||
extern std::vector<const CargoSpec *> _sorted_cargo_specs;
|
||||
extern std::span<const CargoSpec *> _sorted_standard_cargo_specs;
|
||||
|
||||
|
@ -238,8 +238,6 @@ inline bool IsCargoInClass(CargoType cargo, CargoClasses cc)
|
|||
return CargoSpec::Get(cargo)->classes.Any(cc);
|
||||
}
|
||||
|
||||
using SetCargoBitIterator = SetBitIterator<CargoType, CargoTypes>;
|
||||
|
||||
/** Comparator to sort CargoType by according to desired order. */
|
||||
struct CargoTypeComparator {
|
||||
bool operator() (const CargoType &lhs, const CargoType &rhs) const { return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs]; }
|
||||
|
|
|
@ -29,6 +29,7 @@ add_files(
|
|||
string_consumer.hpp
|
||||
string_inplace.cpp
|
||||
string_inplace.hpp
|
||||
strong_bitset_type.hpp
|
||||
strong_typedef_type.hpp
|
||||
utf8.cpp
|
||||
utf8.hpp
|
||||
|
|
|
@ -108,6 +108,16 @@ public:
|
|||
return static_cast<Timpl&>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip all bits.
|
||||
* @returns The bit set
|
||||
*/
|
||||
inline constexpr Timpl &Flip()
|
||||
{
|
||||
this->data ^= Tmask;
|
||||
return static_cast<Timpl&>(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the value-th bit.
|
||||
* @param value Bit to flip.
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file strong_bitset_type.hpp Type helper for making a BitSet out of a Strong Typedef. */
|
||||
|
||||
#ifndef STRONG_BITSET_TYPE_HPP
|
||||
#define STRONG_BITSET_TYPE_HPP
|
||||
|
||||
#include "base_bitset_type.hpp"
|
||||
|
||||
/**
|
||||
* Strong bit set.
|
||||
* @tparam Tvalue_type Type of values to wrap.
|
||||
* @tparam Tstorage Storage type required to hold values.
|
||||
*/
|
||||
template <typename Tvalue_type, typename Tstorage, Tstorage Tmask = std::numeric_limits<Tstorage>::max()>
|
||||
class StrongBitSet : public BaseBitSet<StrongBitSet<Tvalue_type, Tstorage, Tmask>, Tvalue_type, Tstorage> {
|
||||
public:
|
||||
constexpr StrongBitSet() : BaseClass() {}
|
||||
constexpr StrongBitSet(Tvalue_type value) : BaseClass() { this->Set(value); }
|
||||
explicit constexpr StrongBitSet(Tstorage data) : BaseClass(data) {}
|
||||
|
||||
constexpr StrongBitSet(std::initializer_list<const Tvalue_type> values) : BaseClass()
|
||||
{
|
||||
for (const Tvalue_type &value : values) {
|
||||
this->Set(value);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr size_t DecayValueType(Tvalue_type value) { return value.base(); }
|
||||
|
||||
constexpr auto operator <=>(const StrongBitSet &) const noexcept = default;
|
||||
|
||||
private:
|
||||
using BaseClass = BaseBitSet<StrongBitSet<Tvalue_type, Tstorage, Tmask>, Tvalue_type, Tstorage, Tmask>;
|
||||
};
|
||||
|
||||
#endif /* STRONG_BITSET_TYPE_HPP */
|
|
@ -1100,7 +1100,7 @@ static Money DeliverGoods(int num_pieces, CargoType cargo_type, StationID dest,
|
|||
uint accepted_ind = DeliverGoodsToIndustry(st, cargo_type, num_pieces, src.type == SourceType::Industry ? src.ToIndustryID() : IndustryID::Invalid(), company->index);
|
||||
|
||||
/* If this cargo type is always accepted, accept all */
|
||||
uint accepted_total = HasBit(st->always_accepted, cargo_type) ? num_pieces : accepted_ind;
|
||||
uint accepted_total = st->always_accepted.Test(cargo_type) ? num_pieces : accepted_ind;
|
||||
|
||||
/* Update station statistics */
|
||||
if (accepted_total > 0) {
|
||||
|
@ -1393,7 +1393,7 @@ struct PrepareRefitAction
|
|||
bool operator()(const Vehicle *v)
|
||||
{
|
||||
this->consist_capleft[v->cargo_type] -= v->cargo_cap - v->cargo.ReservedCount();
|
||||
this->refit_mask |= EngInfo(v->engine_type)->refit_mask;
|
||||
this->refit_mask.Set(EngInfo(v->engine_type)->refit_mask);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -1486,7 +1486,7 @@ static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station
|
|||
if (is_auto_refit) {
|
||||
/* Get a refittable cargo type with waiting cargo for next_station or StationID::Invalid(). */
|
||||
new_cargo_type = v_start->cargo_type;
|
||||
for (CargoType cargo_type : SetCargoBitIterator(refit_mask)) {
|
||||
for (CargoType cargo_type : refit_mask) {
|
||||
if (st->goods[cargo_type].HasData() && st->goods[cargo_type].GetData().cargo.HasCargoFor(next_station)) {
|
||||
/* Try to find out if auto-refitting would succeed. In case the refit is allowed,
|
||||
* the returned refit capacity will be greater than zero. */
|
||||
|
@ -1645,10 +1645,10 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
bool completely_emptied = true;
|
||||
bool anything_unloaded = false;
|
||||
bool anything_loaded = false;
|
||||
CargoTypes full_load_amount = 0;
|
||||
CargoTypes cargo_not_full = 0;
|
||||
CargoTypes cargo_full = 0;
|
||||
CargoTypes reservation_left = 0;
|
||||
CargoTypes full_load_amount{};
|
||||
CargoTypes cargo_not_full{};
|
||||
CargoTypes cargo_full{};
|
||||
CargoTypes reservation_left{};
|
||||
|
||||
front->cur_speed = 0;
|
||||
|
||||
|
@ -1779,14 +1779,14 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
if (v->cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
|
||||
/* Remember if there are reservations left so that we don't stop
|
||||
* loading before they're loaded. */
|
||||
SetBit(reservation_left, v->cargo_type);
|
||||
reservation_left.Set(v->cargo_type);
|
||||
}
|
||||
|
||||
/* Store whether the maximum possible load amount was loaded or not.*/
|
||||
if (loaded == cap_left) {
|
||||
SetBit(full_load_amount, v->cargo_type);
|
||||
full_load_amount.Set(v->cargo_type);
|
||||
} else {
|
||||
ClrBit(full_load_amount, v->cargo_type);
|
||||
full_load_amount.Reset(v->cargo_type);
|
||||
}
|
||||
|
||||
/* TODO: Regarding this, when we do gradual loading, we
|
||||
|
@ -1819,9 +1819,9 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
}
|
||||
|
||||
if (v->cargo.StoredCount() >= v->cargo_cap) {
|
||||
SetBit(cargo_full, v->cargo_type);
|
||||
cargo_full.Set(v->cargo_type);
|
||||
} else {
|
||||
SetBit(cargo_not_full, v->cargo_type);
|
||||
cargo_not_full.Set(v->cargo_type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1851,7 +1851,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
}
|
||||
/* We loaded less cargo than possible for all cargo types and it's not full
|
||||
* load and we're not supposed to wait any longer: stop loading. */
|
||||
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
|
||||
if (!anything_unloaded && full_load_amount.None() && reservation_left.None() && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
|
||||
front->current_order_time >= std::max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
|
||||
front->vehicle_flags.Set(VehicleFlag::StopLoading);
|
||||
}
|
||||
|
@ -1865,10 +1865,10 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
/* if the aircraft carries passengers and is NOT full, then
|
||||
* continue loading, no matter how much mail is in */
|
||||
if ((front->type == VEH_AIRCRAFT && IsCargoInClass(front->cargo_type, CargoClass::Passengers) && front->cargo_cap > front->cargo.StoredCount()) ||
|
||||
(cargo_not_full != 0 && (cargo_full & ~cargo_not_full) == 0)) { // There are still non-full cargoes
|
||||
(cargo_not_full.Any() && cargo_full.Reset(cargo_not_full).None())) { // There are still non-full cargoes
|
||||
finished_loading = false;
|
||||
}
|
||||
} else if (cargo_not_full != 0) {
|
||||
} else if (cargo_not_full.Any()) {
|
||||
finished_loading = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -927,7 +927,7 @@ static CompanyID GetPreviewCompany(Engine *e)
|
|||
/* Check whether the company uses similar vehicles */
|
||||
for (const Vehicle *v : Vehicle::Iterate()) {
|
||||
if (v->owner != c->index || v->type != e->type) continue;
|
||||
if (!v->GetEngine()->CanCarryCargo() || !HasBit(cargomask, v->cargo_type)) continue;
|
||||
if (!v->GetEngine()->CanCarryCargo() || !cargomask.Test(v->cargo_type)) continue;
|
||||
|
||||
best_hist = c->old_economy[0].performance_history;
|
||||
best_company = c->index;
|
||||
|
@ -1294,7 +1294,7 @@ bool IsEngineRefittable(EngineID engine)
|
|||
if (!e->CanCarryCargo()) return false;
|
||||
|
||||
const EngineInfo *ei = &e->info;
|
||||
if (ei->refit_mask == 0) return false;
|
||||
if (ei->refit_mask.None()) return false;
|
||||
|
||||
/* Are there suffixes?
|
||||
* Note: This does not mean the suffixes are actually available for every consist at any time. */
|
||||
|
@ -1302,9 +1302,7 @@ bool IsEngineRefittable(EngineID engine)
|
|||
|
||||
/* Is there any cargo except the default cargo? */
|
||||
CargoType default_cargo = e->GetDefaultCargoType();
|
||||
CargoTypes default_cargo_mask = 0;
|
||||
SetBit(default_cargo_mask, default_cargo);
|
||||
return IsValidCargoType(default_cargo) && ei->refit_mask != default_cargo_mask;
|
||||
return IsValidCargoType(default_cargo) && ei->refit_mask != default_cargo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1118,7 +1118,7 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
this->cargo_types = this->GetCargoTypes(number);
|
||||
|
||||
this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
|
||||
this->vscroll->SetCount(CountBits(this->cargo_types));
|
||||
this->vscroll->SetCount(this->cargo_types.Count());
|
||||
|
||||
auto *wid = this->GetWidget<NWidgetCore>(WID_GRAPH_FOOTER);
|
||||
wid->SetString(TimerGameEconomy::UsingWallclockUnits() ? footer_wallclock : footer_calendar);
|
||||
|
@ -1138,10 +1138,10 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
if (row >= this->vscroll->GetCount()) return std::nullopt;
|
||||
|
||||
for (const CargoSpec *cs : _sorted_cargo_specs) {
|
||||
if (!HasBit(this->cargo_types, cs->Index())) continue;
|
||||
if (!this->cargo_types.Test(cs->Index())) continue;
|
||||
if (row-- > 0) continue;
|
||||
|
||||
return cs->Index();
|
||||
return cs->Index().base();
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
|
@ -1162,7 +1162,7 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
|
||||
size.height = GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical();
|
||||
|
||||
for (CargoType cargo_type : SetCargoBitIterator(this->cargo_types)) {
|
||||
for (CargoType cargo_type : this->cargo_types) {
|
||||
const CargoSpec *cs = CargoSpec::Get(cargo_type);
|
||||
|
||||
Dimension d = GetStringBoundingBox(GetString(STR_GRAPH_CARGO_PAYMENT_CARGO, cs->name));
|
||||
|
@ -1193,12 +1193,12 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
Rect line = r.WithHeight(this->line_height);
|
||||
|
||||
for (const CargoSpec *cs : _sorted_cargo_specs) {
|
||||
if (!HasBit(this->cargo_types, cs->Index())) continue;
|
||||
if (!this->cargo_types.Test(cs->Index())) continue;
|
||||
|
||||
if (pos-- > 0) continue;
|
||||
if (--max < 0) break;
|
||||
|
||||
bool lowered = !HasBit(this->excluded_data, cs->Index());
|
||||
bool lowered = !HasBit(this->excluded_data, cs->Index().base());
|
||||
|
||||
/* Redraw frame if lowered */
|
||||
if (lowered) DrawFrameRect(line, COLOUR_BROWN, FrameFlag::Lowered);
|
||||
|
@ -1225,14 +1225,14 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
case WID_GRAPH_ENABLE_CARGOES:
|
||||
/* Remove all cargoes from the excluded lists. */
|
||||
this->GetExcludedCargoTypes() = {};
|
||||
this->excluded_data = this->GetExcludedCargoTypes();
|
||||
this->excluded_data = this->GetExcludedCargoTypes().base();
|
||||
this->SetDirty();
|
||||
break;
|
||||
|
||||
case WID_GRAPH_DISABLE_CARGOES: {
|
||||
/* Add all cargoes to the excluded lists. */
|
||||
this->GetExcludedCargoTypes() = this->cargo_types;
|
||||
this->excluded_data = this->GetExcludedCargoTypes();
|
||||
this->excluded_data = this->GetExcludedCargoTypes().base();
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
@ -1242,11 +1242,11 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
|||
if (row >= this->vscroll->GetCount()) return;
|
||||
|
||||
for (const CargoSpec *cs : _sorted_cargo_specs) {
|
||||
if (!HasBit(this->cargo_types, cs->Index())) continue;
|
||||
if (!this->cargo_types.Test(cs->Index())) continue;
|
||||
if (row-- > 0) continue;
|
||||
|
||||
ToggleBit(this->GetExcludedCargoTypes(), cs->Index());
|
||||
this->excluded_data = this->GetExcludedCargoTypes();
|
||||
this->GetExcludedCargoTypes().Flip(cs->Index());
|
||||
this->excluded_data = this->GetExcludedCargoTypes().base();
|
||||
this->SetDirty();
|
||||
break;
|
||||
}
|
||||
|
@ -1318,13 +1318,13 @@ struct PaymentRatesGraphWindow : BaseCargoGraphWindow {
|
|||
*/
|
||||
void UpdatePaymentRates()
|
||||
{
|
||||
this->excluded_data = this->GetExcludedCargoTypes();
|
||||
this->excluded_data = this->GetExcludedCargoTypes().base();
|
||||
|
||||
this->data.clear();
|
||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||
DataSet &dataset = this->data.emplace_back();
|
||||
dataset.colour = cs->legend_colour;
|
||||
dataset.exclude_bit = cs->Index();
|
||||
dataset.exclude_bit = cs->Index().base();
|
||||
|
||||
for (uint j = 0; j != this->num_on_x_axis; j++) {
|
||||
dataset.values[j] = GetTransportedGoodsIncome(10, 20, j * 4 + 4, cs->Index());
|
||||
|
@ -1631,7 +1631,7 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
CargoTypes cargo_types{};
|
||||
const Industry *i = Industry::Get(window_number);
|
||||
for (const auto &p : i->produced) {
|
||||
if (IsValidCargoType(p.cargo)) SetBit(cargo_types, p.cargo);
|
||||
if (IsValidCargoType(p.cargo)) cargo_types.Set(p.cargo);
|
||||
}
|
||||
return cargo_types;
|
||||
}
|
||||
|
@ -1657,12 +1657,12 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
mo += 12;
|
||||
}
|
||||
|
||||
if (!initialize && this->excluded_data == this->GetExcludedCargoTypes() && this->num_on_x_axis == this->num_vert_lines && this->year == yr && this->month == mo) {
|
||||
if (!initialize && this->excluded_data == this->GetExcludedCargoTypes().base() && this->num_on_x_axis == this->num_vert_lines && this->year == yr && this->month == mo) {
|
||||
/* There's no reason to get new stats */
|
||||
return;
|
||||
}
|
||||
|
||||
this->excluded_data = this->GetExcludedCargoTypes();
|
||||
this->excluded_data = this->GetExcludedCargoTypes().base();
|
||||
this->year = yr;
|
||||
this->month = mo;
|
||||
|
||||
|
@ -1677,13 +1677,13 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
|||
|
||||
DataSet &produced = this->data.emplace_back();
|
||||
produced.colour = cs->legend_colour;
|
||||
produced.exclude_bit = cs->Index();
|
||||
produced.exclude_bit = cs->Index().base();
|
||||
produced.range_bit = 0;
|
||||
auto produced_filler = Filler{produced, &Industry::ProducedHistory::production};
|
||||
|
||||
DataSet &transported = this->data.emplace_back();
|
||||
transported.colour = cs->legend_colour;
|
||||
transported.exclude_bit = cs->Index();
|
||||
transported.exclude_bit = cs->Index().base();
|
||||
transported.range_bit = 1;
|
||||
transported.dash = 2;
|
||||
auto transported_filler = Filler{transported, &Industry::ProducedHistory::transported};
|
||||
|
|
|
@ -708,7 +708,7 @@ public:
|
|||
return;
|
||||
|
||||
case WID_GL_FILTER_BY_CARGO: // Select filtering criteria dropdown menu
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria, widget);
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria.base(), widget);
|
||||
break;
|
||||
|
||||
case WID_GL_ALL_VEHICLES: // All vehicles button
|
||||
|
@ -999,7 +999,7 @@ public:
|
|||
break;
|
||||
|
||||
case WID_GL_FILTER_BY_CARGO: // Select a cargo filter criteria
|
||||
this->SetCargoFilter(index);
|
||||
this->SetCargoFilter(static_cast<CargoType>(index));
|
||||
break;
|
||||
|
||||
case WID_GL_MANAGE_VEHICLES_DROPDOWN:
|
||||
|
|
|
@ -71,14 +71,14 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
|||
}
|
||||
};
|
||||
struct ProducedCargo {
|
||||
CargoType cargo = 0; ///< Cargo type
|
||||
CargoType cargo = INVALID_CARGO; ///< Cargo type
|
||||
uint16_t waiting = 0; ///< Amount of cargo produced
|
||||
uint8_t rate = 0; ///< Production rate
|
||||
HistoryData<ProducedHistory> history{}; ///< History of cargo produced and transported for this month and 24 previous months
|
||||
};
|
||||
|
||||
struct AcceptedCargo {
|
||||
CargoType cargo = 0; ///< Cargo type
|
||||
CargoType cargo = INVALID_CARGO; ///< Cargo type
|
||||
uint16_t waiting = 0; ///< Amount of cargo waiting to processed
|
||||
TimerGameEconomy::Date last_accepted{}; ///< Last day cargo was accepted by this industry
|
||||
};
|
||||
|
|
|
@ -464,13 +464,13 @@ static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, Ca
|
|||
acceptance[cargo] += cargo_acceptance[i];
|
||||
|
||||
/* Maybe set 'always accepted' bit (if it's not set already) */
|
||||
if (HasBit(always_accepted, cargo)) continue;
|
||||
if (always_accepted.Test(cargo)) continue;
|
||||
|
||||
/* Test whether the industry itself accepts the cargo type */
|
||||
if (ind->IsCargoAccepted(cargo)) continue;
|
||||
|
||||
/* If the industry itself doesn't accept this cargo, set 'always accepted' bit */
|
||||
SetBit(always_accepted, cargo);
|
||||
always_accepted.Set(cargo);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1308,12 +1308,12 @@ static bool CargoFilter(const Industry * const *industry, const std::pair<CargoT
|
|||
|
||||
bool accepted_cargo_matches;
|
||||
|
||||
switch (accepted_cargo) {
|
||||
case CargoFilterCriteria::CF_ANY:
|
||||
switch (accepted_cargo.base()) {
|
||||
case CargoFilterCriteria::CF_ANY.base():
|
||||
accepted_cargo_matches = true;
|
||||
break;
|
||||
|
||||
case CargoFilterCriteria::CF_NONE:
|
||||
case CargoFilterCriteria::CF_NONE.base():
|
||||
accepted_cargo_matches = !(*industry)->IsCargoAccepted();
|
||||
break;
|
||||
|
||||
|
@ -1324,12 +1324,12 @@ static bool CargoFilter(const Industry * const *industry, const std::pair<CargoT
|
|||
|
||||
bool produced_cargo_matches;
|
||||
|
||||
switch (produced_cargo) {
|
||||
case CargoFilterCriteria::CF_ANY:
|
||||
switch (produced_cargo.base()) {
|
||||
case CargoFilterCriteria::CF_ANY.base():
|
||||
produced_cargo_matches = true;
|
||||
break;
|
||||
|
||||
case CargoFilterCriteria::CF_NONE:
|
||||
case CargoFilterCriteria::CF_NONE.base():
|
||||
produced_cargo_matches = !(*industry)->IsCargoProduced();
|
||||
break;
|
||||
|
||||
|
@ -1415,9 +1415,9 @@ protected:
|
|||
|
||||
StringID GetCargoFilterLabel(CargoType cargo_type) const
|
||||
{
|
||||
switch (cargo_type) {
|
||||
case CargoFilterCriteria::CF_ANY: return STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_NONE: return STR_INDUSTRY_DIRECTORY_FILTER_NONE;
|
||||
switch (cargo_type.base()) {
|
||||
case CargoFilterCriteria::CF_ANY.base(): return STR_INDUSTRY_DIRECTORY_FILTER_ALL_TYPES;
|
||||
case CargoFilterCriteria::CF_NONE.base(): return STR_INDUSTRY_DIRECTORY_FILTER_NONE;
|
||||
default: return CargoSpec::Get(cargo_type)->name;
|
||||
}
|
||||
}
|
||||
|
@ -1795,14 +1795,14 @@ public:
|
|||
DropDownList list;
|
||||
|
||||
/* Add item for disabling filtering. */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY.base()));
|
||||
/* Add item for industries not producing anything, e.g. power plants */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE.base()));
|
||||
|
||||
/* Add cargos */
|
||||
Dimension d = GetLargestCargoIconSize();
|
||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index()));
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index().base()));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -1821,11 +1821,11 @@ public:
|
|||
break;
|
||||
|
||||
case WID_ID_FILTER_BY_ACC_CARGO: // Cargo filter dropdown
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->accepted_cargo_filter_criteria, widget);
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->accepted_cargo_filter_criteria.base(), widget);
|
||||
break;
|
||||
|
||||
case WID_ID_FILTER_BY_PROD_CARGO: // Cargo filter dropdown
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->produced_cargo_filter_criteria, widget);
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(), this->produced_cargo_filter_criteria.base(), widget);
|
||||
break;
|
||||
|
||||
case WID_ID_INDUSTRY_LIST: {
|
||||
|
@ -1854,13 +1854,13 @@ public:
|
|||
}
|
||||
|
||||
case WID_ID_FILTER_BY_ACC_CARGO: {
|
||||
this->SetAcceptedCargoFilter(index);
|
||||
this->SetAcceptedCargoFilter(static_cast<CargoType>(index));
|
||||
this->BuildSortIndustriesList();
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_ID_FILTER_BY_PROD_CARGO: {
|
||||
this->SetProducedCargoFilter(index);
|
||||
this->SetProducedCargoFilter(static_cast<CargoType>(index));
|
||||
this->BuildSortIndustriesList();
|
||||
break;
|
||||
}
|
||||
|
@ -2667,7 +2667,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
const IndustrySpec *indsp = GetIndustrySpec(this->ind_cargo);
|
||||
return GetString(STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION, indsp->name);
|
||||
} else {
|
||||
const CargoSpec *csp = CargoSpec::Get(this->ind_cargo - NUM_INDUSTRYTYPES);
|
||||
const CargoSpec *csp = CargoSpec::Get(static_cast<CargoType>(this->ind_cargo - NUM_INDUSTRYTYPES));
|
||||
return GetString(STR_INDUSTRY_CARGOES_CARGO_CAPTION, csp->name);
|
||||
}
|
||||
}
|
||||
|
@ -2680,9 +2680,9 @@ struct IndustryCargoesWindow : public Window {
|
|||
*/
|
||||
static bool HasCommonValidCargo(const std::span<const CargoType> cargoes1, const std::span<const CargoType> cargoes2)
|
||||
{
|
||||
for (const CargoType cargo_type1 : cargoes1) {
|
||||
for (const CargoType &cargo_type1 : cargoes1) {
|
||||
if (!IsValidCargoType(cargo_type1)) continue;
|
||||
for (const CargoType cargo_type2 : cargoes2) {
|
||||
for (const CargoType &cargo_type2 : cargoes2) {
|
||||
if (cargo_type1 == cargo_type2) return true;
|
||||
}
|
||||
}
|
||||
|
@ -2696,7 +2696,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
*/
|
||||
static bool HousesCanSupply(const std::span<const CargoType> cargoes)
|
||||
{
|
||||
for (const CargoType cargo_type : cargoes) {
|
||||
for (const CargoType &cargo_type : cargoes) {
|
||||
if (!IsValidCargoType(cargo_type)) continue;
|
||||
TownProductionEffect tpe = CargoSpec::Get(cargo_type)->town_production_effect;
|
||||
if (tpe == TPE_PASSENGERS || tpe == TPE_MAIL) return true;
|
||||
|
@ -2713,7 +2713,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
{
|
||||
HouseZones climate_mask = GetClimateMaskForLandscape();
|
||||
|
||||
for (const CargoType cargo_type : cargoes) {
|
||||
for (const CargoType &cargo_type : cargoes) {
|
||||
if (!IsValidCargoType(cargo_type)) continue;
|
||||
|
||||
for (const auto &hs : HouseSpec::Specs()) {
|
||||
|
@ -2894,7 +2894,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
*/
|
||||
void ComputeCargoDisplay(CargoType cargo_type)
|
||||
{
|
||||
this->ind_cargo = cargo_type + NUM_INDUSTRYTYPES;
|
||||
this->ind_cargo = cargo_type.base() + NUM_INDUSTRYTYPES;
|
||||
_displayed_industries.reset();
|
||||
|
||||
this->fields.clear();
|
||||
|
@ -3107,7 +3107,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
DropDownList lst;
|
||||
Dimension d = GetLargestCargoIconSize();
|
||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||
lst.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index()));
|
||||
lst.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index().base()));
|
||||
}
|
||||
if (!lst.empty()) {
|
||||
int selected = (this->ind_cargo >= NUM_INDUSTRYTYPES) ? (int)(this->ind_cargo - NUM_INDUSTRYTYPES) : -1;
|
||||
|
@ -3138,7 +3138,7 @@ struct IndustryCargoesWindow : public Window {
|
|||
|
||||
switch (widget) {
|
||||
case WID_IC_CARGO_DROPDOWN:
|
||||
this->ComputeCargoDisplay(index);
|
||||
this->ComputeCargoDisplay(static_cast<CargoType>(index));
|
||||
break;
|
||||
|
||||
case WID_IC_IND_DROPDOWN:
|
||||
|
|
|
@ -86,7 +86,7 @@ void LinkGraphOverlay::RebuildCache()
|
|||
StationLinkMap &seen_links = this->cached_links[from];
|
||||
|
||||
uint supply = 0;
|
||||
for (CargoType cargo : SetCargoBitIterator(this->cargo_mask)) {
|
||||
for (CargoType cargo : this->cargo_mask) {
|
||||
if (!CargoSpec::Get(cargo)->IsValid()) continue;
|
||||
if (!LinkGraph::IsValidID(sta->goods[cargo].link_graph)) continue;
|
||||
const LinkGraph &lg = *LinkGraph::Get(sta->goods[cargo].link_graph);
|
||||
|
@ -212,7 +212,7 @@ inline bool LinkGraphOverlay::IsLinkVisible(Point pta, Point ptb, const DrawPixe
|
|||
*/
|
||||
void LinkGraphOverlay::AddLinks(const Station *from, const Station *to)
|
||||
{
|
||||
for (CargoType cargo : SetCargoBitIterator(this->cargo_mask)) {
|
||||
for (CargoType cargo : this->cargo_mask) {
|
||||
if (!CargoSpec::Get(cargo)->IsValid()) continue;
|
||||
const GoodsEntry &ge = from->goods[cargo];
|
||||
if (!LinkGraph::IsValidID(ge.link_graph) ||
|
||||
|
@ -566,7 +566,7 @@ void LinkGraphLegendWindow::SetOverlay(std::shared_ptr<LinkGraphOverlay> overlay
|
|||
}
|
||||
CargoTypes cargoes = this->overlay->GetCargoMask();
|
||||
for (uint c = 0; c < this->num_cargo; c++) {
|
||||
this->SetWidgetLoweredState(WID_LGL_CARGO_FIRST + c, HasBit(cargoes, _sorted_cargo_specs[c]->Index()));
|
||||
this->SetWidgetLoweredState(WID_LGL_CARGO_FIRST + c, cargoes.Test(_sorted_cargo_specs[c]->Index()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,10 +669,10 @@ void LinkGraphLegendWindow::UpdateOverlayCompanies()
|
|||
*/
|
||||
void LinkGraphLegendWindow::UpdateOverlayCargoes()
|
||||
{
|
||||
CargoTypes mask = 0;
|
||||
CargoTypes mask{};
|
||||
for (uint c = 0; c < num_cargo; c++) {
|
||||
if (!this->IsWidgetLowered(WID_LGL_CARGO_FIRST + c)) continue;
|
||||
SetBit(mask, _sorted_cargo_specs[c]->Index());
|
||||
mask.Set(_sorted_cargo_specs[c]->Index());
|
||||
}
|
||||
this->overlay->SetCargoMask(mask);
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ bool LinkRefresher::HandleRefit(CargoType refit_cargo)
|
|||
bool any_refit = false;
|
||||
for (Vehicle *v = this->vehicle; v != nullptr; v = v->Next()) {
|
||||
const Engine *e = Engine::Get(v->engine_type);
|
||||
if (!HasBit(e->info.refit_mask, this->cargo)) {
|
||||
if (!e->info.refit_mask.Test(this->cargo)) {
|
||||
++refit_it;
|
||||
continue;
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ void LinkRefresher::RefreshStats(VehicleOrderID cur, VehicleOrderID next)
|
|||
Station *st = Station::GetIfValid(orders[cur].GetDestination().ToStationID());
|
||||
if (st != nullptr && next_station != StationID::Invalid() && next_station != st->index) {
|
||||
Station *st_to = Station::Get(next_station);
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
/* Refresh the link and give it a minimum capacity. */
|
||||
|
||||
uint cargo_quantity = this->capacities[cargo];
|
||||
|
@ -260,7 +260,7 @@ void LinkRefresher::RefreshLinks(VehicleOrderID cur, VehicleOrderID next, Refres
|
|||
} else if (!flags.Test(RefreshFlag::InAutorefit)) {
|
||||
flags.Set(RefreshFlag::InAutorefit);
|
||||
LinkRefresher backup(*this);
|
||||
for (CargoType cargo = 0; cargo != NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
if (CargoSpec::Get(cargo)->IsValid() && this->HandleRefit(cargo)) {
|
||||
this->RefreshLinks(cur, next, flags, num_hops);
|
||||
*this = backup;
|
||||
|
|
|
@ -221,14 +221,14 @@ struct MainWindow : Window
|
|||
NWidgetViewport *nvp = this->GetWidget<NWidgetViewport>(WID_M_VIEWPORT);
|
||||
nvp->InitializeViewport(this, TileXY(32, 32), ScaleZoomGUI(ZoomLevel::Viewport));
|
||||
|
||||
this->viewport->overlay = std::make_shared<LinkGraphOverlay>(this, WID_M_VIEWPORT, 0, CompanyMask{}, 2);
|
||||
this->viewport->overlay = std::make_shared<LinkGraphOverlay>(this, WID_M_VIEWPORT, CargoTypes{}, CompanyMask{}, 2);
|
||||
this->refresh_timeout.Reset();
|
||||
}
|
||||
|
||||
/** Refresh the link-graph overlay. */
|
||||
void RefreshLinkGraph()
|
||||
{
|
||||
if (this->viewport->overlay->GetCargoMask() == 0 ||
|
||||
if (this->viewport->overlay->GetCargoMask().None() ||
|
||||
this->viewport->overlay->GetCompanyMask().None()) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -310,10 +310,10 @@ EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal
|
|||
*/
|
||||
CargoTypes TranslateRefitMask(uint32_t refit_mask)
|
||||
{
|
||||
CargoTypes result = 0;
|
||||
CargoTypes result{};
|
||||
for (uint8_t bit : SetBitIterator(refit_mask)) {
|
||||
CargoType cargo = GetCargoTranslation(bit, _cur_gps.grffile, true);
|
||||
if (IsValidCargoType(cargo)) SetBit(result, cargo);
|
||||
if (IsValidCargoType(cargo)) result.Set(cargo);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -641,9 +641,9 @@ static CargoLabel GetActiveCargoLabel(const std::variant<CargoLabel, MixedCargoT
|
|||
*/
|
||||
static void CalculateRefitMasks()
|
||||
{
|
||||
CargoTypes original_known_cargoes = 0;
|
||||
for (CargoType cargo_type = 0; cargo_type != NUM_CARGO; ++cargo_type) {
|
||||
if (IsDefaultCargo(cargo_type)) SetBit(original_known_cargoes, cargo_type);
|
||||
CargoTypes original_known_cargoes{};
|
||||
for (CargoType cargo_type{}; cargo_type != NUM_CARGO; ++cargo_type) {
|
||||
if (IsDefaultCargo(cargo_type)) original_known_cargoes.Set(cargo_type);
|
||||
}
|
||||
|
||||
for (Engine *e : Engine::Iterate()) {
|
||||
|
@ -738,13 +738,13 @@ static void CalculateRefitMasks()
|
|||
}
|
||||
_gted[engine].UpdateRefittability(_gted[engine].cargo_allowed.Any());
|
||||
|
||||
if (IsValidCargoType(ei->cargo_type)) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
|
||||
if (IsValidCargoType(ei->cargo_type)) _gted[engine].ctt_exclude_mask.Reset(ei->cargo_type);
|
||||
}
|
||||
|
||||
/* Compute refittability */
|
||||
{
|
||||
CargoTypes mask = 0;
|
||||
CargoTypes not_mask = 0;
|
||||
CargoTypes mask{};
|
||||
CargoTypes not_mask{};
|
||||
CargoTypes xor_mask = ei->refit_mask;
|
||||
|
||||
/* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo.
|
||||
|
@ -754,16 +754,17 @@ static void CalculateRefitMasks()
|
|||
if (_gted[engine].cargo_allowed.Any()) {
|
||||
/* Build up the list of cargo types from the set cargo classes. */
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
if (cs->classes.Any(_gted[engine].cargo_allowed) && cs->classes.All(_gted[engine].cargo_allowed_required)) SetBit(mask, cs->Index());
|
||||
if (cs->classes.Any(_gted[engine].cargo_disallowed)) SetBit(not_mask, cs->Index());
|
||||
if (cs->classes.Any(_gted[engine].cargo_allowed) && cs->classes.All(_gted[engine].cargo_allowed_required)) mask.Set(cs->Index());
|
||||
if (cs->classes.Any(_gted[engine].cargo_disallowed)) not_mask.Set(cs->Index());
|
||||
}
|
||||
}
|
||||
|
||||
ei->refit_mask = ((mask & ~not_mask) ^ xor_mask) & _cargo_mask;
|
||||
CargoTypes invalid_mask = CargoTypes{_cargo_mask}.Flip();
|
||||
ei->refit_mask = mask.Reset(not_mask).Flip(xor_mask).Reset(invalid_mask);
|
||||
|
||||
/* Apply explicit refit includes/excludes. */
|
||||
ei->refit_mask |= _gted[engine].ctt_include_mask;
|
||||
ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
|
||||
ei->refit_mask.Set(_gted[engine].ctt_include_mask);
|
||||
ei->refit_mask.Reset(_gted[engine].ctt_exclude_mask);
|
||||
|
||||
/* Custom refit mask callback. */
|
||||
const GRFFile *file = _gted[e->index].defaultcargo_grf;
|
||||
|
@ -776,8 +777,8 @@ static void CalculateRefitMasks()
|
|||
case CALLBACK_FAILED:
|
||||
case 0:
|
||||
break; // Do nothing.
|
||||
case 1: SetBit(ei->refit_mask, cs->Index()); break;
|
||||
case 2: ClrBit(ei->refit_mask, cs->Index()); break;
|
||||
case 1: ei->refit_mask.Set(cs->Index()); break;
|
||||
case 2: ei->refit_mask.Reset(cs->Index()); break;
|
||||
|
||||
default: ErrorUnknownCallbackResult(file->grfid, CBID_VEHICLE_CUSTOM_REFIT, callback);
|
||||
}
|
||||
|
@ -786,24 +787,24 @@ static void CalculateRefitMasks()
|
|||
}
|
||||
|
||||
/* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */
|
||||
if (IsValidCargoType(ei->cargo_type) && !HasBit(_cargo_mask, ei->cargo_type)) ei->cargo_type = INVALID_CARGO;
|
||||
if (IsValidCargoType(ei->cargo_type) && !_cargo_mask.Test(ei->cargo_type)) ei->cargo_type = INVALID_CARGO;
|
||||
|
||||
/* Ensure that the vehicle is either not refittable, or that the default cargo is one of the refittable cargoes.
|
||||
* Note: Vehicles refittable to no cargo are handle differently to vehicle refittable to a single cargo. The latter might have subtypes. */
|
||||
if (!only_defaultcargo && (e->type != VEH_SHIP || e->u.ship.old_refittable) && IsValidCargoType(ei->cargo_type) && !HasBit(ei->refit_mask, ei->cargo_type)) {
|
||||
if (!only_defaultcargo && (e->type != VEH_SHIP || e->u.ship.old_refittable) && IsValidCargoType(ei->cargo_type) && !ei->refit_mask.Test(ei->cargo_type)) {
|
||||
ei->cargo_type = INVALID_CARGO;
|
||||
}
|
||||
|
||||
/* Check if this engine's cargo type is valid. If not, set to the first refittable
|
||||
* cargo type. Finally disable the vehicle, if there is still no cargo. */
|
||||
if (!IsValidCargoType(ei->cargo_type) && ei->refit_mask != 0) {
|
||||
if (!IsValidCargoType(ei->cargo_type) && ei->refit_mask.Any()) {
|
||||
/* Figure out which CTT to use for the default cargo, if it is 'first refittable'. */
|
||||
const GRFFile *file = _gted[engine].defaultcargo_grf;
|
||||
if (file == nullptr) file = e->GetGRF();
|
||||
if (file != nullptr && file->grf_version >= 8 && !file->cargo_list.empty()) {
|
||||
/* Use first refittable cargo from cargo translation table */
|
||||
uint8_t best_local_slot = UINT8_MAX;
|
||||
for (CargoType cargo_type : SetCargoBitIterator(ei->refit_mask)) {
|
||||
for (CargoType cargo_type : ei->refit_mask) {
|
||||
uint8_t local_slot = file->cargo_map[cargo_type];
|
||||
if (local_slot < best_local_slot) {
|
||||
best_local_slot = local_slot;
|
||||
|
@ -814,7 +815,7 @@ static void CalculateRefitMasks()
|
|||
|
||||
if (!IsValidCargoType(ei->cargo_type)) {
|
||||
/* Use first refittable cargo slot */
|
||||
ei->cargo_type = (CargoType)FindFirstBit(ei->refit_mask);
|
||||
ei->cargo_type = *ei->refit_mask.begin();
|
||||
}
|
||||
}
|
||||
if (!IsValidCargoType(ei->cargo_type) && e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON && e->u.rail.capacity == 0) {
|
||||
|
@ -822,14 +823,14 @@ static void CalculateRefitMasks()
|
|||
* Fallback to the first available instead, if the cargo type has not been changed (as indicated by
|
||||
* cargo_label not being CT_INVALID). */
|
||||
if (GetActiveCargoLabel(ei->cargo_label) != CT_INVALID) {
|
||||
ei->cargo_type = static_cast<CargoType>(FindFirstBit(_standard_cargo_mask));
|
||||
ei->cargo_type = *_standard_cargo_mask.begin();
|
||||
}
|
||||
}
|
||||
if (!IsValidCargoType(ei->cargo_type)) ei->climates = {};
|
||||
|
||||
/* Clear refit_mask for not refittable ships */
|
||||
if (e->type == VEH_SHIP && !e->u.ship.old_refittable) {
|
||||
ei->refit_mask = 0;
|
||||
ei->refit_mask.Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ struct GRFFile {
|
|||
std::vector<GRFLabel> labels{}; ///< List of labels
|
||||
|
||||
std::vector<CargoLabel> cargo_list{}; ///< Cargo translation table (local ID -> label)
|
||||
std::array<uint8_t, NUM_CARGO> cargo_map{}; ///< Inverse cargo translation table (CargoType -> local ID)
|
||||
TypedIndexContainer<std::array<uint8_t, NUM_CARGO>, CargoType> cargo_map{}; ///< Inverse cargo translation table (CargoType -> local ID)
|
||||
|
||||
std::vector<BadgeID> badge_list{}; ///< Badge translation table (local index -> global index)
|
||||
std::unordered_map<uint16_t, BadgeID> badge_map{};
|
||||
|
|
|
@ -153,10 +153,10 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint first, uint last, int pro
|
|||
_gted[e->index].UpdateRefittability(prop == 0x1D && count != 0);
|
||||
if (prop == 0x1D) _gted[e->index].defaultcargo_grf = _cur_gps.grffile;
|
||||
CargoTypes &ctt = prop == 0x1D ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
|
||||
ctt = 0;
|
||||
ctt.Reset();
|
||||
while (count--) {
|
||||
CargoType ctype = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
|
||||
if (IsValidCargoType(ctype)) SetBit(ctt, ctype);
|
||||
if (IsValidCargoType(ctype)) ctt.Set(ctype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -34,16 +34,16 @@ static ChangeInfoResult CargoReserveInfo(uint first, uint last, int prop, ByteRe
|
|||
}
|
||||
|
||||
for (uint id = first; id < last; ++id) {
|
||||
CargoSpec *cs = CargoSpec::Get(id);
|
||||
CargoSpec *cs = CargoSpec::Get(static_cast<CargoType>(id));
|
||||
|
||||
switch (prop) {
|
||||
case 0x08: // Bit number of cargo
|
||||
cs->bitnum = buf.ReadByte();
|
||||
if (cs->IsValid()) {
|
||||
cs->grffile = _cur_gps.grffile;
|
||||
SetBit(_cargo_mask, id);
|
||||
_cargo_mask.Set(cs->Index());
|
||||
} else {
|
||||
ClrBit(_cargo_mask, id);
|
||||
_cargo_mask.Reset(cs->Index());
|
||||
}
|
||||
BuildCargoLabelMap();
|
||||
break;
|
||||
|
|
|
@ -305,7 +305,7 @@ static ChangeInfoResult TownHouseChangeInfo(uint first, uint last, int prop, Byt
|
|||
uint8_t count = buf.ReadByte();
|
||||
for (uint8_t j = 0; j < count; j++) {
|
||||
CargoType cargo = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
|
||||
if (IsValidCargoType(cargo)) SetBit(housespec->watched_cargoes, cargo);
|
||||
if (IsValidCargoType(cargo)) housespec->watched_cargoes.Set(cargo);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -194,10 +194,10 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint first, uint last, int prop, B
|
|||
_gted[e->index].UpdateRefittability(prop == 0x24 && count != 0);
|
||||
if (prop == 0x24) _gted[e->index].defaultcargo_grf = _cur_gps.grffile;
|
||||
CargoTypes &ctt = prop == 0x24 ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
|
||||
ctt = 0;
|
||||
ctt.Reset();
|
||||
while (count--) {
|
||||
CargoType ctype = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
|
||||
if (IsValidCargoType(ctype)) SetBit(ctt, ctype);
|
||||
if (IsValidCargoType(ctype)) ctt.Set(ctype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -173,10 +173,10 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, B
|
|||
_gted[e->index].UpdateRefittability(prop == 0x1E && count != 0);
|
||||
if (prop == 0x1E) _gted[e->index].defaultcargo_grf = _cur_gps.grffile;
|
||||
CargoTypes &ctt = prop == 0x1E ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
|
||||
ctt = 0;
|
||||
ctt.Reset();
|
||||
while (count--) {
|
||||
CargoType ctype = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
|
||||
if (IsValidCargoType(ctype)) SetBit(ctt, ctype);
|
||||
if (IsValidCargoType(ctype)) ctt.Set(ctype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -292,10 +292,10 @@ ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteRead
|
|||
_gted[e->index].UpdateRefittability(prop == 0x2C && count != 0);
|
||||
if (prop == 0x2C) _gted[e->index].defaultcargo_grf = _cur_gps.grffile;
|
||||
CargoTypes &ctt = prop == 0x2C ? _gted[e->index].ctt_include_mask : _gted[e->index].ctt_exclude_mask;
|
||||
ctt = 0;
|
||||
ctt.Reset();
|
||||
while (count--) {
|
||||
CargoType ctype = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
|
||||
if (IsValidCargoType(ctype)) SetBit(ctt, ctype);
|
||||
if (IsValidCargoType(ctype)) ctt.Set(ctype);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -379,7 +379,7 @@ static void CargoMapSpriteGroup(ByteReader &buf, uint8_t idcount)
|
|||
continue;
|
||||
}
|
||||
|
||||
CargoSpec *cs = CargoSpec::Get(cargo_type);
|
||||
CargoSpec *cs = CargoSpec::Get(static_cast<CargoType>(cargo_type));
|
||||
cs->grffile = _cur_gps.grffile;
|
||||
cs->group = _cur_gps.spritegroups[groupid];
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ struct AnimationBase {
|
|||
* @param random_animation Whether to pass random bits to the "next frame" callback.
|
||||
* @param extra_data Custom extra callback data.
|
||||
*/
|
||||
static void AnimateTile(const Tspec *spec, Tobj *obj, TileIndex tile, bool random_animation, Textra extra_data = 0)
|
||||
static void AnimateTile(const Tspec *spec, Tobj *obj, TileIndex tile, bool random_animation, Textra extra_data = {})
|
||||
{
|
||||
assert(spec != nullptr);
|
||||
|
||||
|
@ -128,7 +128,7 @@ struct AnimationBase {
|
|||
* @param trigger What triggered this update? To be passed as parameter to the NewGRF.
|
||||
* @param extra_data Custom extra data for callback processing.
|
||||
*/
|
||||
static void ChangeAnimationFrame(CallbackID cb, const Tspec *spec, Tobj *obj, TileIndex tile, uint32_t random_bits, uint32_t trigger, Textra extra_data = 0)
|
||||
static void ChangeAnimationFrame(CallbackID cb, const Tspec *spec, Tobj *obj, TileIndex tile, uint32_t random_bits, uint32_t trigger, Textra extra_data = {})
|
||||
{
|
||||
uint16_t callback = GetCallback(cb, random_bits, trigger, spec, obj, tile, extra_data);
|
||||
if (callback == CALLBACK_FAILED) return;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "sprite.h"
|
||||
#include "core/alloc_type.hpp"
|
||||
#include "core/convertible_through_base.hpp"
|
||||
#include "command_type.h"
|
||||
#include "direction_type.h"
|
||||
#include "company_type.h"
|
||||
|
@ -454,9 +455,9 @@ struct VariableGRFFileProps : GRFFilePropsBase {
|
|||
* Sprite groups indexed by CargoType.
|
||||
*/
|
||||
struct CargoGRFFileProps : VariableGRFFileProps<CargoType> {
|
||||
static constexpr CargoType SG_DEFAULT = NUM_CARGO; ///< Default type used when no more-specific cargo matches.
|
||||
static constexpr CargoType SG_PURCHASE = NUM_CARGO + 1; ///< Used in purchase lists before an item exists.
|
||||
static constexpr CargoType SG_DEFAULT_NA = NUM_CARGO + 2; ///< Used only by stations and roads when no more-specific cargo matches.
|
||||
static constexpr CargoType SG_DEFAULT{NUM_CARGO}; ///< Default type used when no more-specific cargo matches.
|
||||
static constexpr CargoType SG_PURCHASE{NUM_CARGO + 1}; ///< Used in purchase lists before an item exists.
|
||||
static constexpr CargoType SG_DEFAULT_NA{NUM_CARGO + 2}; ///< Used only by stations and roads when no more-specific cargo matches.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -426,7 +426,7 @@ struct NewGRFInspectWindow : Window {
|
|||
{
|
||||
switch (nip.type) {
|
||||
case NIT_INT: return GetString(STR_JUST_INT, value);
|
||||
case NIT_CARGO: return GetString(IsValidCargoType(value) ? CargoSpec::Get(value)->name : STR_QUANTITY_N_A);
|
||||
case NIT_CARGO: return GetString(IsValidCargoType(static_cast<CargoType>(value)) ? CargoSpec::Get(static_cast<CargoType>(value))->name : STR_QUANTITY_N_A);
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
|||
|
||||
case 0x42: { // Consist cargo information
|
||||
if (!HasBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION)) {
|
||||
std::array<uint8_t, NUM_CARGO> common_cargoes{};
|
||||
TypedIndexContainer<std::array<uint8_t, NUM_CARGO>, CargoType> common_cargoes{};
|
||||
uint8_t cargo_classes = 0;
|
||||
uint8_t user_def_data = 0;
|
||||
|
||||
|
@ -470,12 +470,12 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
|||
|
||||
/* Note: We have to store the untranslated cargotype in the cache as the cache can be read by different NewGRFs,
|
||||
* which will need different translations */
|
||||
v->grf_cache.consist_cargo_information = cargo_classes | (common_cargo_type << 8) | (common_subtype << 16) | (user_def_data << 24);
|
||||
v->grf_cache.consist_cargo_information = cargo_classes | (common_cargo_type.base() << 8) | (common_subtype << 16) | (user_def_data << 24);
|
||||
SetBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION);
|
||||
}
|
||||
|
||||
/* The cargo translation is specific to the accessing GRF, and thus cannot be cached. */
|
||||
CargoType common_cargo_type = (v->grf_cache.consist_cargo_information >> 8) & 0xFF;
|
||||
CargoType common_cargo_type = static_cast<CargoType>(GB(v->grf_cache.consist_cargo_information, 8, 8));
|
||||
|
||||
/* Note:
|
||||
* - Unlike everywhere else the cargo translation table is only used since grf version 8, not 7.
|
||||
|
@ -822,7 +822,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
|||
case 0x36: return v->subspeed;
|
||||
case 0x37: return v->acceleration;
|
||||
case 0x38: break; // not implemented
|
||||
case 0x39: return v->cargo_type;
|
||||
case 0x39: return v->cargo_type.base();
|
||||
case 0x3A: return v->cargo_cap;
|
||||
case 0x3B: return GB(v->cargo_cap, 8, 8);
|
||||
case 0x3C: return ClampTo<uint16_t>(v->cargo.StoredCount());
|
||||
|
|
|
@ -36,7 +36,7 @@ struct GenericScopeResolver : public ScopeResolver {
|
|||
* @param ai_callback Callback comes from the AI.
|
||||
*/
|
||||
GenericScopeResolver(ResolverObject &ro, bool ai_callback)
|
||||
: ScopeResolver(ro), cargo_type(0), default_selection(0), src_industry(0), dst_industry(0), distance(0),
|
||||
: ScopeResolver(ro), cargo_type(INVALID_CARGO), default_selection(0), src_industry(0), dst_industry(0), distance(0),
|
||||
event(), count(0), station_size(0), feature(GSF_INVALID), ai_callback(ai_callback)
|
||||
{
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ void AddGenericCallback(GrfSpecFeature feature, const GRFFile *file, const Sprit
|
|||
switch (variable) {
|
||||
case 0x40: return this->ro.grffile->cargo_map[this->cargo_type];
|
||||
|
||||
case 0x80: return this->cargo_type;
|
||||
case 0x80: return this->cargo_type.base();
|
||||
case 0x81: return CargoSpec::Get(this->cargo_type)->bitnum;
|
||||
case 0x82: return this->default_selection;
|
||||
case 0x83: return this->src_industry;
|
||||
|
|
|
@ -402,7 +402,7 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex start_ti
|
|||
}
|
||||
|
||||
/* Cargo triggered CB 148? */
|
||||
if (HasBit(this->watched_cargo_triggers, cargo_type)) SetBit(res, 4);
|
||||
if (this->watched_cargo_triggers.Test(cargo_type)) SetBit(res, 4);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -739,9 +739,9 @@ void TriggerHouseAnimation_WatchedCargoAccepted(TileIndex tile, CargoTypes trigg
|
|||
HouseID id = GetHouseType(tile);
|
||||
const HouseSpec *hs = HouseSpec::Get(id);
|
||||
|
||||
trigger_cargoes &= hs->watched_cargoes;
|
||||
trigger_cargoes = trigger_cargoes & hs->watched_cargoes;
|
||||
/* None of the trigger cargoes is watched? */
|
||||
if (trigger_cargoes == 0) return;
|
||||
if (trigger_cargoes.None()) return;
|
||||
|
||||
/* Same random value for all tiles of a multi-tile house. */
|
||||
uint16_t r = Random();
|
||||
|
|
|
@ -55,7 +55,7 @@ struct HouseResolverObject : public SpecializedResolverObject<HouseRandomTrigger
|
|||
|
||||
HouseResolverObject(HouseID house_id, TileIndex tile, Town *town,
|
||||
CallbackID callback = CBID_NO_CALLBACK, uint32_t param1 = 0, uint32_t param2 = 0,
|
||||
bool not_yet_constructed = false, uint8_t initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0, int view = 0);
|
||||
bool not_yet_constructed = false, uint8_t initial_random_bits = 0, CargoTypes watched_cargo_triggers = {}, int view = 0);
|
||||
|
||||
ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0) override
|
||||
{
|
||||
|
@ -105,7 +105,7 @@ void TriggerHouseAnimation_ConstructionStageChanged(TileIndex tile, bool first_c
|
|||
void TriggerHouseAnimation_WatchedCargoAccepted(TileIndex tile, CargoTypes trigger_cargoes);
|
||||
|
||||
uint16_t GetHouseCallback(CallbackID callback, uint32_t param1, uint32_t param2, HouseID house_id, Town *town, TileIndex tile, std::span<int32_t> regs100 = {},
|
||||
bool not_yet_constructed = false, uint8_t initial_random_bits = 0, CargoTypes watched_cargo_triggers = 0, int view = 0);
|
||||
bool not_yet_constructed = false, uint8_t initial_random_bits = 0, CargoTypes watched_cargo_triggers = {}, int view = 0);
|
||||
|
||||
bool CanDeleteHouse(TileIndex tile);
|
||||
|
||||
|
|
|
@ -371,7 +371,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(const ResolverObject &objec
|
|||
case 0x87: return this->industry->location.h;// xy dimensions
|
||||
|
||||
case 0x88:
|
||||
case 0x89: return this->industry->GetProduced(variable - 0x88).cargo;
|
||||
case 0x89: return this->industry->GetProduced(variable - 0x88).cargo.base();
|
||||
case 0x8A: return this->industry->GetProduced(0).waiting;
|
||||
case 0x8B: return GB(this->industry->GetProduced(0).waiting, 8, 8);
|
||||
case 0x8C: return this->industry->GetProduced(1).waiting;
|
||||
|
@ -380,7 +380,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(const ResolverObject &objec
|
|||
case 0x8F: return this->industry->GetProduced(variable - 0x8E).rate;
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
case 0x92: return this->industry->GetAccepted(variable - 0x90).cargo;
|
||||
case 0x92: return this->industry->GetAccepted(variable - 0x90).cargo.base();
|
||||
case 0x93: return this->industry->prod_level;
|
||||
/* amount of cargo produced so far THIS month. */
|
||||
case 0x94: return this->industry->GetProduced(0).history[THIS_MONTH].production;
|
||||
|
|
|
@ -232,7 +232,7 @@ RoadStopResolverObject::RoadStopResolverObject(const RoadStopSpec *roadstopspec,
|
|||
/* Pick the first cargo that we have waiting */
|
||||
for (const auto &[cargo, spritegroup] : roadstopspec->grf_prop.spritegroups) {
|
||||
if (cargo < NUM_CARGO && station->goods[cargo].HasData() && station->goods[cargo].GetData().cargo.TotalCount() > 0) {
|
||||
ctype = cargo;
|
||||
ctype = static_cast<CargoType>(cargo);
|
||||
this->root_spritegroup = spritegroup;
|
||||
break;
|
||||
}
|
||||
|
@ -422,18 +422,15 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
|||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
* to bother with any further processing.
|
||||
* Note: cached_roadstop_cargo_triggers must be non-zero even for cargo-independent triggers. */
|
||||
if (st->cached_roadstop_cargo_triggers == 0) return;
|
||||
if (IsValidCargoType(cargo_type) && !HasBit(st->cached_roadstop_cargo_triggers, cargo_type)) return;
|
||||
if (st->cached_roadstop_cargo_triggers.None()) return;
|
||||
if (IsValidCargoType(cargo_type) && !st->cached_roadstop_cargo_triggers.Test(cargo_type)) return;
|
||||
|
||||
st->waiting_random_triggers.Set(trigger);
|
||||
|
||||
uint32_t whole_reseed = 0;
|
||||
|
||||
/* Bitmask of completely empty cargo types to be matched. */
|
||||
CargoTypes empty_mask{};
|
||||
if (trigger == StationRandomTrigger::CargoTaken) {
|
||||
empty_mask = GetEmptyMask(Station::From(st));
|
||||
}
|
||||
CargoTypes not_empty_mask = (trigger == StationRandomTrigger::CargoTaken) ? GetEmptyMask(Station::From(st)).Flip() : ALL_CARGOTYPES;
|
||||
|
||||
StationRandomTriggers used_random_triggers;
|
||||
auto process_tile = [&](TileIndex cur_tile) {
|
||||
|
@ -443,10 +440,10 @@ void TriggerRoadStopRandomisation(BaseStation *st, TileIndex tile, StationRandom
|
|||
/* Cargo taken "will only be triggered if all of those
|
||||
* cargo types have no more cargo waiting." */
|
||||
if (trigger == StationRandomTrigger::CargoTaken) {
|
||||
if ((ss->cargo_triggers & ~empty_mask) != 0) return;
|
||||
if (ss->cargo_triggers.Any(not_empty_mask)) return;
|
||||
}
|
||||
|
||||
if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
if (!IsValidCargoType(cargo_type) || ss->cargo_triggers.Test(cargo_type)) {
|
||||
RoadStopResolverObject object(ss, st, cur_tile, INVALID_ROADTYPE, GetStationType(cur_tile), GetStationGfx(cur_tile));
|
||||
object.SetWaitingRandomTriggers(st->waiting_random_triggers);
|
||||
|
||||
|
@ -621,7 +618,7 @@ void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex)
|
|||
} else {
|
||||
st->roadstop_speclist.clear();
|
||||
st->cached_roadstop_anim_triggers = {};
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers.Reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -636,13 +633,13 @@ void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex)
|
|||
void RoadStopUpdateCachedTriggers(BaseStation *st)
|
||||
{
|
||||
st->cached_roadstop_anim_triggers = {};
|
||||
st->cached_roadstop_cargo_triggers = 0;
|
||||
st->cached_roadstop_cargo_triggers.Reset();
|
||||
|
||||
/* Combine animation trigger bitmask for all road stop specs
|
||||
* of this station. */
|
||||
for (const auto &sm : GetStationSpecList<RoadStopSpec>(st)) {
|
||||
if (sm.spec == nullptr) continue;
|
||||
st->cached_roadstop_anim_triggers.Set(sm.spec->animation.triggers);
|
||||
st->cached_roadstop_cargo_triggers |= sm.spec->cargo_triggers;
|
||||
st->cached_roadstop_cargo_triggers.Set(sm.spec->cargo_triggers);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ struct RoadStopSpec : NewGRFSpecBase<RoadStopClassID> {
|
|||
RoadStopCallbackMasks callback_mask{};
|
||||
RoadStopSpecFlags flags{};
|
||||
|
||||
CargoTypes cargo_triggers = 0; ///< Bitmask of cargo types which cause trigger re-randomizing
|
||||
CargoTypes cargo_triggers{}; ///< Bitmask of cargo types which cause trigger re-randomizing
|
||||
|
||||
AnimationInfo<StationAnimationTriggers> animation;
|
||||
|
||||
|
|
|
@ -415,7 +415,7 @@ uint32_t Station::GetNewGRFVariable(const ResolverObject &object, uint8_t variab
|
|||
{
|
||||
switch (variable) {
|
||||
case 0x48: { // Accepted cargo types
|
||||
uint32_t value = GetAcceptanceMask(this);
|
||||
uint32_t value = GetAcceptanceMask(this).base();
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -514,14 +514,14 @@ uint32_t Waypoint::GetNewGRFVariable(const ResolverObject &, uint8_t variable, [
|
|||
uint cargo = 0;
|
||||
const Station *st = Station::From(this->station_scope.st);
|
||||
|
||||
switch (this->station_scope.cargo_type) {
|
||||
case INVALID_CARGO:
|
||||
case CargoGRFFileProps::SG_DEFAULT_NA:
|
||||
case CargoGRFFileProps::SG_PURCHASE:
|
||||
switch (this->station_scope.cargo_type.base()) {
|
||||
case INVALID_CARGO.base():
|
||||
case CargoGRFFileProps::SG_DEFAULT_NA.base():
|
||||
case CargoGRFFileProps::SG_PURCHASE.base():
|
||||
cargo = 0;
|
||||
break;
|
||||
|
||||
case CargoGRFFileProps::SG_DEFAULT:
|
||||
case CargoGRFFileProps::SG_DEFAULT.base():
|
||||
for (const GoodsEntry &ge : st->goods) {
|
||||
if (!ge.HasData()) continue;
|
||||
cargo += ge.GetData().cargo.TotalCount();
|
||||
|
@ -771,7 +771,7 @@ void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex)
|
|||
} else {
|
||||
st->speclist.clear();
|
||||
st->cached_anim_triggers = {};
|
||||
st->cached_cargo_triggers = 0;
|
||||
st->cached_cargo_triggers.Reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -948,17 +948,14 @@ void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, Statio
|
|||
/* Check the cached cargo trigger bitmask to see if we need
|
||||
* to bother with any further processing.
|
||||
* Note: cached_cargo_triggers must be non-zero even for cargo-independent triggers. */
|
||||
if (st->cached_cargo_triggers == 0) return;
|
||||
if (IsValidCargoType(cargo_type) && !HasBit(st->cached_cargo_triggers, cargo_type)) return;
|
||||
if (st->cached_cargo_triggers.None()) return;
|
||||
if (IsValidCargoType(cargo_type) && !st->cached_cargo_triggers.Test(cargo_type)) return;
|
||||
|
||||
uint32_t whole_reseed = 0;
|
||||
ETileArea area = ETileArea(st, trigger_tile, tas[static_cast<size_t>(trigger)]);
|
||||
|
||||
/* Bitmask of completely empty cargo types to be matched. */
|
||||
CargoTypes empty_mask{};
|
||||
if (trigger == StationRandomTrigger::CargoTaken) {
|
||||
empty_mask = GetEmptyMask(Station::From(st));
|
||||
}
|
||||
CargoTypes not_empty_mask = (trigger == StationRandomTrigger::CargoTaken) ? GetEmptyMask(Station::From(st)).Flip() : ALL_CARGOTYPES;
|
||||
|
||||
/* Store triggers now for var 5F */
|
||||
st->waiting_random_triggers.Set(trigger);
|
||||
|
@ -973,10 +970,10 @@ void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, Statio
|
|||
/* Cargo taken "will only be triggered if all of those
|
||||
* cargo types have no more cargo waiting." */
|
||||
if (trigger == StationRandomTrigger::CargoTaken) {
|
||||
if ((ss->cargo_triggers & ~empty_mask) != 0) continue;
|
||||
if (ss->cargo_triggers.Any(not_empty_mask)) continue;
|
||||
}
|
||||
|
||||
if (!IsValidCargoType(cargo_type) || HasBit(ss->cargo_triggers, cargo_type)) {
|
||||
if (!IsValidCargoType(cargo_type) || ss->cargo_triggers.Test(cargo_type)) {
|
||||
StationResolverObject object(ss, st, tile, CBID_RANDOM_TRIGGER, 0);
|
||||
object.SetWaitingRandomTriggers(st->waiting_random_triggers);
|
||||
|
||||
|
@ -1016,14 +1013,14 @@ void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, Statio
|
|||
void StationUpdateCachedTriggers(BaseStation *st)
|
||||
{
|
||||
st->cached_anim_triggers = {};
|
||||
st->cached_cargo_triggers = 0;
|
||||
st->cached_cargo_triggers.Reset();
|
||||
|
||||
/* Combine animation trigger bitmask for all station specs
|
||||
* of this station. */
|
||||
for (const auto &sm : GetStationSpecList<StationSpec>(st)) {
|
||||
if (sm.spec == nullptr) continue;
|
||||
st->cached_anim_triggers.Set(sm.spec->animation.triggers);
|
||||
st->cached_cargo_triggers |= sm.spec->cargo_triggers;
|
||||
st->cached_cargo_triggers.Set(sm.spec->cargo_triggers);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ using StationSpecFlags = EnumBitSet<StationSpecFlag, uint8_t>;
|
|||
struct StationSpec : NewGRFSpecBase<StationClassID> {
|
||||
StationSpec() : name(0),
|
||||
disallowed_platforms(0), disallowed_lengths(0),
|
||||
cargo_threshold(0), cargo_triggers(0),
|
||||
cargo_threshold(0), cargo_triggers{},
|
||||
callback_mask(0), flags(0)
|
||||
{}
|
||||
|
||||
|
|
|
@ -862,7 +862,7 @@ static void ProcessNewGRFStringControlCode(char32_t scc, StringConsumer &consume
|
|||
|
||||
case SCC_NEWGRF_PRINT_WORD_CARGO_NAME: {
|
||||
CargoType cargo = GetCargoTranslation(stack.PopUnsignedWord(), stack.grffile);
|
||||
params.emplace_back(cargo < NUM_CARGO ? 1ULL << cargo : 0);
|
||||
params.emplace_back(cargo < NUM_CARGO ? CargoTypes{cargo}.base() : 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -635,7 +635,7 @@ static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, Carg
|
|||
CargoType pass = GetCargoTypeByLabel(CT_PASSENGERS);
|
||||
if (IsValidCargoType(pass)) {
|
||||
acceptance[pass] += std::max(1U, level);
|
||||
SetBit(always_accepted, pass);
|
||||
always_accepted.Set(pass);
|
||||
}
|
||||
|
||||
/* Top town building generates 4, HQ can make up to 8. The
|
||||
|
@ -645,7 +645,7 @@ static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, Carg
|
|||
CargoType mail = GetCargoTypeByLabel(CT_MAIL);
|
||||
if (IsValidCargoType(mail)) {
|
||||
acceptance[mail] += std::max(1U, level / 2);
|
||||
SetBit(always_accepted, mail);
|
||||
always_accepted.Set(mail);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ void DrawRoadVehDetails(const Vehicle *v, const Rect &r)
|
|||
|
||||
if (v->HasArticulatedPart()) {
|
||||
CargoArray max_cargo{};
|
||||
std::array<StringID, NUM_CARGO> subtype_text{};
|
||||
TypedIndexContainer<std::array<StringID, NUM_CARGO>, CargoType> subtype_text{};
|
||||
|
||||
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||
max_cargo[u->cargo_type] += u->cargo_cap;
|
||||
|
|
|
@ -359,7 +359,7 @@ public:
|
|||
|
||||
SLE_CONDVAR(CompanyEconomyEntry, delivered_cargo[NUM_CARGO - 1], SLE_INT32, SL_MIN_VERSION, SLV_170),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, 32, SLV_170, SLV_EXTEND_CARGOTYPES),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_CONDARR(CompanyEconomyEntry, delivered_cargo, SLE_UINT32, NUM_CARGO, SLV_EXTEND_CARGOTYPES, SL_MAX_VERSION),
|
||||
SLE_VAR(CompanyEconomyEntry, performance_history, SLE_INT32),
|
||||
};
|
||||
static inline const SaveLoadCompatTable compat_description = _company_economy_compat;
|
||||
|
|
|
@ -383,7 +383,7 @@ public:
|
|||
{
|
||||
Station *st = Station::From(bst);
|
||||
|
||||
SlSetStructListLength(NUM_CARGO);
|
||||
SlSetStructListLength(std::size(st->goods));
|
||||
|
||||
for (GoodsEntry &ge : st->goods) {
|
||||
SlStationGoods::cargo_reserved_count = ge.HasData() ? ge.GetData().cargo.reserved_count : 0;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
{
|
||||
if (!IsValidCargo(cargo_type)) return std::nullopt;
|
||||
|
||||
return ::StrMakeValid(::GetString(STR_JUST_CARGO_LIST, 1ULL << cargo_type), {});
|
||||
return ::StrMakeValid(::GetString(STR_JUST_CARGO_LIST, CargoTypes{cargo_type}), {});
|
||||
}
|
||||
|
||||
/* static */ std::optional<std::string> ScriptCargo::GetCargoLabel(CargoType cargo_type)
|
||||
|
|
|
@ -60,9 +60,9 @@ public:
|
|||
*/
|
||||
enum SpecialCargoType {
|
||||
/* Note: these values represent part of the in-game CargoTypes enum */
|
||||
CT_AUTO_REFIT = ::CARGO_AUTO_REFIT, ///< Automatically choose cargo type when doing auto-refitting.
|
||||
CT_NO_REFIT = ::CARGO_NO_REFIT, ///< Do not refit cargo of a vehicle.
|
||||
CT_INVALID = ::INVALID_CARGO, ///< An invalid cargo type.
|
||||
CT_AUTO_REFIT = ::CARGO_AUTO_REFIT.base(), ///< Automatically choose cargo type when doing auto-refitting.
|
||||
CT_NO_REFIT = ::CARGO_NO_REFIT.base(), ///< Do not refit cargo of a vehicle.
|
||||
CT_INVALID = ::INVALID_CARGO.base(), ///< An invalid cargo type.
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
ScriptCargoList::ScriptCargoList()
|
||||
{
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
this->AddItem(cs->Index());
|
||||
this->AddItem(cs->Index().base());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ ScriptCargoList_IndustryAccepting::ScriptCargoList_IndustryAccepting(IndustryID
|
|||
const Industry *ind = ::Industry::Get(industry_id);
|
||||
for (const auto &a : ind->accepted) {
|
||||
if (::IsValidCargoType(a.cargo)) {
|
||||
this->AddItem(a.cargo);
|
||||
this->AddItem(a.cargo.base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ ScriptCargoList_IndustryProducing::ScriptCargoList_IndustryProducing(IndustryID
|
|||
const Industry *ind = ::Industry::Get(industry_id);
|
||||
for (const auto &p : ind->produced) {
|
||||
if (::IsValidCargoType(p.cargo)) {
|
||||
this->AddItem(p.cargo);
|
||||
this->AddItem(p.cargo.base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ ScriptCargoList_StationAccepting::ScriptCargoList_StationAccepting(StationID sta
|
|||
if (!ScriptStation::IsValidStation(station_id)) return;
|
||||
|
||||
const Station *st = ::Station::Get(station_id);
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
if (st->goods[cargo].status.Test(GoodsEntry::State::Acceptance)) this->AddItem(cargo);
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
if (st->goods[cargo].status.Test(GoodsEntry::State::Acceptance)) this->AddItem(cargo.base());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
if (!IsValidEngine(engine_id)) return false;
|
||||
if (!ScriptCargo::IsValidCargo(cargo_type)) return false;
|
||||
|
||||
return HasBit(::GetUnionOfArticulatedRefitMasks(engine_id, true), cargo_type);
|
||||
return ::GetUnionOfArticulatedRefitMasks(engine_id, true).Test(cargo_type);
|
||||
}
|
||||
|
||||
/* static */ bool ScriptEngine::CanPullCargo(EngineID engine_id, CargoType cargo_type)
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
ScriptList *list = new ScriptList();
|
||||
for (const CargoType &cargo : ins->produced_cargo) {
|
||||
if (::IsValidCargoType(cargo)) list->AddItem(cargo);
|
||||
if (::IsValidCargoType(cargo)) list->AddItem(cargo.base());
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -86,7 +86,7 @@
|
|||
|
||||
ScriptList *list = new ScriptList();
|
||||
for (const CargoType &cargo : ins->accepts_cargo) {
|
||||
if (::IsValidCargoType(cargo)) list->AddItem(cargo);
|
||||
if (::IsValidCargoType(cargo)) list->AddItem(cargo.base());
|
||||
}
|
||||
|
||||
return list;
|
||||
|
|
|
@ -227,7 +227,7 @@ void BuildLinkStatsLegend()
|
|||
|
||||
_legend_linkstats[i].legend = cs->name;
|
||||
_legend_linkstats[i].colour = cs->legend_colour;
|
||||
_legend_linkstats[i].type = cs->Index();
|
||||
_legend_linkstats[i].type = cs->Index().base(); /// IndustryType!?
|
||||
_legend_linkstats[i].show_on_map = true;
|
||||
}
|
||||
|
||||
|
@ -1254,9 +1254,9 @@ protected:
|
|||
*/
|
||||
void SetOverlayCargoMask()
|
||||
{
|
||||
CargoTypes cargo_mask = 0;
|
||||
CargoTypes cargo_mask{};
|
||||
for (int i = 0; i != _smallmap_cargo_count; ++i) {
|
||||
if (_legend_linkstats[i].show_on_map) SetBit(cargo_mask, _legend_linkstats[i].type);
|
||||
if (_legend_linkstats[i].show_on_map) cargo_mask.Set(static_cast<CargoType>(_legend_linkstats[i].type));
|
||||
}
|
||||
this->overlay->SetCargoMask(cargo_mask);
|
||||
}
|
||||
|
@ -1453,7 +1453,7 @@ public:
|
|||
SmallMapWindow(WindowDesc &desc, int window_number) : Window(desc)
|
||||
{
|
||||
_smallmap_industry_highlight = IT_INVALID;
|
||||
this->overlay = std::make_unique<LinkGraphOverlay>(this, WID_SM_MAP, 0, this->GetOverlayCompanyMask(), 1);
|
||||
this->overlay = std::make_unique<LinkGraphOverlay>(this, WID_SM_MAP, CargoTypes{}, this->GetOverlayCompanyMask(), 1);
|
||||
this->CreateNestedTree();
|
||||
this->LowerWidget(WID_SM_CONTOUR + this->map_type);
|
||||
|
||||
|
|
|
@ -535,7 +535,7 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
|
|||
|
||||
struct GrfSpriteOffset {
|
||||
size_t file_pos;
|
||||
uint8_t control_flags;
|
||||
SpriteCacheCtrlFlags control_flags{};
|
||||
};
|
||||
|
||||
/** Map from sprite numbers to position in the GRF file. */
|
||||
|
@ -565,7 +565,7 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
|||
size_t old_pos = file.GetPos();
|
||||
file.SeekTo(data_offset, SEEK_CUR);
|
||||
|
||||
GrfSpriteOffset offset = { 0, 0 };
|
||||
GrfSpriteOffset offset{0};
|
||||
|
||||
/* Loop over all sprite section entries and store the file
|
||||
* offset for each newly encountered ID. */
|
||||
|
@ -574,7 +574,6 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
|||
if (id != prev_id) {
|
||||
_grf_sprite_offsets[prev_id] = offset;
|
||||
offset.file_pos = file.GetPos() - 4;
|
||||
offset.control_flags = 0;
|
||||
}
|
||||
prev_id = id;
|
||||
uint length = file.ReadDword();
|
||||
|
@ -585,11 +584,11 @@ void ReadGRFSpriteOffsets(SpriteFile &file)
|
|||
uint8_t zoom = file.ReadByte();
|
||||
length--;
|
||||
if (colour.Any() && zoom == 0) { // ZoomLevel::Normal (normal zoom)
|
||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL);
|
||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL);
|
||||
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin1x32bpp : SpriteCacheCtrlFlag::AllowZoomMin1xPal);
|
||||
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal);
|
||||
}
|
||||
if (colour.Any() && zoom == 2) { // ZoomLevel::In2x (2x zoomed in)
|
||||
SetBit(offset.control_flags, (colour != SpriteComponent::Palette) ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL);
|
||||
offset.control_flags.Set((colour != SpriteComponent::Palette) ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +620,7 @@ bool LoadNextSprite(SpriteID load_index, SpriteFile &file, uint file_sprite_id)
|
|||
uint8_t grf_type = file.ReadByte();
|
||||
|
||||
SpriteType type;
|
||||
uint8_t control_flags = 0;
|
||||
SpriteCacheCtrlFlags control_flags;
|
||||
if (grf_type == 0xFF) {
|
||||
/* Some NewGRF files have "empty" pseudo-sprites which are 1
|
||||
* byte long. Catch these so the sprites won't be displayed. */
|
||||
|
|
|
@ -11,24 +11,9 @@
|
|||
#define SPRITECACHE_H
|
||||
|
||||
#include "gfx_type.h"
|
||||
#include "spritecache_type.h"
|
||||
#include "spriteloader/spriteloader.hpp"
|
||||
|
||||
/** Data structure describing a sprite. */
|
||||
struct Sprite {
|
||||
uint16_t height; ///< Height of the sprite.
|
||||
uint16_t width; ///< Width of the sprite.
|
||||
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
||||
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
||||
std::byte data[]; ///< Sprite data.
|
||||
};
|
||||
|
||||
enum SpriteCacheCtrlFlags : uint8_t {
|
||||
SCCF_ALLOW_ZOOM_MIN_1X_PAL = 0, ///< Allow use of sprite min zoom setting at 1x in palette mode.
|
||||
SCCF_ALLOW_ZOOM_MIN_1X_32BPP = 1, ///< Allow use of sprite min zoom setting at 1x in 32bpp mode.
|
||||
SCCF_ALLOW_ZOOM_MIN_2X_PAL = 2, ///< Allow use of sprite min zoom setting at 2x in palette mode.
|
||||
SCCF_ALLOW_ZOOM_MIN_2X_32BPP = 3, ///< Allow use of sprite min zoom setting at 2x in 32bpp mode.
|
||||
};
|
||||
|
||||
extern uint _sprite_cache_size;
|
||||
|
||||
/** SpriteAllocator that allocates memory via a unique_ptr array. */
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "core/math_func.hpp"
|
||||
#include "gfx_type.h"
|
||||
#include "spritecache_type.h"
|
||||
#include "spriteloader/spriteloader.hpp"
|
||||
|
||||
#include "table/sprites.h"
|
||||
|
@ -27,7 +28,7 @@ struct SpriteCache {
|
|||
uint32_t lru = 0;
|
||||
SpriteType type = SpriteType::Invalid; ///< In some cases a single sprite is misused by two NewGRFs. Once as real sprite and once as recolour sprite. If the recolour sprite gets into the cache it might be drawn as real sprite which causes enormous trouble.
|
||||
bool warned = false; ///< True iff the user has been warned about incorrect use of this sprite
|
||||
uint8_t control_flags = 0; ///< Control flags, see SpriteCacheCtrlFlags
|
||||
SpriteCacheCtrlFlags control_flags{}; ///< Control flags, see SpriteCacheCtrlFlags
|
||||
|
||||
void ClearSpriteData();
|
||||
};
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file spritecache_type.h Types related to the sprite cache. */
|
||||
|
||||
#ifndef SPRITECACHE_TYPE_H
|
||||
#define SPRITECACHE_TYPE_H
|
||||
|
||||
#include "core/enum_type.hpp"
|
||||
|
||||
/** Data structure describing a sprite. */
|
||||
struct Sprite {
|
||||
uint16_t height; ///< Height of the sprite.
|
||||
uint16_t width; ///< Width of the sprite.
|
||||
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
||||
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
||||
std::byte data[]; ///< Sprite data.
|
||||
};
|
||||
|
||||
enum class SpriteCacheCtrlFlag : uint8_t {
|
||||
AllowZoomMin1xPal, ///< Allow use of sprite min zoom setting at 1x in palette mode.
|
||||
AllowZoomMin1x32bpp, ///< Allow use of sprite min zoom setting at 1x in 32bpp mode.
|
||||
AllowZoomMin2xPal, ///< Allow use of sprite min zoom setting at 2x in palette mode.
|
||||
AllowZoomMin2x32bpp, ///< Allow use of sprite min zoom setting at 2x in 32bpp mode.
|
||||
};
|
||||
|
||||
using SpriteCacheCtrlFlags = EnumBitSet<SpriteCacheCtrlFlag, uint8_t>;
|
||||
|
||||
#endif /* SPRITECACHE_TYPE_H */
|
|
@ -256,7 +256,7 @@ static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
|||
return {};
|
||||
}
|
||||
|
||||
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
{
|
||||
static const ZoomLevel zoom_lvl_map[6] = {ZoomLevel::Normal, ZoomLevel::In4x, ZoomLevel::In2x, ZoomLevel::Out2x, ZoomLevel::Out4x, ZoomLevel::Out8x};
|
||||
|
||||
|
@ -295,11 +295,11 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
|||
is_wanted_zoom_lvl = true;
|
||||
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZoomLevel::Min : _settings_client.gui.sprite_zoom_min;
|
||||
if (zoom_min >= ZoomLevel::In2x &&
|
||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl < ZoomLevel::In2x) {
|
||||
control_flags.Test(load_32bpp ? SpriteCacheCtrlFlag::AllowZoomMin2x32bpp : SpriteCacheCtrlFlag::AllowZoomMin2xPal) && zoom_lvl < ZoomLevel::In2x) {
|
||||
is_wanted_zoom_lvl = false;
|
||||
}
|
||||
if (zoom_min >= ZoomLevel::Normal &&
|
||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl < ZoomLevel::Normal) {
|
||||
control_flags.Test(load_32bpp ? SpriteCacheCtrlFlag::AllowZoomMin1x32bpp : SpriteCacheCtrlFlag::AllowZoomMin1xPal) && zoom_lvl < ZoomLevel::Normal) {
|
||||
is_wanted_zoom_lvl = false;
|
||||
}
|
||||
} else {
|
||||
|
@ -359,7 +359,7 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
|||
return loaded_sprites;
|
||||
}
|
||||
|
||||
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
{
|
||||
if (this->container_ver >= 2) {
|
||||
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderGrf : public SpriteLoader {
|
|||
uint8_t container_ver;
|
||||
public:
|
||||
SpriteLoaderGrf(uint8_t container_ver) : container_ver(container_ver) {}
|
||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||
};
|
||||
|
||||
#endif /* SPRITELOADER_GRF_HPP */
|
||||
|
|
|
@ -48,7 +48,7 @@ static void Convert32bppTo8bpp(SpriteLoader::Sprite &sprite)
|
|||
}
|
||||
}
|
||||
|
||||
ZoomLevels SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
ZoomLevels SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
||||
{
|
||||
ZoomLevels avail = this->baseloader.LoadSprite(sprite, file, file_pos, sprite_type, true, control_flags, avail_8bpp, avail_32bpp);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderMakeIndexed : public SpriteLoader {
|
|||
SpriteLoader &baseloader;
|
||||
public:
|
||||
SpriteLoaderMakeIndexed(SpriteLoader &baseloader) : baseloader(baseloader) {}
|
||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
||||
};
|
||||
|
||||
#endif /* SPRITELOADER_MAKEINDEXED_H */
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "../core/alloc_type.hpp"
|
||||
#include "../core/enum_type.hpp"
|
||||
#include "../gfx_type.h"
|
||||
#include "../spritecache_type.h"
|
||||
#include "sprite_file_type.hpp"
|
||||
|
||||
struct Sprite;
|
||||
|
@ -94,7 +95,7 @@ public:
|
|||
* @param[out] avail_32bpp Available 32bpp sprites.
|
||||
* @return Available sprites matching \a load_32bpp.
|
||||
*/
|
||||
virtual ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) = 0;
|
||||
virtual ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCacheCtrlFlags control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) = 0;
|
||||
|
||||
virtual ~SpriteLoader() = default;
|
||||
};
|
||||
|
|
|
@ -100,7 +100,7 @@ Station::~Station()
|
|||
if (a->targetairport == this->index) a->targetairport = StationID::Invalid();
|
||||
}
|
||||
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
LinkGraph *lg = LinkGraph::GetIfValid(this->goods[cargo].link_graph);
|
||||
if (lg == nullptr) continue;
|
||||
|
||||
|
|
|
@ -526,7 +526,7 @@ public:
|
|||
|
||||
uint8_t last_vehicle_type = 0;
|
||||
std::list<Vehicle *> loading_vehicles{};
|
||||
std::array<GoodsEntry, NUM_CARGO> goods; ///< Goods at this station
|
||||
TypedIndexContainer<std::array<GoodsEntry, NUM_CARGO>, CargoType> goods; ///< Goods at this station
|
||||
CargoTypes always_accepted{}; ///< Bitmask of always accepted cargo types (by houses, HQs, industry tiles when industry doesn't accept cargo)
|
||||
|
||||
IndustryList industries_near{}; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry()
|
||||
|
|
|
@ -499,10 +499,10 @@ void ClearAllStationCachedNames()
|
|||
*/
|
||||
CargoTypes GetAcceptanceMask(const Station *st)
|
||||
{
|
||||
CargoTypes mask = 0;
|
||||
CargoTypes mask{};
|
||||
|
||||
for (auto it = std::begin(st->goods); it != std::end(st->goods); ++it) {
|
||||
if (it->status.Test(GoodsEntry::State::Acceptance)) SetBit(mask, std::distance(std::begin(st->goods), it));
|
||||
if (it->status.Test(GoodsEntry::State::Acceptance)) mask.Set(static_cast<CargoType>(std::distance(std::begin(st->goods), it)));
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
@ -514,10 +514,10 @@ CargoTypes GetAcceptanceMask(const Station *st)
|
|||
*/
|
||||
CargoTypes GetEmptyMask(const Station *st)
|
||||
{
|
||||
CargoTypes mask = 0;
|
||||
CargoTypes mask{};
|
||||
|
||||
for (auto it = std::begin(st->goods); it != std::end(st->goods); ++it) {
|
||||
if (!it->HasData() || it->GetData().cargo.TotalCount() == 0) SetBit(mask, std::distance(std::begin(st->goods), it));
|
||||
if (!it->HasData() || it->GetData().cargo.TotalCount() == 0) mask.Set(static_cast<CargoType>(std::distance(std::begin(st->goods), it)));
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
@ -582,7 +582,7 @@ CargoArray GetProductionAroundTiles(TileIndex north_tile, int w, int h, int rad)
|
|||
CargoArray GetAcceptanceAroundTiles(TileIndex center_tile, int w, int h, int rad, CargoTypes *always_accepted)
|
||||
{
|
||||
CargoArray acceptance{};
|
||||
if (always_accepted != nullptr) *always_accepted = 0;
|
||||
if (always_accepted != nullptr) always_accepted->Reset();
|
||||
|
||||
TileArea ta = TileArea(center_tile, w, h).Expand(rad);
|
||||
|
||||
|
@ -604,7 +604,7 @@ CargoArray GetAcceptanceAroundTiles(TileIndex center_tile, int w, int h, int rad
|
|||
static CargoArray GetAcceptanceAroundStation(const Station *st, CargoTypes *always_accepted)
|
||||
{
|
||||
CargoArray acceptance{};
|
||||
if (always_accepted != nullptr) *always_accepted = 0;
|
||||
if (always_accepted != nullptr) always_accepted->Reset();
|
||||
|
||||
BitmapTileIterator it(st->catchment_tiles);
|
||||
for (TileIndex tile = it; tile != INVALID_TILE; tile = ++it) {
|
||||
|
@ -631,7 +631,7 @@ void UpdateStationAcceptance(Station *st, bool show_msg)
|
|||
}
|
||||
|
||||
/* Adjust in case our station only accepts fewer kinds of goods */
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
uint amt = acceptance[cargo];
|
||||
|
||||
/* Make sure the station can accept the goods type. */
|
||||
|
@ -655,12 +655,12 @@ void UpdateStationAcceptance(Station *st, bool show_msg)
|
|||
/* show a message to report that the acceptance was changed? */
|
||||
if (show_msg && st->owner == _local_company && st->IsInUse()) {
|
||||
/* Combine old and new masks to get changes */
|
||||
CargoTypes accepts = new_acc & ~old_acc;
|
||||
CargoTypes rejects = ~new_acc & old_acc;
|
||||
CargoTypes accepts = new_acc & CargoTypes{old_acc}.Flip();
|
||||
CargoTypes rejects = CargoTypes{new_acc}.Flip() & old_acc;
|
||||
|
||||
/* Show news message if there are any changes */
|
||||
if (accepts != 0) ShowRejectOrAcceptNews(st, accepts, false);
|
||||
if (rejects != 0) ShowRejectOrAcceptNews(st, rejects, true);
|
||||
if (accepts.Any()) ShowRejectOrAcceptNews(st, accepts, false);
|
||||
if (rejects.Any()) ShowRejectOrAcceptNews(st, rejects, true);
|
||||
}
|
||||
|
||||
/* redraw the station view since acceptance changed */
|
||||
|
@ -3760,13 +3760,13 @@ static VehicleEnterTileStates VehicleEnter_Station(Vehicle *v, TileIndex tile, i
|
|||
void TriggerWatchedCargoCallbacks(Station *st)
|
||||
{
|
||||
/* Collect cargoes accepted since the last big tick. */
|
||||
CargoTypes cargoes = 0;
|
||||
for (CargoType cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
|
||||
if (st->goods[cargo_type].status.Test(GoodsEntry::State::AcceptedBigtick)) SetBit(cargoes, cargo_type);
|
||||
CargoTypes cargoes{};
|
||||
for (CargoType cargo_type{}; cargo_type < NUM_CARGO; ++cargo_type) {
|
||||
if (st->goods[cargo_type].status.Test(GoodsEntry::State::AcceptedBigtick)) cargoes.Set(cargo_type);
|
||||
}
|
||||
|
||||
/* Anything to do? */
|
||||
if (cargoes == 0) return;
|
||||
if (cargoes.None()) return;
|
||||
|
||||
/* Loop over all houses in the catchment. */
|
||||
BitmapTileIterator it(st->catchment_tiles);
|
||||
|
@ -4027,7 +4027,7 @@ void RerouteCargo(Station *st, CargoType cargo, StationID avoid, StationID avoid
|
|||
*/
|
||||
void DeleteStaleLinks(Station *from)
|
||||
{
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
const bool auto_distributed = (_settings_game.linkgraph.GetDistributionType(cargo) != DT_MANUAL);
|
||||
GoodsEntry &ge = from->goods[cargo];
|
||||
LinkGraph *lg = LinkGraph::GetIfValid(ge.link_graph);
|
||||
|
|
|
@ -76,7 +76,7 @@ using RoadWaypointTypeFilter = GenericWaypointTypeFilter<true, MP_ROAD>;
|
|||
int DrawStationCoverageAreaText(const Rect &r, StationCoverageType sct, int rad, bool supplies)
|
||||
{
|
||||
TileIndex tile = TileVirtXY(_thd.pos.x, _thd.pos.y);
|
||||
CargoTypes cargo_mask = 0;
|
||||
CargoTypes cargo_mask{};
|
||||
if (_thd.drawstyle == HT_RECT && tile < Map::Size()) {
|
||||
CargoArray cargoes;
|
||||
if (supplies) {
|
||||
|
@ -86,14 +86,14 @@ int DrawStationCoverageAreaText(const Rect &r, StationCoverageType sct, int rad,
|
|||
}
|
||||
|
||||
/* Convert cargo counts to a set of cargo bits, and draw the result. */
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
switch (sct) {
|
||||
case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(cargo, CargoClass::Passengers)) continue; break;
|
||||
case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(cargo, CargoClass::Passengers)) continue; break;
|
||||
case SCT_ALL: break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
if (cargoes[cargo] >= (supplies ? 1U : 8U)) SetBit(cargo_mask, cargo);
|
||||
if (cargoes[cargo] >= (supplies ? 1U : 8U)) cargo_mask.Set(cargo);
|
||||
}
|
||||
}
|
||||
return DrawStringMultiLine(r, GetString(supplies ? STR_STATION_BUILD_SUPPLIES_CARGO : STR_STATION_BUILD_ACCEPTS_CARGO, cargo_mask));
|
||||
|
@ -291,7 +291,7 @@ protected:
|
|||
Scrollbar *vscroll = nullptr;
|
||||
uint rating_width = 0;
|
||||
bool filter_expanded = false;
|
||||
std::array<uint16_t, NUM_CARGO> stations_per_cargo_type{}; ///< Number of stations with a rating for each cargo type.
|
||||
TypedIndexContainer<std::array<uint16_t, NUM_CARGO>, CargoType> stations_per_cargo_type{}; ///< Number of stations with a rating for each cargo type.
|
||||
uint16_t stations_per_cargo_type_no_rating = 0; ///< Number of stations without a rating.
|
||||
|
||||
/**
|
||||
|
@ -314,13 +314,13 @@ protected:
|
|||
if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, true, owner))) {
|
||||
bool has_rating = false;
|
||||
/* Add to the station/cargo counts. */
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
if (st->goods[cargo].HasRating()) this->stations_per_cargo_type[cargo]++;
|
||||
}
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
if (st->goods[cargo].HasRating()) {
|
||||
has_rating = true;
|
||||
if (HasBit(this->filter.cargoes, cargo)) {
|
||||
if (this->filter.cargoes.Test(cargo)) {
|
||||
this->stations.push_back(st);
|
||||
break;
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ protected:
|
|||
{
|
||||
int diff = 0;
|
||||
|
||||
for (CargoType cargo : SetCargoBitIterator(cargo_filter)) {
|
||||
for (CargoType cargo : cargo_filter) {
|
||||
diff += (a->goods[cargo].HasData() ? a->goods[cargo].GetData().cargo.TotalCount() : 0) - (b->goods[cargo].HasData() ? b->goods[cargo].GetData().cargo.TotalCount() : 0);
|
||||
}
|
||||
|
||||
|
@ -371,7 +371,7 @@ protected:
|
|||
{
|
||||
int diff = 0;
|
||||
|
||||
for (CargoType cargo : SetCargoBitIterator(cargo_filter)) {
|
||||
for (CargoType cargo : cargo_filter) {
|
||||
diff += (a->goods[cargo].HasData() ? a->goods[cargo].GetData().cargo.AvailableCount() : 0) - (b->goods[cargo].HasData() ? b->goods[cargo].GetData().cargo.AvailableCount() : 0);
|
||||
}
|
||||
|
||||
|
@ -384,7 +384,7 @@ protected:
|
|||
uint8_t maxr1 = 0;
|
||||
uint8_t maxr2 = 0;
|
||||
|
||||
for (CargoType cargo : SetCargoBitIterator(cargo_filter)) {
|
||||
for (CargoType cargo : cargo_filter) {
|
||||
if (a->goods[cargo].HasRating()) maxr1 = std::max(maxr1, a->goods[cargo].rating);
|
||||
if (b->goods[cargo].HasRating()) maxr2 = std::max(maxr2, b->goods[cargo].rating);
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ protected:
|
|||
uint8_t minr1 = 255;
|
||||
uint8_t minr2 = 255;
|
||||
|
||||
for (CargoType cargo : SetCargoBitIterator(cargo_filter)) {
|
||||
for (CargoType cargo : cargo_filter) {
|
||||
if (a->goods[cargo].HasRating()) minr1 = std::min(minr1, a->goods[cargo].rating);
|
||||
if (b->goods[cargo].HasRating()) minr2 = std::min(minr2, b->goods[cargo].rating);
|
||||
}
|
||||
|
@ -558,9 +558,9 @@ public:
|
|||
}
|
||||
|
||||
if (widget == WID_STL_CARGODROPDOWN) {
|
||||
if (this->filter.cargoes == 0) return GetString(this->filter.include_no_rating ? STR_STATION_LIST_CARGO_FILTER_ONLY_NO_RATING : STR_STATION_LIST_CARGO_FILTER_NO_CARGO_TYPES);
|
||||
if (this->filter.cargoes.None()) return GetString(this->filter.include_no_rating ? STR_STATION_LIST_CARGO_FILTER_ONLY_NO_RATING : STR_STATION_LIST_CARGO_FILTER_NO_CARGO_TYPES);
|
||||
if (this->filter.cargoes == _cargo_mask) return GetString(this->filter.include_no_rating ? STR_STATION_LIST_CARGO_FILTER_ALL_AND_NO_RATING : STR_CARGO_TYPE_FILTER_ALL);
|
||||
if (CountBits(this->filter.cargoes) == 1 && !this->filter.include_no_rating) return GetString(CargoSpec::Get(FindFirstBit(this->filter.cargoes))->name);
|
||||
if (this->filter.cargoes.Count() == 1 && !this->filter.include_no_rating) return GetString(CargoSpec::Get(*this->filter.cargoes.begin())->name);
|
||||
return GetString(STR_STATION_LIST_CARGO_FILTER_MULTIPLE);
|
||||
}
|
||||
|
||||
|
@ -573,7 +573,7 @@ public:
|
|||
using DropDownListCargoItem = DropDownCheck<DropDownString<DropDownListIconItem, FS_SMALL, true>>;
|
||||
|
||||
DropDownList list;
|
||||
list.push_back(MakeDropDownListStringItem(STR_STATION_LIST_CARGO_FILTER_SELECT_ALL, CargoFilterCriteria::CF_SELECT_ALL));
|
||||
list.push_back(MakeDropDownListStringItem(STR_STATION_LIST_CARGO_FILTER_SELECT_ALL, CargoFilterCriteria::CF_SELECT_ALL.base()));
|
||||
list.push_back(MakeDropDownListDividerItem());
|
||||
|
||||
bool any_hidden = false;
|
||||
|
@ -582,7 +582,7 @@ public:
|
|||
if (count == 0 && !expanded) {
|
||||
any_hidden = true;
|
||||
} else {
|
||||
list.push_back(std::make_unique<DropDownString<DropDownListCheckedItem, FS_SMALL, true>>(fmt::format("{}", count), 0, this->filter.include_no_rating, GetString(STR_STATION_LIST_CARGO_FILTER_NO_RATING), CargoFilterCriteria::CF_NO_RATING, false, count == 0));
|
||||
list.push_back(std::make_unique<DropDownString<DropDownListCheckedItem, FS_SMALL, true>>(fmt::format("{}", count), 0, this->filter.include_no_rating, GetString(STR_STATION_LIST_CARGO_FILTER_NO_RATING), CargoFilterCriteria::CF_NO_RATING.base(), false, count == 0));
|
||||
}
|
||||
|
||||
Dimension d = GetLargestCargoIconSize();
|
||||
|
@ -591,13 +591,13 @@ public:
|
|||
if (count == 0 && !expanded) {
|
||||
any_hidden = true;
|
||||
} else {
|
||||
list.push_back(std::make_unique<DropDownListCargoItem>(HasBit(this->filter.cargoes, cs->Index()), fmt::format("{}", count), d, cs->GetCargoIcon(), PAL_NONE, GetString(cs->name), cs->Index(), false, count == 0));
|
||||
list.push_back(std::make_unique<DropDownListCargoItem>(this->filter.cargoes.Test(cs->Index()), fmt::format("{}", count), d, cs->GetCargoIcon(), PAL_NONE, GetString(cs->name), cs->Index().base(), false, count == 0));
|
||||
}
|
||||
}
|
||||
|
||||
if (!expanded && any_hidden) {
|
||||
if (list.size() > 2) list.push_back(MakeDropDownListDividerItem());
|
||||
list.push_back(MakeDropDownListStringItem(STR_STATION_LIST_CARGO_FILTER_EXPAND, CargoFilterCriteria::CF_EXPAND_LIST));
|
||||
list.push_back(MakeDropDownListStringItem(STR_STATION_LIST_CARGO_FILTER_EXPAND, CargoFilterCriteria::CF_EXPAND_LIST.base()));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -684,11 +684,11 @@ public:
|
|||
if (widget == WID_STL_CARGODROPDOWN) {
|
||||
FilterState oldstate = this->filter;
|
||||
|
||||
if (index >= 0 && index < NUM_CARGO) {
|
||||
if (IsInsideMM(index, 0, NUM_CARGO)) {
|
||||
if (_ctrl_pressed) {
|
||||
ToggleBit(this->filter.cargoes, index);
|
||||
this->filter.cargoes.Flip(static_cast<CargoType>(index));
|
||||
} else {
|
||||
this->filter.cargoes = 1ULL << index;
|
||||
this->filter.cargoes = static_cast<CargoType>(index);
|
||||
this->filter.include_no_rating = false;
|
||||
}
|
||||
} else if (index == CargoFilterCriteria::CF_NO_RATING) {
|
||||
|
@ -696,7 +696,7 @@ public:
|
|||
this->filter.include_no_rating = !this->filter.include_no_rating;
|
||||
} else {
|
||||
this->filter.include_no_rating = true;
|
||||
this->filter.cargoes = 0;
|
||||
this->filter.cargoes.Reset();
|
||||
}
|
||||
} else if (index == CargoFilterCriteria::CF_SELECT_ALL) {
|
||||
this->filter.cargoes = _cargo_mask;
|
||||
|
@ -1047,13 +1047,11 @@ private:
|
|||
void IncrementSize();
|
||||
|
||||
CargoDataEntry *parent; ///< the parent of this entry.
|
||||
const union {
|
||||
StationID station; ///< ID of the station this entry is associated with.
|
||||
struct {
|
||||
CargoType cargo; ///< ID of the cargo this entry is associated with.
|
||||
bool transfers; ///< If there are transfers for this cargo.
|
||||
};
|
||||
};
|
||||
|
||||
const StationID station = StationID::Invalid(); ///< ID of the station this entry is associated with.
|
||||
const CargoType cargo = INVALID_CARGO; ///< ID of the cargo this entry is associated with.
|
||||
bool transfers = false; ///< If there are transfers for this cargo.
|
||||
|
||||
uint num_children; ///< the number of subentries belonging to this entry.
|
||||
uint count; ///< sum of counts of all children or amount of cargo for this entry.
|
||||
std::unique_ptr<CargoDataSet> children; ///< the children of this entry.
|
||||
|
@ -1673,7 +1671,7 @@ struct StationViewWindow : public Window {
|
|||
*/
|
||||
void BuildCargoList(CargoDataEntry *entry, const Station *st)
|
||||
{
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
for (CargoType cargo{}; cargo < NUM_CARGO; ++cargo) {
|
||||
|
||||
if (this->cached_destinations.Retrieve(cargo) == nullptr) {
|
||||
this->RecalcDestinations(cargo);
|
||||
|
@ -2141,8 +2139,8 @@ struct StationViewWindow : public Window {
|
|||
void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override
|
||||
{
|
||||
if (gui_scope) {
|
||||
if (data >= 0 && data < NUM_CARGO) {
|
||||
this->cached_destinations.Remove((CargoType)data);
|
||||
if (IsInsideMM(data, 0, NUM_CARGO)) {
|
||||
this->cached_destinations.Remove(static_cast<CargoType>(data));
|
||||
} else {
|
||||
this->ReInit();
|
||||
}
|
||||
|
|
|
@ -1342,10 +1342,10 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
|
|||
/* Tiny description of cargotypes. Layout:
|
||||
* param 1: cargo type
|
||||
* param 2: cargo count */
|
||||
CargoType cargo = args.GetNextParameter<CargoType>();
|
||||
CargoType cargo{args.GetNextParameter<CargoType::BaseType>()};
|
||||
int64_t amount = args.GetNextParameter<int64_t>();
|
||||
|
||||
if (cargo >= CargoSpec::GetArraySize()) {
|
||||
if (cargo.base() >= CargoSpec::GetArraySize()) {
|
||||
builder += "(invalid cargo type)";
|
||||
break;
|
||||
}
|
||||
|
@ -1371,10 +1371,10 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
|
|||
/* Short description of cargotypes. Layout:
|
||||
* param 1: cargo type
|
||||
* param 2: cargo count */
|
||||
CargoType cargo = args.GetNextParameter<CargoType>();
|
||||
CargoType cargo{args.GetNextParameter<CargoType::BaseType>()};
|
||||
int64_t amount = args.GetNextParameter<int64_t>();
|
||||
|
||||
if (cargo >= CargoSpec::GetArraySize()) {
|
||||
if (cargo.base() >= CargoSpec::GetArraySize()) {
|
||||
builder += "(invalid cargo type)";
|
||||
break;
|
||||
}
|
||||
|
@ -1408,9 +1408,9 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
|
|||
|
||||
case SCC_CARGO_LONG: { // {CARGO_LONG}
|
||||
/* First parameter is cargo type, second parameter is cargo count */
|
||||
CargoType cargo = args.GetNextParameter<CargoType>();
|
||||
CargoType cargo{args.GetNextParameter<CargoType::BaseType>()};
|
||||
int64_t amount = args.GetNextParameter<int64_t>();
|
||||
if (cargo < CargoSpec::GetArraySize()) {
|
||||
if (cargo.base() < CargoSpec::GetArraySize()) {
|
||||
auto tmp_args = MakeParameters(amount);
|
||||
GetStringWithArgs(builder, CargoSpec::Get(cargo)->quantifier, tmp_args);
|
||||
} else if (!IsValidCargoType(cargo)) {
|
||||
|
@ -1427,7 +1427,7 @@ static void FormatString(StringBuilder &builder, std::string_view str_arg, Strin
|
|||
|
||||
std::string_view list_separator = GetListSeparator();
|
||||
for (const auto &cs : _sorted_cargo_specs) {
|
||||
if (!HasBit(cmask, cs->Index())) continue;
|
||||
if (!cmask.Test(cs->Index())) continue;
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
|
|
|
@ -296,8 +296,8 @@ bool FindSubsidyTownCargoRoute()
|
|||
|
||||
/* Choose a random cargo that is produced in the town. */
|
||||
uint8_t cargo_number = RandomRange(cargo_count);
|
||||
CargoType cargo_type;
|
||||
for (cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
|
||||
CargoType cargo_type{};
|
||||
for (; cargo_type < NUM_CARGO; ++cargo_type) {
|
||||
if (town_cargo_produced[cargo_type] > 0) {
|
||||
if (cargo_number == 0) break;
|
||||
cargo_number--;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MT(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, 0, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MT(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, CargoTypes{}, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/**
|
||||
* Writes the properties of a multiple-unit train into the EngineInfo struct.
|
||||
|
@ -39,7 +39,7 @@
|
|||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MM(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, 0, 8, EngineMiscFlags{EngineMiscFlag::RailIsMU}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MM(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, CargoTypes{}, 8, EngineMiscFlags{EngineMiscFlag::RailIsMU}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/**
|
||||
* Writes the properties of a train carriage into the EngineInfo struct.
|
||||
|
@ -52,7 +52,7 @@
|
|||
* @see MT
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MW(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, 0, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MW(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, CargoTypes{}, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/**
|
||||
* Writes the properties of a road vehicle into the EngineInfo struct.
|
||||
|
@ -65,7 +65,7 @@
|
|||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MR(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, 0, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MR(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 5, f, INVALID_CARGO, e, CargoTypes{}, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/**
|
||||
* Writes the properties of a ship into the EngineInfo struct.
|
||||
|
@ -77,7 +77,7 @@
|
|||
* @param f Bitmask of the climates
|
||||
* @note the 10 between b and f is the load amount
|
||||
*/
|
||||
#define MS(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 10, f, INVALID_CARGO, e, 0, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MS(a, b, c, d, e, f) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 10, f, INVALID_CARGO, e, CargoTypes{}, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/**
|
||||
* Writes the properties of an aeroplane into the EngineInfo struct.
|
||||
|
@ -88,7 +88,7 @@
|
|||
* @param e Bitmask of the climates
|
||||
* @note the 20 between b and e is the load amount
|
||||
*/
|
||||
#define MA(a, b, c, d, e) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 20, e, INVALID_CARGO, CT_INVALID, 0, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
#define MA(a, b, c, d, e) { CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, TimerGameCalendar::Year{c}, TimerGameCalendar::Year{d}, b, 20, e, INVALID_CARGO, CT_INVALID, CargoTypes{}, 8, EngineMiscFlags{}, VehicleCallbackMasks{}, 0, {}, STR_EMPTY, Ticks::CARGO_AGING_TICKS, EngineID::Invalid() }
|
||||
|
||||
/* Climates
|
||||
* T = Temperate
|
||||
|
|
|
@ -270,8 +270,8 @@ static const NIFeature _nif_industrytile = {
|
|||
|
||||
|
||||
/*** NewGRF industries ***/
|
||||
#define NIP_PRODUCED_CARGO(prop, base_class, slot, type, name) { name, [] (const void *b) -> uint32_t { return static_cast<const base_class *>(b)->GetProduced(slot).cargo; }, prop, type }
|
||||
#define NIP_ACCEPTED_CARGO(prop, base_class, slot, type, name) { name, [] (const void *b) -> uint32_t { return static_cast<const base_class *>(b)->GetAccepted(slot).cargo; }, prop, type }
|
||||
#define NIP_PRODUCED_CARGO(prop, base_class, slot, type, name) { name, [] (const void *b) -> uint32_t { return static_cast<const base_class *>(b)->GetProduced(slot).cargo.base(); }, prop, type }
|
||||
#define NIP_ACCEPTED_CARGO(prop, base_class, slot, type, name) { name, [] (const void *b) -> uint32_t { return static_cast<const base_class *>(b)->GetAccepted(slot).cargo.base(); }, prop, type }
|
||||
|
||||
static const NIProperty _nip_industries[] = {
|
||||
NIP_PRODUCED_CARGO(0x25, Industry, 0, NIT_CARGO, "produced cargo 0"),
|
||||
|
|
|
@ -1814,7 +1814,7 @@ static_assert(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
|
|||
{ca1, ca2, ca3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
|
||||
bf, ba, true, SubstituteGRFFileProps(INVALID_HOUSE_ID), HouseCallbackMasks{}, {COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN}, \
|
||||
16, HouseExtraFlags{}, HOUSE_NO_CLASS, AnimationInfo<void>{}, 0, 0, 0, {}, {cg1, cg2, cg3}, }
|
||||
16, HouseExtraFlags{}, HOUSE_NO_CLASS, AnimationInfo<void>{}, 0, 0, CargoTypes{}, {}, {cg1, cg2, cg3}, }
|
||||
/** House specifications from original data */
|
||||
extern const HouseSpec _original_house_specs[] = {
|
||||
/**
|
||||
|
|
|
@ -33,7 +33,7 @@ static bool MockLoadNextSprite(SpriteID load_index)
|
|||
sc->id = 0;
|
||||
sc->type = is_mapgen ? SpriteType::MapGen : SpriteType::Normal;
|
||||
sc->warned = false;
|
||||
sc->control_flags = 0;
|
||||
sc->control_flags = {};
|
||||
|
||||
/* Fill with empty sprites up until the default sprite count. */
|
||||
return load_index < SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT;
|
||||
|
|
|
@ -169,7 +169,7 @@ inline void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance, CargoTypes
|
|||
{
|
||||
AddAcceptedCargoProc *proc = _tile_type_procs[GetTileType(tile)]->add_accepted_cargo_proc;
|
||||
if (proc == nullptr) return;
|
||||
CargoTypes dummy = 0; // use dummy bitmask so there don't need to be several 'always_accepted != nullptr' checks
|
||||
CargoTypes dummy{}; // use dummy bitmask so there don't need to be several 'always_accepted != nullptr' checks
|
||||
proc(tile, acceptance, always_accepted == nullptr ? dummy : *always_accepted);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
|||
uint8_t exclusive_counter = 0; ///< months till the exclusivity expires
|
||||
TypedIndexContainer<std::array<int16_t, MAX_COMPANIES>, CompanyID> ratings{}; ///< ratings of each company for this town
|
||||
|
||||
std::array<TransportedCargoStat<uint32_t>, NUM_CARGO> supplied{}; ///< Cargo statistics about supplied cargo.
|
||||
TypedIndexContainer<std::array<TransportedCargoStat<uint32_t>, NUM_CARGO>, CargoType> supplied{}; ///< Cargo statistics about supplied cargo.
|
||||
std::array<TransportedCargoStat<uint16_t>, NUM_TAE> received{}; ///< Cargo statistics about received cargotypes.
|
||||
std::array<uint32_t, NUM_TAE> goal{}; ///< Amount of cargo required for the town to grow.
|
||||
|
||||
|
|
|
@ -783,7 +783,7 @@ static void AddAcceptedCargoSetMask(CargoType cargo, uint amount, CargoArray &ac
|
|||
{
|
||||
if (!IsValidCargoType(cargo) || amount == 0) return;
|
||||
acceptance[cargo] += amount;
|
||||
SetBit(always_accepted, cargo);
|
||||
always_accepted.Set(cargo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -400,7 +400,7 @@ public:
|
|||
for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) {
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
|
||||
CargoType cargo_type = cs->Index();
|
||||
DrawString(tr, GetString(str_last_period, 1ULL << cargo_type, this->town->supplied[cargo_type].old_act, this->town->supplied[cargo_type].old_max));
|
||||
DrawString(tr, GetString(str_last_period, CargoTypes{cargo_type}, this->town->supplied[cargo_type].old_act, this->town->supplied[cargo_type].old_max));
|
||||
tr.top += GetCharacterHeight(FS_NORMAL);
|
||||
}
|
||||
}
|
||||
|
@ -1616,12 +1616,12 @@ static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
|
|||
uint amt = GB(callback, 0, 8);
|
||||
if (amt == 0) continue;
|
||||
|
||||
SetBit(produced, cargo);
|
||||
produced.Set(cargo);
|
||||
}
|
||||
} else {
|
||||
/* Cargo is not controlled by NewGRF, town production effect is used instead. */
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) SetBit(produced, cs->Index());
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) SetBit(produced, cs->Index());
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) produced.Set(cs->Index());
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) produced.Set(cs->Index());
|
||||
}
|
||||
return produced;
|
||||
}
|
||||
|
@ -1707,7 +1707,7 @@ struct BuildHouseWindow : public PickerWindow {
|
|||
}
|
||||
|
||||
CargoTypes produced = GetProducedCargoOfHouse(hs);
|
||||
if (produced != 0) {
|
||||
if (produced.Any()) {
|
||||
line << "\n";
|
||||
line << GetString(STR_HOUSE_PICKER_CARGO_PRODUCED, produced);
|
||||
}
|
||||
|
|
|
@ -246,10 +246,10 @@ bool Vehicle::NeedsServicing() const
|
|||
CargoTypes available_cargo_types, union_mask;
|
||||
GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types);
|
||||
/* Is there anything to refit? */
|
||||
if (union_mask != 0) {
|
||||
if (union_mask.Any()) {
|
||||
CargoType cargo_type;
|
||||
CargoTypes cargo_mask = GetCargoTypesOfArticulatedVehicle(v, &cargo_type);
|
||||
if (!HasAtMostOneBit(cargo_mask)) {
|
||||
if (!HasAtMostOneBit(cargo_mask.base())) {
|
||||
CargoTypes new_engine_default_cargoes = GetCargoTypesOfArticulatedParts(new_engine);
|
||||
if ((cargo_mask & new_engine_default_cargoes) != cargo_mask) {
|
||||
/* We cannot refit to mixed cargoes in an automated way */
|
||||
|
@ -260,7 +260,7 @@ bool Vehicle::NeedsServicing() const
|
|||
/* Did the old vehicle carry anything? */
|
||||
if (IsValidCargoType(cargo_type)) {
|
||||
/* We can't refit the vehicle to carry the cargo we want */
|
||||
if (!HasBit(available_cargo_types, cargo_type)) continue;
|
||||
if (!available_cargo_types.Test(cargo_type)) continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -389,7 +389,7 @@ static std::tuple<CommandCost, uint, uint16_t, CargoArray> RefitVehicle(Vehicle
|
|||
|
||||
/* If the vehicle is not refittable, or does not allow automatic refitting,
|
||||
* count its capacity nevertheless if the cargo matches */
|
||||
bool refittable = HasBit(e->info.refit_mask, new_cargo_type) && (!auto_refit || e->info.misc_flags.Test(EngineMiscFlag::AutoRefit));
|
||||
bool refittable = e->info.refit_mask.Test(new_cargo_type) && (!auto_refit || e->info.misc_flags.Test(EngineMiscFlag::AutoRefit));
|
||||
if (!refittable && v->cargo_type != new_cargo_type) {
|
||||
uint amount = e->DetermineCapacity(v, nullptr);
|
||||
if (amount > 0) cargo_capacities[v->cargo_type] += amount;
|
||||
|
|
|
@ -227,10 +227,10 @@ void BaseVehicleListWindow::BuildVehicleList()
|
|||
|
||||
GenerateVehicleSortList(&this->vehicles, this->vli);
|
||||
|
||||
CargoTypes used = 0;
|
||||
CargoTypes used{};
|
||||
for (const Vehicle *v : this->vehicles) {
|
||||
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->cargo_cap > 0) SetBit(used, u->cargo_type);
|
||||
if (u->cargo_cap > 0) used.Set(u->cargo_type);
|
||||
}
|
||||
}
|
||||
this->used_cargoes = used;
|
||||
|
@ -483,10 +483,10 @@ void BaseVehicleListWindow::OnInit()
|
|||
|
||||
StringID BaseVehicleListWindow::GetCargoFilterLabel(CargoType cargo_type) const
|
||||
{
|
||||
switch (cargo_type) {
|
||||
case CargoFilterCriteria::CF_ANY: return STR_CARGO_TYPE_FILTER_ALL;
|
||||
case CargoFilterCriteria::CF_FREIGHT: return STR_CARGO_TYPE_FILTER_FREIGHT;
|
||||
case CargoFilterCriteria::CF_NONE: return STR_CARGO_TYPE_FILTER_NONE;
|
||||
switch (cargo_type.base()) {
|
||||
case CargoFilterCriteria::CF_ANY.base(): return STR_CARGO_TYPE_FILTER_ALL;
|
||||
case CargoFilterCriteria::CF_FREIGHT.base(): return STR_CARGO_TYPE_FILTER_FREIGHT;
|
||||
case CargoFilterCriteria::CF_NONE.base(): return STR_CARGO_TYPE_FILTER_NONE;
|
||||
default: return CargoSpec::Get(cargo_type)->name;
|
||||
}
|
||||
}
|
||||
|
@ -501,17 +501,17 @@ DropDownList BaseVehicleListWindow::BuildCargoDropDownList(bool full) const
|
|||
DropDownList list;
|
||||
|
||||
/* Add item for disabling filtering. */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_ANY), CargoFilterCriteria::CF_ANY.base()));
|
||||
/* Add item for freight (i.e. vehicles with cargo capacity and with no passenger capacity). */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_FREIGHT), CargoFilterCriteria::CF_FREIGHT));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_FREIGHT), CargoFilterCriteria::CF_FREIGHT.base()));
|
||||
/* Add item for vehicles not carrying anything, e.g. train engines. */
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE));
|
||||
list.push_back(MakeDropDownListStringItem(this->GetCargoFilterLabel(CargoFilterCriteria::CF_NONE), CargoFilterCriteria::CF_NONE.base()));
|
||||
|
||||
/* Add cargos */
|
||||
Dimension d = GetLargestCargoIconSize();
|
||||
for (const CargoSpec *cs : _sorted_cargo_specs) {
|
||||
if (!full && !HasBit(this->used_cargoes, cs->Index())) continue;
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index(), false, !HasBit(this->used_cargoes, cs->Index())));
|
||||
if (!full && !this->used_cargoes.Test(cs->Index())) continue;
|
||||
list.push_back(MakeDropDownListIconItem(d, cs->GetCargoIcon(), PAL_NONE, cs->name, cs->Index().base(), false, !this->used_cargoes.Test(cs->Index())));
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -619,7 +619,7 @@ uint8_t GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoType dest_ca
|
|||
for (Vehicle *v = v_for; v != nullptr; v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr) {
|
||||
const Engine *e = v->GetEngine();
|
||||
if (!e->CanCarryCargo() || !e->info.callback_mask.Test(VehicleCallbackMask::CargoSuffix)) continue;
|
||||
if (!HasBit(e->info.refit_mask, dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
|
||||
if (!e->info.refit_mask.Test(dest_cargo_type) && v->cargo_type != dest_cargo_type) continue;
|
||||
|
||||
CargoType old_cargo_type = v->cargo_type;
|
||||
uint8_t old_cargo_subtype = v->cargo_subtype;
|
||||
|
@ -791,7 +791,7 @@ struct RefitWindow : public Window {
|
|||
for (const auto &cs : _sorted_cargo_specs) {
|
||||
CargoType cargo_type = cs->Index();
|
||||
/* Skip cargo type if it's not listed */
|
||||
if (!HasBit(cmask, cargo_type)) continue;
|
||||
if (!cmask.Test(cargo_type)) continue;
|
||||
|
||||
auto &list = this->refit_list[cargo_type];
|
||||
bool first_vehicle = list.empty();
|
||||
|
@ -1359,25 +1359,24 @@ void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *pare
|
|||
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
|
||||
{
|
||||
/* List of cargo types of this engine */
|
||||
CargoTypes cmask = GetUnionOfArticulatedRefitMasks(engine, false);
|
||||
/* List of cargo types available in this climate */
|
||||
CargoTypes lmask = _cargo_mask;
|
||||
CargoTypes present = GetUnionOfArticulatedRefitMasks(engine, false);
|
||||
|
||||
/* Draw nothing if the engine is not refittable */
|
||||
if (HasAtMostOneBit(cmask)) return y;
|
||||
if (HasAtMostOneBit(present.base())) return y;
|
||||
|
||||
std::string str;
|
||||
if (cmask == lmask) {
|
||||
if (present == _cargo_mask) {
|
||||
/* Engine can be refitted to all types in this climate */
|
||||
str = GetString(STR_PURCHASE_INFO_REFITTABLE_TO, STR_PURCHASE_INFO_ALL_TYPES, std::monostate{});
|
||||
} else {
|
||||
/* Check if we are able to refit to more cargo types and unable to. If
|
||||
* so, invert the cargo types to list those that we can't refit to. */
|
||||
if (CountBits(cmask ^ lmask) < CountBits(cmask) && CountBits(cmask ^ lmask) <= 7) {
|
||||
cmask ^= lmask;
|
||||
str = GetString(STR_PURCHASE_INFO_REFITTABLE_TO, STR_PURCHASE_INFO_ALL_BUT, cmask);
|
||||
CargoTypes excluded = CargoTypes{present}.Flip(_cargo_mask);
|
||||
uint num_excluded = excluded.Count();
|
||||
if (num_excluded < present.Count() && num_excluded <= 7) {
|
||||
str = GetString(STR_PURCHASE_INFO_REFITTABLE_TO, STR_PURCHASE_INFO_ALL_BUT, excluded);
|
||||
} else {
|
||||
str = GetString(STR_PURCHASE_INFO_REFITTABLE_TO, STR_JUST_CARGO_LIST, cmask);
|
||||
str = GetString(STR_PURCHASE_INFO_REFITTABLE_TO, STR_JUST_CARGO_LIST, present);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1793,12 +1792,12 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
|||
|
||||
if (_settings_client.gui.show_cargo_in_vehicle_lists) {
|
||||
/* Get the cargoes the vehicle can carry */
|
||||
CargoTypes vehicle_cargoes = 0;
|
||||
CargoTypes vehicle_cargoes{};
|
||||
|
||||
for (auto u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->cargo_cap == 0) continue;
|
||||
|
||||
SetBit(vehicle_cargoes, u->cargo_type);
|
||||
vehicle_cargoes.Set(u->cargo_type);
|
||||
}
|
||||
|
||||
if (!v->name.empty()) {
|
||||
|
@ -2110,7 +2109,7 @@ public:
|
|||
return;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO: // Cargo filter dropdown
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria, widget);
|
||||
ShowDropDownList(this, this->BuildCargoDropDownList(false), this->cargo_filter_criteria.base(), widget);
|
||||
break;
|
||||
|
||||
case WID_VL_LIST: { // Matrix to show vehicles
|
||||
|
@ -2182,7 +2181,7 @@ public:
|
|||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
this->SetCargoFilter(index);
|
||||
this->SetCargoFilter(static_cast<CargoType>(index));
|
||||
break;
|
||||
|
||||
case WID_VL_MANAGE_VEHICLES_DROPDOWN:
|
||||
|
|
|
@ -116,7 +116,7 @@ struct BaseVehicleListWindow : public Window {
|
|||
void UpdateVehicleGroupBy(GroupBy group_by);
|
||||
void SortVehicleList();
|
||||
void BuildVehicleList();
|
||||
void SetCargoFilter(uint8_t index);
|
||||
void SetCargoFilter(CargoType index);
|
||||
void SetCargoFilterArray();
|
||||
void FilterVehicleList();
|
||||
StringID GetCargoFilterLabel(CargoType cargo_type) const;
|
||||
|
|
|
@ -1825,7 +1825,7 @@ void ViewportDoDraw(const Viewport &vp, int left, int top, int right, int bottom
|
|||
dp.height = UnScaleByZoom(dp.height, zoom);
|
||||
AutoRestoreBackup cur_dpi(_cur_dpi, &dp);
|
||||
|
||||
if (vp.overlay != nullptr && vp.overlay->GetCargoMask() != 0 && vp.overlay->GetCompanyMask().Any()) {
|
||||
if (vp.overlay != nullptr && vp.overlay->GetCargoMask().Any() && vp.overlay->GetCompanyMask().Any()) {
|
||||
/* translate to window coordinates */
|
||||
dp.left = x;
|
||||
dp.top = y;
|
||||
|
@ -2499,7 +2499,7 @@ void RebuildViewportOverlay(Window *w)
|
|||
{
|
||||
if (w->viewport->overlay != nullptr &&
|
||||
w->viewport->overlay->GetCompanyMask().Any() &&
|
||||
w->viewport->overlay->GetCargoMask() != 0) {
|
||||
w->viewport->overlay->GetCargoMask().Any()) {
|
||||
w->viewport->overlay->SetDirty();
|
||||
w->SetDirty();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue