OpenTTD Source 20260311-master-g511d3794ce
newgrf_act0_industries.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "../stdafx.h"
11#include "../debug.h"
12#include "../newgrf_cargo.h"
13#include "../industry.h"
14#include "../industrytype.h"
15#include "../industry_map.h"
17#include "newgrf_bytereader.h"
18#include "newgrf_internal.h"
20
21#include "table/strings.h"
22
23#include "../safeguards.h"
24
27
35{
37
38 switch (prop) {
39 case 0x09:
40 case 0x0D:
41 case 0x0E:
42 case 0x10:
43 case 0x11:
44 case 0x12:
45 buf.ReadByte();
46 break;
47
48 case 0x0A:
49 case 0x0B:
50 case 0x0C:
51 case 0x0F:
52 buf.ReadWord();
53 break;
54
55 case 0x13:
56 buf.Skip(buf.ReadByte() * 2);
57 break;
58
59 default:
60 ret = CIR_UNKNOWN;
61 break;
62 }
63 return ret;
64}
65
74static ChangeInfoResult IndustrytilesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
75{
77
78 if (last > NUM_INDUSTRYTILES_PER_GRF) {
79 GrfMsg(1, "IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last, NUM_INDUSTRYTILES_PER_GRF);
80 return CIR_INVALID_ID;
81 }
82
83 /* Allocate industry tile specs if they haven't been allocated already. */
84 if (_cur_gps.grffile->indtspec.size() < last) _cur_gps.grffile->indtspec.resize(last);
85
86 for (uint id = first; id < last; ++id) {
87 auto &tsp = _cur_gps.grffile->indtspec[id];
88
89 if (prop != 0x08 && tsp == nullptr) {
91 if (cir > ret) ret = cir;
92 continue;
93 }
94
95 switch (prop) {
96 case 0x08: { // Substitute industry tile type
97 uint8_t subs_id = buf.ReadByte();
98 if (subs_id >= NEW_INDUSTRYTILEOFFSET) {
99 /* The substitute id must be one of the original industry tile. */
100 GrfMsg(2, "IndustryTilesChangeInfo: Attempt to use new industry tile {} as substitute industry tile for {}. Ignoring.", subs_id, id);
101 continue;
102 }
103
104 /* Allocate space for this industry. */
105 if (tsp == nullptr) {
106 tsp = std::make_unique<IndustryTileSpec>(_industry_tile_specs[subs_id]);
107
108 tsp->enabled = true;
109
110 /* A copied tile should not have the animation infos copied too.
111 * The anim_state should be left untouched, though
112 * It is up to the author to animate them */
113 tsp->anim_production = INDUSTRYTILE_NOANIM;
114 tsp->anim_next = INDUSTRYTILE_NOANIM;
115
116 tsp->grf_prop.local_id = id;
117 tsp->grf_prop.subst_id = subs_id;
118 tsp->grf_prop.SetGRFFile(_cur_gps.grffile);
119 _industile_mngr.AddEntityID(id, _cur_gps.grffile->grfid, subs_id); // pre-reserve the tile slot
120 }
121 break;
122 }
123
124 case 0x09: { // Industry tile override
125 uint8_t ovrid = buf.ReadByte();
126
127 /* The industry being overridden must be an original industry. */
128 if (ovrid >= NEW_INDUSTRYTILEOFFSET) {
129 GrfMsg(2, "IndustryTilesChangeInfo: Attempt to override new industry tile {} with industry tile id {}. Ignoring.", ovrid, id);
130 continue;
131 }
132
133 _industile_mngr.Add(id, _cur_gps.grffile->grfid, ovrid);
134 break;
135 }
136
137 case 0x0A: // Tile acceptance
138 case 0x0B:
139 case 0x0C: {
140 uint16_t acctp = buf.ReadWord();
141 tsp->accepts_cargo[prop - 0x0A] = GetCargoTranslation(GB(acctp, 0, 8), _cur_gps.grffile);
142 tsp->acceptance[prop - 0x0A] = Clamp(GB(acctp, 8, 8), 0, 16);
143 tsp->accepts_cargo_label[prop - 0x0A] = CT_INVALID;
144 break;
145 }
146
147 case 0x0D: // Land shape flags
148 tsp->slopes_refused = (Slope)buf.ReadByte();
149 break;
150
151 case 0x0E: // Callback mask
152 tsp->callback_mask = static_cast<IndustryTileCallbackMasks>(buf.ReadByte());
153 break;
154
155 case 0x0F: // Animation information
156 tsp->animation.frames = buf.ReadByte();
157 tsp->animation.status = static_cast<AnimationStatus>(buf.ReadByte());
158 break;
159
160 case 0x10: // Animation speed
161 tsp->animation.speed = buf.ReadByte();
162 break;
163
164 case 0x11: // Triggers for callback 25
165 tsp->animation.triggers = static_cast<IndustryAnimationTriggers>(buf.ReadByte());
166 break;
167
168 case 0x12: // Special flags
169 tsp->special_flags = IndustryTileSpecialFlags{buf.ReadByte()};
170 break;
171
172 case 0x13: { // variable length cargo acceptance
173 uint8_t num_cargoes = buf.ReadByte();
174 if (num_cargoes > std::size(tsp->acceptance)) {
175 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
176 error->param_value[1] = prop;
177 return CIR_DISABLED;
178 }
179 for (uint i = 0; i < std::size(tsp->acceptance); i++) {
180 if (i < num_cargoes) {
181 tsp->accepts_cargo[i] = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
182 /* Tile acceptance can be negative to counteract the IndustryTileSpecialFlag::AcceptsAllCargo flag */
183 tsp->acceptance[i] = (int8_t)buf.ReadByte();
184 } else {
185 tsp->accepts_cargo[i] = INVALID_CARGO;
186 tsp->acceptance[i] = 0;
187 }
188 if (i < std::size(tsp->accepts_cargo_label)) tsp->accepts_cargo_label[i] = CT_INVALID;
189 }
190 break;
191 }
192
193 case 0x14: // Badge list
194 tsp->badges = ReadBadgeList(buf, GSF_INDUSTRYTILES);
195 break;
196
197 default:
198 ret = CIR_UNKNOWN;
199 break;
200 }
201 }
202
203 return ret;
204}
205
213{
215
216 switch (prop) {
217 case 0x09:
218 case 0x0B:
219 case 0x0F:
220 case 0x12:
221 case 0x13:
222 case 0x14:
223 case 0x17:
224 case 0x18:
225 case 0x19:
226 case 0x21:
227 case 0x22:
228 buf.ReadByte();
229 break;
230
231 case 0x0C:
232 case 0x0D:
233 case 0x0E:
234 case 0x10: // INDUSTRY_ORIGINAL_NUM_OUTPUTS bytes
235 case 0x1B:
236 case 0x1F:
237 case 0x24:
238 buf.ReadWord();
239 break;
240
241 case 0x11: // INDUSTRY_ORIGINAL_NUM_INPUTS bytes + 1
242 case 0x1A:
243 case 0x1C:
244 case 0x1D:
245 case 0x1E:
246 case 0x20:
247 case 0x23:
248 buf.ReadDWord();
249 break;
250
251 case 0x0A: {
252 uint8_t num_table = buf.ReadByte();
253 for (uint8_t j = 0; j < num_table; j++) {
254 for (uint k = 0;; k++) {
255 uint8_t x = buf.ReadByte();
256 if (x == 0xFE && k == 0) {
257 buf.ReadByte();
258 buf.ReadByte();
259 break;
260 }
261
262 uint8_t y = buf.ReadByte();
263 if (x == 0 && y == 0x80) break;
264
265 uint8_t gfx = buf.ReadByte();
266 if (gfx == 0xFE) buf.ReadWord();
267 }
268 }
269 break;
270 }
271
272 case 0x16:
273 for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_INPUTS; j++) buf.ReadByte();
274 break;
275
276 case 0x15:
277 case 0x25:
278 case 0x26:
279 case 0x27:
280 buf.Skip(buf.ReadByte());
281 break;
282
283 case 0x28: {
284 int num_inputs = buf.ReadByte();
285 int num_outputs = buf.ReadByte();
286 buf.Skip(num_inputs * num_outputs * 2);
287 break;
288 }
289
290 case 0x29: // Badge list
291 SkipBadgeList(buf);
292 break;
293
294 default:
295 ret = CIR_UNKNOWN;
296 break;
297 }
298 return ret;
299}
300
307{
308 const size_t size = layout.size();
309 if (size == 0) return false;
310
311 for (size_t i = 0; i < size - 1; i++) {
312 for (size_t j = i + 1; j < size; j++) {
313 if (layout[i].ti.x == layout[j].ti.x &&
314 layout[i].ti.y == layout[j].ti.y) {
315 return false;
316 }
317 }
318 }
319
320 bool have_regular_tile = false;
321 for (const auto &tilelayout : layout) {
322 if (tilelayout.gfx != GFX_WATERTILE_SPECIALCHECK) {
323 have_regular_tile = true;
324 break;
325 }
326 }
327
328 return have_regular_tile;
329}
330
339static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
340{
342
343 if (last > NUM_INDUSTRYTYPES_PER_GRF) {
344 GrfMsg(1, "IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last, NUM_INDUSTRYTYPES_PER_GRF);
345 return CIR_INVALID_ID;
346 }
347
348 /* Allocate industry specs if they haven't been allocated already. */
349 if (_cur_gps.grffile->industryspec.size() < last) _cur_gps.grffile->industryspec.resize(last);
350
351 for (uint id = first; id < last; ++id) {
352 auto &indsp = _cur_gps.grffile->industryspec[id];
353
354 if (prop != 0x08 && indsp == nullptr) {
356 if (cir > ret) ret = cir;
357 continue;
358 }
359
360 switch (prop) {
361 case 0x08: { // Substitute industry type
362 uint8_t subs_id = buf.ReadByte();
363 if (subs_id == 0xFF) {
364 /* Instead of defining a new industry, a substitute industry id
365 * of 0xFF disables the old industry with the current id. */
366 _industry_specs[id].enabled = false;
367 continue;
368 } else if (subs_id >= NEW_INDUSTRYOFFSET) {
369 /* The substitute id must be one of the original industry. */
370 GrfMsg(2, "_industry_specs: Attempt to use new industry {} as substitute industry for {}. Ignoring.", subs_id, id);
371 continue;
372 }
373
374 /* Allocate space for this industry.
375 * Only need to do it once. If ever it is called again, it should not
376 * do anything */
377 if (indsp == nullptr) {
378 indsp = std::make_unique<IndustrySpec>(_origin_industry_specs[subs_id]);
379
380 indsp->enabled = true;
381 indsp->grf_prop.local_id = id;
382 indsp->grf_prop.subst_id = subs_id;
383 indsp->grf_prop.SetGRFFile(_cur_gps.grffile);
384 /* If the grf industry needs to check its surrounding upon creation, it should
385 * rely on callbacks, not on the original placement functions */
386 indsp->check_proc = CHECK_NOTHING;
387 }
388 break;
389 }
390
391 case 0x09: { // Industry type override
392 uint8_t ovrid = buf.ReadByte();
393
394 /* The industry being overridden must be an original industry. */
395 if (ovrid >= NEW_INDUSTRYOFFSET) {
396 GrfMsg(2, "IndustriesChangeInfo: Attempt to override new industry {} with industry id {}. Ignoring.", ovrid, id);
397 continue;
398 }
399 indsp->grf_prop.override_id = ovrid;
400 _industry_mngr.Add(id, _cur_gps.grffile->grfid, ovrid);
401 break;
402 }
403
404 case 0x0A: { // Set industry layout(s)
405 uint8_t new_num_layouts = buf.ReadByte();
406 uint32_t definition_size = buf.ReadDWord();
407 uint32_t bytes_read = 0;
408 std::vector<IndustryTileLayout> new_layouts;
409 IndustryTileLayout layout;
410
411 for (uint8_t j = 0; j < new_num_layouts; j++) {
412 layout.clear();
413
414 for (uint k = 0;; k++) {
415 if (bytes_read >= definition_size) {
416 GrfMsg(3, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.", id);
417 /* Avoid warning twice */
418 definition_size = UINT32_MAX;
419 }
420
421 IndustryTileLayoutTile &it = layout.emplace_back();
422
423 it.ti.x = buf.ReadByte(); // Offsets from northernmost tile
424 ++bytes_read;
425
426 if (it.ti.x == 0xFE && k == 0) {
427 /* This means we have to borrow the layout from an old industry */
428 IndustryType type = buf.ReadByte();
429 uint8_t laynbr = buf.ReadByte();
430 bytes_read += 2;
431
432 if (type >= lengthof(_origin_industry_specs)) {
433 GrfMsg(1, "IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", id);
434 DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
435 return CIR_DISABLED;
436 }
437 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
438 GrfMsg(1, "IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", id);
439 DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
440 return CIR_DISABLED;
441 }
442 layout = _origin_industry_specs[type].layouts[laynbr];
443 break;
444 }
445
446 it.ti.y = buf.ReadByte(); // Or table definition finalisation
447 ++bytes_read;
448
449 if (it.ti.x == 0 && it.ti.y == 0x80) {
450 /* Terminator, remove and finish up */
451 layout.pop_back();
452 break;
453 }
454
455 it.gfx = buf.ReadByte();
456 ++bytes_read;
457
458 if (it.gfx == 0xFE) {
459 /* Use a new tile from this GRF */
460 int local_tile_id = buf.ReadWord();
461 bytes_read += 2;
462
463 /* Read the ID from the _industile_mngr. */
464 int tempid = _industile_mngr.GetID(local_tile_id, _cur_gps.grffile->grfid);
465
466 if (tempid == INVALID_INDUSTRYTILE) {
467 GrfMsg(2, "IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, id);
468 } else {
469 /* Declared as been valid, can be used */
470 it.gfx = tempid;
471 }
472 } else if (it.gfx == GFX_WATERTILE_SPECIALCHECK) {
473 it.ti.x = (int8_t)GB(it.ti.x, 0, 8);
474 it.ti.y = (int8_t)GB(it.ti.y, 0, 8);
475
476 /* When there were only 256x256 maps, TileIndex was a uint16_t and
477 * it.ti was just a TileIndexDiff that was added to it.
478 * As such negative "x" values were shifted into the "y" position.
479 * x = -1, y = 1 -> x = 255, y = 0
480 * Since GRF version 8 the position is interpreted as pair of independent int8.
481 * For GRF version < 8 we need to emulate the old shifting behaviour.
482 */
483 if (_cur_gps.grffile->grf_version < 8 && it.ti.x < 0) it.ti.y += 1;
484 }
485 }
486
487 if (!ValidateIndustryLayout(layout)) {
488 /* The industry layout was not valid, so skip this one. */
489 GrfMsg(1, "IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", id);
490 } else {
491 new_layouts.push_back(layout);
492 }
493 }
494
495 /* Install final layout construction in the industry spec */
496 indsp->layouts = std::move(new_layouts);
497 break;
498 }
499
500 case 0x0B: // Industry production flags
501 indsp->life_type = IndustryLifeTypes{buf.ReadByte()};
502 break;
503
504 case 0x0C: // Industry closure message
505 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->closure_text);
506 break;
507
508 case 0x0D: // Production increase message
509 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->production_up_text);
510 break;
511
512 case 0x0E: // Production decrease message
513 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->production_down_text);
514 break;
515
516 case 0x0F: // Fund cost multiplier
517 indsp->cost_multiplier = buf.ReadByte();
518 break;
519
520 case 0x10: // Production cargo types
521 for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_OUTPUTS; j++) {
522 indsp->produced_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
523 indsp->produced_cargo_label[j] = CT_INVALID;
524 }
525 break;
526
527 case 0x11: // Acceptance cargo types
528 for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_INPUTS; j++) {
529 indsp->accepts_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
530 indsp->accepts_cargo_label[j] = CT_INVALID;
531 }
532 buf.ReadByte(); // Unnused, eat it up
533 break;
534
535 case 0x12: // Production multipliers
536 case 0x13:
537 indsp->production_rate[prop - 0x12] = buf.ReadByte();
538 break;
539
540 case 0x14: // Minimal amount of cargo distributed
541 indsp->minimal_cargo = buf.ReadByte();
542 break;
543
544 case 0x15: { // Random sound effects
545 uint8_t num_sounds = buf.ReadByte();
546
547 std::vector<uint8_t> sounds;
548 sounds.reserve(num_sounds);
549 for (uint8_t j = 0; j < num_sounds; ++j) {
550 sounds.push_back(buf.ReadByte());
551 }
552
553 indsp->random_sounds = std::move(sounds);
554 break;
555 }
556
557 case 0x16: // Conflicting industry types
558 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
559 break;
560
561 case 0x17: // Probability in random game
562 indsp->appear_creation[to_underlying(_settings_game.game_creation.landscape)] = buf.ReadByte();
563 break;
564
565 case 0x18: // Probability during gameplay
566 indsp->appear_ingame[to_underlying(_settings_game.game_creation.landscape)] = buf.ReadByte();
567 break;
568
569 case 0x19: // Map colour
570 indsp->map_colour = PixelColour{buf.ReadByte()};
571 break;
572
573 case 0x1A: // Special industry flags to define special behavior
574 indsp->behaviour = IndustryBehaviours{buf.ReadDWord()};
575 break;
576
577 case 0x1B: // New industry text ID
578 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->new_industry_text);
579 break;
580
581 case 0x1C: // Input cargo multipliers for the three input cargo types
582 case 0x1D:
583 case 0x1E: {
584 uint32_t multiples = buf.ReadDWord();
585 indsp->input_cargo_multiplier[prop - 0x1C][0] = GB(multiples, 0, 16);
586 indsp->input_cargo_multiplier[prop - 0x1C][1] = GB(multiples, 16, 16);
587 break;
588 }
589
590 case 0x1F: // Industry name
591 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->name);
592 break;
593
594 case 0x20: // Prospecting success chance
595 indsp->prospecting_chance = buf.ReadDWord();
596 break;
597
598 case 0x21: // Callback mask
599 case 0x22: { // Callback additional mask
600 auto mask = indsp->callback_mask.base();
601 SB(mask, (prop - 0x21) * 8, 8, buf.ReadByte());
602 indsp->callback_mask = IndustryCallbackMasks{mask};
603 break;
604 }
605
606 case 0x23: // removal cost multiplier
607 indsp->removal_cost_multiplier = buf.ReadDWord();
608 break;
609
610 case 0x24: { // name for nearby station
611 GRFStringID str{buf.ReadWord()};
612 if (str == 0) {
613 indsp->station_name = STR_NULL;
614 } else {
615 AddStringForMapping(str, &indsp->station_name);
616 }
617 break;
618 }
619
620 case 0x25: { // variable length produced cargoes
621 uint8_t num_cargoes = buf.ReadByte();
622 if (num_cargoes > std::size(indsp->produced_cargo)) {
623 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
624 error->param_value[1] = prop;
625 return CIR_DISABLED;
626 }
627 for (size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
628 if (i < num_cargoes) {
629 CargoType cargo = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
630 indsp->produced_cargo[i] = cargo;
631 } else {
632 indsp->produced_cargo[i] = INVALID_CARGO;
633 }
634 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] = CT_INVALID;
635 }
636 break;
637 }
638
639 case 0x26: { // variable length accepted cargoes
640 uint8_t num_cargoes = buf.ReadByte();
641 if (num_cargoes > std::size(indsp->accepts_cargo)) {
642 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
643 error->param_value[1] = prop;
644 return CIR_DISABLED;
645 }
646 for (size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
647 if (i < num_cargoes) {
648 CargoType cargo = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
649 indsp->accepts_cargo[i] = cargo;
650 } else {
651 indsp->accepts_cargo[i] = INVALID_CARGO;
652 }
653 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] = CT_INVALID;
654 }
655 break;
656 }
657
658 case 0x27: { // variable length production rates
659 uint8_t num_cargoes = buf.ReadByte();
660 if (num_cargoes > lengthof(indsp->production_rate)) {
661 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
662 error->param_value[1] = prop;
663 return CIR_DISABLED;
664 }
665 for (uint i = 0; i < lengthof(indsp->production_rate); i++) {
666 if (i < num_cargoes) {
667 indsp->production_rate[i] = buf.ReadByte();
668 } else {
669 indsp->production_rate[i] = 0;
670 }
671 }
672 break;
673 }
674
675 case 0x28: { // variable size input/output production multiplier table
676 uint8_t num_inputs = buf.ReadByte();
677 uint8_t num_outputs = buf.ReadByte();
678 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
679 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
680 error->param_value[1] = prop;
681 return CIR_DISABLED;
682 }
683 for (size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
684 for (size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
685 uint16_t mult = 0;
686 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
687 indsp->input_cargo_multiplier[i][j] = mult;
688 }
689 }
690 break;
691 }
692
693 case 0x29: // Badge list
694 indsp->badges = ReadBadgeList(buf, GSF_INDUSTRIES);
695 break;
696
697 default:
698 ret = CIR_UNKNOWN;
699 break;
700 }
701 }
702
703 return ret;
704}
705
706template <> ChangeInfoResult GrfChangeInfoHandler<GSF_INDUSTRYTILES>::Reserve(uint, uint, int, ByteReader &) { return CIR_UNHANDLED; }
707template <> ChangeInfoResult GrfChangeInfoHandler<GSF_INDUSTRYTILES>::Activation(uint first, uint last, int prop, ByteReader &buf) { return IndustrytilesChangeInfo(first, last, prop, buf); }
708
709template <> ChangeInfoResult GrfChangeInfoHandler<GSF_INDUSTRIES>::Reserve(uint, uint, int, ByteReader &) { return CIR_UNHANDLED; }
710template <> ChangeInfoResult GrfChangeInfoHandler<GSF_INDUSTRIES>::Activation(uint first, uint last, int prop, ByteReader &buf) { return IndustriesChangeInfo(first, last, prop, buf); }
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
static constexpr CargoLabel CT_INVALID
Invalid cargo type.
Definition cargo_type.h:70
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:21
Class to read from a NewGRF file.
uint32_t ReadDWord()
Read a single DWord (32 bits).
uint16_t ReadWord()
Read a single Word (16 bits).
uint8_t ReadByte()
Read a single byte (8 bits).
Functions related to debugging.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Base of all industries.
Accessors to map for industries.
@ GFX_WATERTILE_SPECIALCHECK
not really a tile, but rather a very special check
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
static const IndustryGfx INDUSTRYTILE_NOANIM
flag to mark industry tiles as having no animation
static const IndustryType NEW_INDUSTRYOFFSET
original number of industry types
static const int INDUSTRY_ORIGINAL_NUM_INPUTS
Original number of accepted cargo types.
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF; limited to 255 to allow extending Action3 with an extend...
static const IndustryGfx INVALID_INDUSTRYTILE
one above amount is considered invalid
static const int INDUSTRY_ORIGINAL_NUM_OUTPUTS
Original number of produced cargo types.
static const IndustryType NUM_INDUSTRYTYPES_PER_GRF
maximum number of industry types per NewGRF; limited to 128 because bit 7 has a special meaning in so...
Industry type specs.
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
@ CHECK_NOTHING
Always succeeds.
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
GRFError * DisableGrf(StringID message, GRFConfig *config)
Disable a GRF.
Definition newgrf.cpp:139
std::vector< BadgeID > ReadBadgeList(ByteReader &buf, GrfSpecFeature feature)
Read a list of badges.
void SkipBadgeList(ByteReader &buf)
Skip a list of badges.
const IndustrySpec _origin_industry_specs[NEW_INDUSTRYOFFSET]
Extern declaration for _origin_industry_specs in table/build_industry.h.
static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader &buf)
Ignore an industry property.
static ChangeInfoResult IndustriesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industries.
static ChangeInfoResult IndustrytilesChangeInfo(uint first, uint last, int prop, ByteReader &buf)
Define properties for industry tiles.
static bool ValidateIndustryLayout(const IndustryTileLayout &layout)
Validate the industry layout; e.g.
static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader &buf)
Ignore an industry tile property.
AnimationStatus
Statuses of animation within NewGRFs.
NewGRF buffer reader definition.
CargoType GetCargoTranslation(uint8_t cargo, const GRFFile *grffile, bool usebit)
Translate a GRF-local cargo slot/bitnum into a CargoType.
Cargo support for NewGRFs.
Functions for NewGRF industries.
NewGRF internal processing state.
ChangeInfoResult
Possible return values for the GrfChangeInfoHandler functions.
@ CIR_INVALID_ID
Attempt to modify an invalid ID.
@ CIR_DISABLED
GRF was disabled due to error.
@ CIR_UNKNOWN
Variable is unknown.
@ CIR_UNHANDLED
Variable was parsed but unread.
@ CIR_SUCCESS
Variable was parsed and read.
void AddStringForMapping(GRFStringID source, std::function< void(StringID)> &&func)
Record a static StringID for getting translated later.
NewGRF string mapping definition.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
Slope
Enumeration for the slope-type.
Definition slope_type.h:47
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
Information about why GRF had problems during initialisation.
std::array< uint32_t, 2 > param_value
Values of GRF parameters to show for message and custom_message.
Defines the data structure for constructing industry.
Definition of one tile in an industry tile layout.
Colour for pixel/line drawing.
Definition gfx_type.h:405
int16_t x
The x value of the coordinate.
Definition map_type.h:32
int16_t y
The y value of the coordinate.
Definition map_type.h:33