4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file cargotype.cpp Implementation of cargoes. */
13 #include "cargotype.h"
14 #include "newgrf_cargo.h"
15 #include "string_func.h"
16 #include "strings_func.h"
17 #include "core/sort_func.hpp"
19 #include "table/sprites.h"
20 #include "table/strings.h"
21 #include "table/cargo_const.h"
23 CargoSpec
CargoSpec::array
[NUM_CARGO
];
26 * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes.
27 * Initialized during a call to #SetupCargoForClimate.
32 * Bitmask of real cargo types available. Phony cargoes like regearing cargoes are excluded.
34 uint32 _standard_cargo_mask
;
37 * Set up the default cargo types for the given landscape type.
40 void SetupCargoForClimate(LandscapeID l
)
42 assert(l
< lengthof(_default_climate_cargo
));
44 /* Reset and disable all cargo types */
45 memset(CargoSpec::array
, 0, sizeof(CargoSpec::array
));
46 for (CargoID i
= 0; i
< lengthof(CargoSpec::array
); i
++) {
47 CargoSpec::Get(i
)->bitnum
= INVALID_CARGO
;
49 /* Set defaults for newer properties, which old GRFs do not know */
50 CargoSpec::Get(i
)->multiplier
= 0x100;
55 for (CargoID i
= 0; i
< lengthof(_default_climate_cargo
[l
]); i
++) {
56 CargoLabel cl
= _default_climate_cargo
[l
][i
];
58 /* Bzzt: check if cl is just an index into the cargo table */
59 if (cl
< lengthof(_default_cargo
)) {
60 /* Copy the indexed cargo */
61 CargoSpec
*cargo
= CargoSpec::Get(i
);
62 *cargo
= _default_cargo
[cl
];
63 if (cargo
->bitnum
!= INVALID_CARGO
) SetBit(_cargo_mask
, i
);
67 /* Loop through each of the default cargo types to see if
68 * the label matches */
69 for (uint j
= 0; j
< lengthof(_default_cargo
); j
++) {
70 if (_default_cargo
[j
].label
== cl
) {
71 *CargoSpec::Get(i
) = _default_cargo
[j
];
73 /* Populate the available cargo mask */
74 SetBit(_cargo_mask
, i
);
82 * Get the cargo ID by cargo label.
83 * @param cl Cargo type to get.
84 * @return ID number if the cargo exists, else #CT_INVALID
86 CargoID
GetCargoIDByLabel(CargoLabel cl
)
89 FOR_ALL_CARGOSPECS(cs
) {
90 if (cs
->label
== cl
) return cs
->Index();
93 /* No matching label was found, so it is invalid */
99 * Find the CargoID of a 'bitnum' value.
100 * @param bitnum 'bitnum' to find.
101 * @return First CargoID with the given bitnum, or #CT_INVALID if not found or if the provided \a bitnum is invalid.
103 CargoID
GetCargoIDByBitnum(uint8 bitnum
)
105 if (bitnum
== INVALID_CARGO
) return CT_INVALID
;
108 FOR_ALL_CARGOSPECS(cs
) {
109 if (cs
->bitnum
== bitnum
) return cs
->Index();
112 /* No matching label was found, so it is invalid */
117 * Get sprite for showing cargo of this type.
118 * @return Sprite number to use.
120 SpriteID
CargoSpec::GetCargoIcon() const
122 SpriteID sprite
= this->sprite
;
123 if (sprite
== 0xFFFF) {
124 /* A value of 0xFFFF indicates we should draw a custom icon */
125 sprite
= GetCustomCargoSprite(this);
128 if (sprite
== 0) sprite
= SPR_CARGO_GOODS
;
133 const CargoSpec
*_sorted_cargo_specs
[NUM_CARGO
]; ///< Cargo specifications sorted alphabetically by name.
134 uint8 _sorted_cargo_specs_size
; ///< Number of cargo specifications stored at the _sorted_cargo_specs array (including special cargoes).
135 uint8 _sorted_standard_cargo_specs_size
; ///< Number of standard cargo specifications stored at the _sorted_cargo_specs array.
138 /** Sort cargo specifications by their name. */
139 static int CDECL
CargoSpecNameSorter(const CargoSpec
* const *a
, const CargoSpec
* const *b
)
141 static char a_name
[64];
142 static char b_name
[64];
144 GetString(a_name
, (*a
)->name
, lastof(a_name
));
145 GetString(b_name
, (*b
)->name
, lastof(b_name
));
147 int res
= strnatcmp(a_name
, b_name
); // Sort by name (natural sorting).
149 /* If the names are equal, sort by cargo bitnum. */
150 return (res
!= 0) ? res
: ((*a
)->bitnum
- (*b
)->bitnum
);
153 /** Sort cargo specifications by their cargo class. */
154 static int CDECL
CargoSpecClassSorter(const CargoSpec
* const *a
, const CargoSpec
* const *b
)
156 int res
= ((*b
)->classes
& CC_PASSENGERS
) - ((*a
)->classes
& CC_PASSENGERS
);
158 res
= ((*b
)->classes
& CC_MAIL
) - ((*a
)->classes
& CC_MAIL
);
160 res
= ((*a
)->classes
& CC_SPECIAL
) - ((*b
)->classes
& CC_SPECIAL
);
162 return CargoSpecNameSorter(a
, b
);
170 /** Initialize the list of sorted cargo specifications. */
171 void InitializeSortedCargoSpecs()
173 _sorted_cargo_specs_size
= 0;
174 const CargoSpec
*cargo
;
175 /* Add each cargo spec to the list. */
176 FOR_ALL_CARGOSPECS(cargo
) {
177 _sorted_cargo_specs
[_sorted_cargo_specs_size
] = cargo
;
178 _sorted_cargo_specs_size
++;
181 /* Sort cargo specifications by cargo class and name. */
182 QSortT(_sorted_cargo_specs
, _sorted_cargo_specs_size
, &CargoSpecClassSorter
);
184 _standard_cargo_mask
= 0;
186 _sorted_standard_cargo_specs_size
= 0;
187 FOR_ALL_SORTED_CARGOSPECS(cargo
) {
188 if (cargo
->classes
& CC_SPECIAL
) break;
189 _sorted_standard_cargo_specs_size
++;
190 SetBit(_standard_cargo_mask
, cargo
->Index());