Merge road stop removal cases in BuildRoadToolbarWindow
[openttd/fttd.git] / src / cargotype.cpp
blobf8c73dc7d0ff194205cad9f88e1963ce8909b1c3
1 /* $Id$ */
3 /*
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/>.
8 */
10 /** @file cargotype.cpp Implementation of cargoes. */
12 #include "stdafx.h"
13 #include "cargotype.h"
14 #include "newgrf_cargo.h"
15 #include "string.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];
25 /**
26 * Bitmask of cargo types available. This includes phony cargoes like regearing cargoes.
27 * Initialized during a call to #SetupCargoForClimate.
29 uint32 _cargo_mask;
31 /**
32 * Bitmask of real cargo types available. Phony cargoes like regearing cargoes are excluded.
34 uint32 _standard_cargo_mask;
36 /**
37 * Set up the default cargo types for the given landscape type.
38 * @param l Landscape
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;
53 _cargo_mask = 0;
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);
64 continue;
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);
75 break;
81 /**
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)
88 const CargoSpec *cs;
89 FOR_ALL_CARGOSPECS(cs) {
90 if (cs->label == cl) return cs->Index();
93 /* No matching label was found, so it is invalid */
94 return CT_INVALID;
98 /**
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;
107 const CargoSpec *cs;
108 FOR_ALL_CARGOSPECS(cs) {
109 if (cs->bitnum == bitnum) return cs->Index();
112 /* No matching label was found, so it is invalid */
113 return CT_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;
130 return sprite;
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);
145 GetString (b_name, (*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);
157 if (res == 0) {
158 res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
159 if (res == 0) {
160 res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
161 if (res == 0) {
162 return CargoSpecNameSorter(a, b);
167 return res;
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());