2009-08-21 20:21:05 +00:00
|
|
|
/*
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2011-12-15 21:56:00 +00:00
|
|
|
/** @file cargotype.h Types/functions related to cargoes. */
|
2007-02-23 11:50:43 +00:00
|
|
|
|
2007-02-20 22:09:21 +00:00
|
|
|
#ifndef CARGOTYPE_H
|
|
|
|
#define CARGOTYPE_H
|
|
|
|
|
2009-09-06 20:36:17 +00:00
|
|
|
#include "economy_type.h"
|
2007-12-21 22:50:51 +00:00
|
|
|
#include "cargo_type.h"
|
2007-12-23 10:56:02 +00:00
|
|
|
#include "gfx_type.h"
|
2008-04-17 11:47:22 +00:00
|
|
|
#include "strings_type.h"
|
2008-05-07 09:07:19 +00:00
|
|
|
#include "landscape_type.h"
|
2021-06-13 02:29:24 +00:00
|
|
|
#include "core/bitmath_func.hpp"
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
/** Town growth effect when delivering cargo. */
|
2024-01-07 19:32:39 +00:00
|
|
|
enum TownAcceptanceEffect : byte {
|
|
|
|
TAE_BEGIN = 0,
|
|
|
|
TAE_NONE = TAE_BEGIN, ///< Cargo has no effect.
|
|
|
|
TAE_PASSENGERS, ///< Cargo behaves passenger-like.
|
|
|
|
TAE_MAIL, ///< Cargo behaves mail-like.
|
|
|
|
TAE_GOODS, ///< Cargo behaves goods/candy-like.
|
|
|
|
TAE_WATER, ///< Cargo behaves water-like.
|
|
|
|
TAE_FOOD, ///< Cargo behaves food/fizzy-drinks-like.
|
|
|
|
TAE_END, ///< End of town effects.
|
|
|
|
NUM_TAE = TAE_END, ///< Amount of town effects.
|
2007-03-15 22:48:46 +00:00
|
|
|
};
|
|
|
|
|
2024-01-07 19:32:39 +00:00
|
|
|
/** Town effect when producing cargo. */
|
|
|
|
enum TownProductionEffect : byte {
|
|
|
|
TPE_NONE, ///< Town will not produce this cargo type.
|
|
|
|
TPE_PASSENGERS, ///< Cargo behaves passenger-like for production.
|
|
|
|
TPE_MAIL, ///< Cargo behaves mail-like for production.
|
|
|
|
NUM_TPE,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Invalid town production effect. Used as a sentinel to indicate if a NewGRF has explicitly set an effect.
|
|
|
|
* This does not 'exist' after cargo types are finalised.
|
|
|
|
*/
|
|
|
|
INVALID_TPE,
|
|
|
|
};
|
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
/** Cargo classes. */
|
2009-11-05 19:46:17 +00:00
|
|
|
enum CargoClass {
|
|
|
|
CC_NOAVAILABLE = 0, ///< No cargo class has been specified
|
|
|
|
CC_PASSENGERS = 1 << 0, ///< Passengers
|
|
|
|
CC_MAIL = 1 << 1, ///< Mail
|
|
|
|
CC_EXPRESS = 1 << 2, ///< Express cargo (Goods, Food, Candy, but also possible for passengers)
|
|
|
|
CC_ARMOURED = 1 << 3, ///< Armoured cargo (Valuables, Gold, Diamonds)
|
|
|
|
CC_BULK = 1 << 4, ///< Bulk cargo (Coal, Grain etc., Ores, Fruit)
|
|
|
|
CC_PIECE_GOODS = 1 << 5, ///< Piece goods (Livestock, Wood, Steel, Paper)
|
|
|
|
CC_LIQUID = 1 << 6, ///< Liquids (Oil, Water, Rubber)
|
|
|
|
CC_REFRIGERATED = 1 << 7, ///< Refrigerated cargo (Food, Fruit)
|
|
|
|
CC_HAZARDOUS = 1 << 8, ///< Hazardous cargo (Nuclear Fuel, Explosives, etc.)
|
2013-01-08 22:46:42 +00:00
|
|
|
CC_COVERED = 1 << 9, ///< Covered/Sheltered Freight (Transportation in Box Vans, Silo Wagons, etc.)
|
2011-12-19 17:48:04 +00:00
|
|
|
CC_SPECIAL = 1 << 15, ///< Special bit used for livery refit tricks instead of normal cargoes.
|
2009-11-05 19:46:17 +00:00
|
|
|
};
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2023-05-23 07:35:47 +00:00
|
|
|
static const byte INVALID_CARGO_BITNUM = 0xFF; ///< Constant representing invalid cargo
|
2009-06-25 23:49:59 +00:00
|
|
|
|
2024-02-03 13:58:31 +00:00
|
|
|
static const uint TOWN_PRODUCTION_DIVISOR = 256;
|
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
/** Specification of a cargo type. */
|
2007-03-07 12:11:48 +00:00
|
|
|
struct CargoSpec {
|
2009-12-05 21:39:28 +00:00
|
|
|
CargoLabel label; ///< Unique label of the cargo type.
|
2023-09-17 16:42:34 +00:00
|
|
|
uint8_t bitnum{INVALID_CARGO_BITNUM}; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec.
|
2023-05-08 17:01:06 +00:00
|
|
|
uint8_t legend_colour;
|
|
|
|
uint8_t rating_colour;
|
|
|
|
uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg).
|
2023-04-27 12:26:10 +00:00
|
|
|
uint16_t multiplier{0x100}; ///< Capacity multiplier for vehicles. (8 fractional bits)
|
2023-09-17 16:42:34 +00:00
|
|
|
uint16_t classes; ///< Classes of this cargo type. @see CargoClass
|
2023-05-08 17:01:06 +00:00
|
|
|
int32_t initial_payment; ///< Initial payment rate before inflation is applied.
|
|
|
|
uint8_t transit_periods[2];
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier).
|
2024-01-07 19:32:39 +00:00
|
|
|
TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies.
|
2024-01-07 19:32:39 +00:00
|
|
|
TownProductionEffect town_production_effect{INVALID_TPE}; ///< The effect on town cargo production.
|
2024-02-03 13:58:31 +00:00
|
|
|
uint16_t town_production_multiplier{TOWN_PRODUCTION_DIVISOR}; ///< Town production multipler, if commanded by TownProductionEffect.
|
2023-05-08 17:01:06 +00:00
|
|
|
uint8_t callback_mask; ///< Bitmask of cargo callbacks that have to be called
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
StringID name; ///< Name of this type of cargo.
|
|
|
|
StringID name_single; ///< Name of a single entity of this type of cargo.
|
|
|
|
StringID units_volume; ///< Name of a single unit of cargo of this type.
|
|
|
|
StringID quantifier; ///< Text for multiple units of cargo of this type.
|
|
|
|
StringID abbrev; ///< Two letter abbreviation for this cargo type.
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
SpriteID sprite; ///< Icon to display this cargo type, may be \c 0xFFF (which means to resolve an action123 chain).
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2009-12-05 21:39:28 +00:00
|
|
|
const struct GRFFile *grffile; ///< NewGRF where #group belongs to.
|
2007-03-23 20:55:45 +00:00
|
|
|
const struct SpriteGroup *group;
|
2007-02-23 09:56:20 +00:00
|
|
|
|
2009-09-06 20:36:17 +00:00
|
|
|
Money current_payment;
|
|
|
|
|
2009-07-16 20:40:06 +00:00
|
|
|
/**
|
|
|
|
* Determines index of this cargospec
|
|
|
|
* @return index (in the CargoSpec::array array)
|
|
|
|
*/
|
2011-12-20 17:57:56 +00:00
|
|
|
inline CargoID Index() const
|
2009-07-16 20:40:06 +00:00
|
|
|
{
|
|
|
|
return this - CargoSpec::array;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Tests for validity of this cargospec
|
|
|
|
* @return is this cargospec valid?
|
|
|
|
* @note assert(cs->IsValid()) can be triggered when GRF config is modified
|
|
|
|
*/
|
2011-12-20 17:57:56 +00:00
|
|
|
inline bool IsValid() const
|
2009-06-25 23:49:59 +00:00
|
|
|
{
|
2023-05-23 07:35:47 +00:00
|
|
|
return this->bitnum != INVALID_CARGO_BITNUM;
|
2009-06-25 23:49:59 +00:00
|
|
|
}
|
2009-07-16 19:00:13 +00:00
|
|
|
|
2009-07-16 20:40:06 +00:00
|
|
|
/**
|
2009-07-16 21:37:59 +00:00
|
|
|
* Total number of cargospecs, both valid and invalid
|
|
|
|
* @return length of CargoSpec::array
|
2009-07-16 20:40:06 +00:00
|
|
|
*/
|
2011-12-20 17:57:56 +00:00
|
|
|
static inline size_t GetArraySize()
|
2009-07-16 20:40:06 +00:00
|
|
|
{
|
|
|
|
return lengthof(CargoSpec::array);
|
|
|
|
}
|
|
|
|
|
2009-07-16 19:00:13 +00:00
|
|
|
/**
|
|
|
|
* Retrieve cargo details for the given cargo ID
|
2009-07-16 20:40:06 +00:00
|
|
|
* @param index ID of cargo
|
|
|
|
* @pre index is a valid cargo ID
|
2009-07-16 19:00:13 +00:00
|
|
|
*/
|
2011-12-20 17:57:56 +00:00
|
|
|
static inline CargoSpec *Get(size_t index)
|
2009-07-16 19:00:13 +00:00
|
|
|
{
|
2009-07-16 20:40:06 +00:00
|
|
|
assert(index < lengthof(CargoSpec::array));
|
|
|
|
return &CargoSpec::array[index];
|
2009-07-16 19:00:13 +00:00
|
|
|
}
|
|
|
|
|
2009-12-05 16:00:58 +00:00
|
|
|
SpriteID GetCargoIcon() const;
|
|
|
|
|
2023-05-08 17:01:06 +00:00
|
|
|
inline uint64_t WeightOfNUnits(uint32_t n) const
|
2022-11-02 17:31:10 +00:00
|
|
|
{
|
|
|
|
return n * this->weight / 16u;
|
|
|
|
}
|
|
|
|
|
2023-05-08 17:01:06 +00:00
|
|
|
uint64_t WeightOfNUnitsInTrain(uint32_t n) const;
|
2022-11-02 17:31:10 +00:00
|
|
|
|
2021-04-29 15:51:05 +00:00
|
|
|
/**
|
|
|
|
* Iterator to iterate all valid CargoSpec
|
|
|
|
*/
|
|
|
|
struct Iterator {
|
|
|
|
typedef CargoSpec value_type;
|
|
|
|
typedef CargoSpec *pointer;
|
|
|
|
typedef CargoSpec &reference;
|
|
|
|
typedef size_t difference_type;
|
|
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
|
|
|
|
|
|
explicit Iterator(size_t index) : index(index)
|
|
|
|
{
|
|
|
|
this->ValidateIndex();
|
|
|
|
};
|
|
|
|
|
|
|
|
bool operator==(const Iterator &other) const { return this->index == other.index; }
|
|
|
|
bool operator!=(const Iterator &other) const { return !(*this == other); }
|
|
|
|
CargoSpec * operator*() const { return CargoSpec::Get(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++; }
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Iterable ensemble of all valid CargoSpec
|
|
|
|
*/
|
|
|
|
struct IterateWrapper {
|
|
|
|
size_t from;
|
|
|
|
IterateWrapper(size_t from = 0) : from(from) {}
|
|
|
|
Iterator begin() { return Iterator(this->from); }
|
|
|
|
Iterator end() { return Iterator(CargoSpec::GetArraySize()); }
|
|
|
|
bool empty() { return this->begin() == this->end(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an iterable ensemble of all valid CargoSpec
|
|
|
|
* @param from index of the first CargoSpec to consider
|
|
|
|
* @return an iterable ensemble of all valid CargoSpec
|
|
|
|
*/
|
|
|
|
static IterateWrapper Iterate(size_t from = 0) { return IterateWrapper(from); }
|
|
|
|
|
2024-01-07 19:32:39 +00:00
|
|
|
/** List of cargo specs for each Town Product Effect. */
|
|
|
|
static std::array<std::vector<const CargoSpec *>, NUM_TPE> town_production_cargoes;
|
|
|
|
|
2009-07-16 19:00:13 +00:00
|
|
|
private:
|
2009-07-16 21:37:59 +00:00
|
|
|
static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
|
2024-02-04 10:16:08 +00:00
|
|
|
static inline std::map<CargoLabel, CargoID> label_map{}; ///< Translation map from CargoLabel to Cargo ID.
|
2009-07-16 19:00:13 +00:00
|
|
|
|
|
|
|
friend void SetupCargoForClimate(LandscapeID l);
|
2024-02-04 10:16:08 +00:00
|
|
|
friend void BuildCargoLabelMap();
|
|
|
|
friend inline CargoID GetCargoIDByLabel(CargoLabel ct);
|
2024-01-19 20:07:47 +00:00
|
|
|
friend void FinaliseCargoArray();
|
2007-03-07 12:11:48 +00:00
|
|
|
};
|
2007-02-20 22:09:21 +00:00
|
|
|
|
2018-05-21 21:08:39 +00:00
|
|
|
extern CargoTypes _cargo_mask;
|
|
|
|
extern CargoTypes _standard_cargo_mask;
|
2007-02-22 22:09:51 +00:00
|
|
|
|
2007-02-20 22:09:21 +00:00
|
|
|
void SetupCargoForClimate(LandscapeID l);
|
2024-02-04 10:16:08 +00:00
|
|
|
bool IsDefaultCargo(CargoID cid);
|
|
|
|
void BuildCargoLabelMap();
|
2023-05-08 17:01:06 +00:00
|
|
|
CargoID GetCargoIDByBitnum(uint8_t bitnum);
|
2024-02-04 10:16:08 +00:00
|
|
|
|
|
|
|
inline CargoID GetCargoIDByLabel(CargoLabel label)
|
|
|
|
{
|
|
|
|
auto found = CargoSpec::label_map.find(label);
|
|
|
|
if (found != std::end(CargoSpec::label_map)) return found->second;
|
|
|
|
return INVALID_CARGO;
|
|
|
|
}
|
|
|
|
|
2023-11-25 20:20:35 +00:00
|
|
|
Dimension GetLargestCargoIconSize();
|
2007-02-22 22:09:51 +00:00
|
|
|
|
2010-04-01 19:48:28 +00:00
|
|
|
void InitializeSortedCargoSpecs();
|
2023-09-18 21:34:55 +00:00
|
|
|
extern std::array<uint8_t, NUM_CARGO> _sorted_cargo_types;
|
2019-04-12 15:47:13 +00:00
|
|
|
extern std::vector<const CargoSpec *> _sorted_cargo_specs;
|
2024-01-16 21:46:00 +00:00
|
|
|
extern std::span<const CargoSpec *> _sorted_standard_cargo_specs;
|
2010-04-01 19:48:28 +00:00
|
|
|
|
2010-08-01 19:22:34 +00:00
|
|
|
/**
|
|
|
|
* Does cargo \a c have cargo class \a cc?
|
2009-12-05 21:39:28 +00:00
|
|
|
* @param c Cargo type.
|
|
|
|
* @param cc Cargo class.
|
|
|
|
* @return The type fits in the class.
|
|
|
|
*/
|
2024-01-06 11:19:27 +00:00
|
|
|
inline bool IsCargoInClass(CargoID c, CargoClass cc)
|
2007-03-18 22:07:44 +00:00
|
|
|
{
|
2009-07-16 19:00:13 +00:00
|
|
|
return (CargoSpec::Get(c)->classes & cc) != 0;
|
2007-03-18 22:07:44 +00:00
|
|
|
}
|
|
|
|
|
2021-06-13 02:29:24 +00:00
|
|
|
using SetCargoBitIterator = SetBitIterator<CargoID, CargoTypes>;
|
2010-05-11 21:01:01 +00:00
|
|
|
|
2023-10-14 20:20:23 +00:00
|
|
|
/** Comparator to sort CargoID by according to desired order. */
|
|
|
|
struct CargoIDComparator {
|
|
|
|
bool operator() (const CargoID &lhs, const CargoID &rhs) const { return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs]; }
|
|
|
|
};
|
|
|
|
|
2007-02-20 22:09:21 +00:00
|
|
|
#endif /* CARGOTYPE_H */
|