OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

cargotype.cpp
Go to the documentation of this file.
1 /* $Id: cargotype.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
2
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 */
9
12 #include "stdafx.h"
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"
18
19 #include "table/sprites.h"
20 #include "table/strings.h"
21 #include "table/cargo_const.h"
22
23 #include "safeguards.h"
24
25 CargoSpec CargoSpec::array[NUM_CARGO];
26
31 uint32 _cargo_mask;
32
36 uint32 _standard_cargo_mask;
37
42 void SetupCargoForClimate(LandscapeID l)
43 {
44 assert(l < lengthof(_default_climate_cargo));
45
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;
50
51 /* Set defaults for newer properties, which old GRFs do not know */
52 CargoSpec::Get(i)->multiplier = 0x100;
53 }
54
55 _cargo_mask = 0;
56
57 for (CargoID i = 0; i < lengthof(_default_climate_cargo[l]); i++) {
58 CargoLabel cl = _default_climate_cargo[l][i];
59
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);
66 continue;
67 }
68
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];
74
75 /* Populate the available cargo mask */
76 SetBit(_cargo_mask, i);
77 break;
78 }
79 }
80 }
81 }
82
88 CargoID GetCargoIDByLabel(CargoLabel cl)
89 {
90 const CargoSpec *cs;
91 FOR_ALL_CARGOSPECS(cs) {
92 if (cs->label == cl) return cs->Index();
93 }
94
95 /* No matching label was found, so it is invalid */
96 return CT_INVALID;
97 }
98
99
105 CargoID GetCargoIDByBitnum(uint8 bitnum)
106 {
107 if (bitnum == INVALID_CARGO) return CT_INVALID;
108
109 const CargoSpec *cs;
110 FOR_ALL_CARGOSPECS(cs) {
111 if (cs->bitnum == bitnum) return cs->Index();
112 }
113
114 /* No matching label was found, so it is invalid */
115 return CT_INVALID;
116 }
117
122 SpriteID CargoSpec::GetCargoIcon() const
123 {
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);
128 }
129
130 if (sprite == 0) sprite = SPR_CARGO_GOODS;
131
132 return sprite;
133 }
134
135 const CargoSpec *_sorted_cargo_specs[NUM_CARGO];
136 uint8 _sorted_cargo_specs_size;
137 uint8 _sorted_standard_cargo_specs_size;
138
139
141 static int CDECL CargoSpecNameSorter(const CargoSpec * const *a, const CargoSpec * const *b)
142 {
143 static char a_name[64];
144 static char b_name[64];
145
146 GetString(a_name, (*a)->name, lastof(a_name));
147 GetString(b_name, (*b)->name, lastof(b_name));
148
149 int res = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
150
151 /* If the names are equal, sort by cargo bitnum. */
152 return (res != 0) ? res : ((*a)->bitnum - (*b)->bitnum);
153 }
154
156 static int CDECL CargoSpecClassSorter(const CargoSpec * const *a, const CargoSpec * const *b)
157 {
158 int res = ((*b)->classes & CC_PASSENGERS) - ((*a)->classes & CC_PASSENGERS);
159 if (res == 0) {
160 res = ((*b)->classes & CC_MAIL) - ((*a)->classes & CC_MAIL);
161 if (res == 0) {
162 res = ((*a)->classes & CC_SPECIAL) - ((*b)->classes & CC_SPECIAL);
163 if (res == 0) {
164 return CargoSpecNameSorter(a, b);
165 }
166 }
167 }
168
169 return res;
170 }
171
173 void InitializeSortedCargoSpecs()
174 {
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++;
181 }
182
183 /* Sort cargo specifications by cargo class and name. */
184 QSortT(_sorted_cargo_specs, _sorted_cargo_specs_size, &CargoSpecClassSorter);
185
186 _standard_cargo_mask = 0;
187
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());
193 }
194 }
195