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 #include "safeguards.h"
25 CargoSpec
CargoSpec::array
[NUM_CARGO
];
28 * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes.
29 * Initialized during a call to #SetupCargoForClimate.
34 * Bitmask of real cargo types available. Phony cargoes like regearing cargoes are excluded.
36 uint32 _standard_cargo_mask
;
39 * Set up the default cargo types for the given landscape type.
42 void SetupCargoForClimate(LandscapeID l
)
44 assert(l
< lengthof(_default_climate_cargo
));
46 /* Reset and disable all cargo types */
47 memset(CargoSpec::array
, 0, sizeof(CargoSpec::array
));
48 for (CargoID i
= 0; i
< lengthof(CargoSpec::array
); i
++) {
49 CargoSpec::Get(i
)->bitnum
= INVALID_CARGO
;
51 /* Set defaults for newer properties, which old GRFs do not know */
52 CargoSpec::Get(i
)->multiplier
= 0x100;
57 for (CargoID i
= 0; i
< lengthof(_default_climate_cargo
[l
]); i
++) {
58 CargoLabel cl
= _default_climate_cargo
[l
][i
];
60 /* Bzzt: check if cl is just an index into the cargo table */
61 if (cl
< lengthof(_default_cargo
)) {
62 /* Copy the indexed cargo */
63 CargoSpec
*cargo
= CargoSpec::Get(i
);
64 *cargo
= _default_cargo
[cl
];
65 if (cargo
->bitnum
!= INVALID_CARGO
) SetBit(_cargo_mask
, i
);
69 /* Loop through each of the default cargo types to see if
70 * the label matches */
71 for (uint j
= 0; j
< lengthof(_default_cargo
); j
++) {
72 if (_default_cargo
[j
].label
== cl
) {
73 *CargoSpec::Get(i
) = _default_cargo
[j
];
75 /* Populate the available cargo mask */
76 SetBit(_cargo_mask
, i
);
84 * Get the cargo ID by cargo label.
85 * @param cl Cargo type to get.
86 * @return ID number if the cargo exists, else #CT_INVALID
88 CargoID
GetCargoIDByLabel(CargoLabel cl
)
91 FOR_ALL_CARGOSPECS(cs
) {
92 if (cs
->label
== cl
) return cs
->Index();
95 /* No matching label was found, so it is invalid */
101 * Find the CargoID of a 'bitnum' value.
102 * @param bitnum 'bitnum' to find.
103 * @return First CargoID with the given bitnum, or #CT_INVALID if not found or if the provided \a bitnum is invalid.
105 CargoID
GetCargoIDByBitnum(uint8 bitnum
)
107 if (bitnum
== INVALID_CARGO
) return CT_INVALID
;
110 FOR_ALL_CARGOSPECS(cs
) {
111 if (cs
->bitnum
== bitnum
) return cs
->Index();
114 /* No matching label was found, so it is invalid */
119 * Get sprite for showing cargo of this type.
120 * @return Sprite number to use.
122 SpriteID
CargoSpec::GetCargoIcon() const
124 SpriteID sprite
= this->sprite
;
125 if (sprite
== 0xFFFF) {
126 /* A value of 0xFFFF indicates we should draw a custom icon */
127 sprite
= GetCustomCargoSprite(this);
130 if (sprite
== 0) sprite
= SPR_CARGO_GOODS
;
135 const CargoSpec
*_sorted_cargo_specs
[NUM_CARGO
]; ///< Cargo specifications sorted alphabetically by name.
136 uint8 _sorted_cargo_specs_size
; ///< Number of cargo specifications stored at the _sorted_cargo_specs array (including special cargoes).
137 uint8 _sorted_standard_cargo_specs_size
; ///< Number of standard cargo specifications stored at the _sorted_cargo_specs array.
140 /** Sort cargo specifications by their name. */
141 static int CDECL
CargoSpecNameSorter(const CargoSpec
* const *a
, const CargoSpec
* const *b
)
143 static char a_name
[64];
144 static char b_name
[64];
146 GetString(a_name
, (*a
)->name
, lastof(a_name
));
147 GetString(b_name
, (*b
)->name
, lastof(b_name
));
149 int res
= strnatcmp(a_name
, b_name
); // Sort by name (natural sorting).
151 /* If the names are equal, sort by cargo bitnum. */
152 return (res
!= 0) ? res
: ((*a
)->bitnum
- (*b
)->bitnum
);
155 /** Sort cargo specifications by their cargo class. */
156 static int CDECL
CargoSpecClassSorter(const CargoSpec
* const *a
, const CargoSpec
* const *b
)
158 int res
= ((*b
)->classes
& CC_PASSENGERS
) - ((*a
)->classes
& CC_PASSENGERS
);
160 res
= ((*b
)->classes
& CC_MAIL
) - ((*a
)->classes
& CC_MAIL
);
162 res
= ((*a
)->classes
& CC_SPECIAL
) - ((*b
)->classes
& CC_SPECIAL
);
164 return CargoSpecNameSorter(a
, b
);
172 /** Initialize the list of sorted cargo specifications. */
173 void InitializeSortedCargoSpecs()
175 _sorted_cargo_specs_size
= 0;
176 const CargoSpec
*cargo
;
177 /* Add each cargo spec to the list. */
178 FOR_ALL_CARGOSPECS(cargo
) {
179 _sorted_cargo_specs
[_sorted_cargo_specs_size
] = cargo
;
180 _sorted_cargo_specs_size
++;
183 /* Sort cargo specifications by cargo class and name. */
184 QSortT(_sorted_cargo_specs
, _sorted_cargo_specs_size
, &CargoSpecClassSorter
);
186 _standard_cargo_mask
= 0;
188 _sorted_standard_cargo_specs_size
= 0;
189 FOR_ALL_SORTED_CARGOSPECS(cargo
) {
190 if (cargo
->classes
& CC_SPECIAL
) break;
191 _sorted_standard_cargo_specs_size
++;
192 SetBit(_standard_cargo_mask
, cargo
->Index());