OpenTTD Source 20260911-master-gee2b2ac12a
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:
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(Severity::Error, "IndustryTilesChangeInfo: Too many industry tiles loaded ({}), max ({}). Ignoring.", last, NUM_INDUSTRYTILES_PER_GRF);
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(Severity::Warning, "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(Severity::Warning, "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;
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
195 break;
196
197 default:
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:
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(Severity::Error, "IndustriesChangeInfo: Too many industries loaded ({}), max ({}). Ignoring.", last, NUM_INDUSTRYTYPES_PER_GRF);
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(Severity::Warning, "_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 = IndustryCheck::None;
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(Severity::Warning, "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 num_layouts = buf.ReadByte();
406 size_t definition_size = buf.ReadDWord();
407 size_t definition_end = definition_size + buf.GetBytesRead();
408
409 std::vector<IndustryTileLayout> layouts;
410 layouts.reserve(num_layouts);
411
412 IndustryTileLayout layout;
413
414 for (uint8_t j = 0; j < num_layouts; j++) {
415 bool invalid_layout = false;
416 layout.clear();
417
418 for (uint k = 0;; k++) {
419 if (definition_end < buf.GetBytesRead()) {
420 GrfMsg(Severity::Notice, "IndustriesChangeInfo: Incorrect size for industry tile layout definition for industry {}.", id);
421 /* Avoid warning twice */
422 definition_end = SIZE_MAX;
423 }
424
425 IndustryTileLayoutTile &it = layout.emplace_back();
426
427 it.ti.x = buf.ReadByte(); // Offsets from northernmost tile
428
429 if (it.ti.x == 0xFE && k == 0) {
430 /* This means we have to borrow the layout from an old industry */
431 IndustryType type = buf.ReadByte();
432 uint8_t laynbr = buf.ReadByte();
433
434 if (type >= lengthof(_origin_industry_specs)) {
435 GrfMsg(Severity::Error, "IndustriesChangeInfo: Invalid original industry number for layout import, industry {}", id);
436 DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
438 }
439 if (laynbr >= _origin_industry_specs[type].layouts.size()) {
440 GrfMsg(Severity::Error, "IndustriesChangeInfo: Invalid original industry layout index for layout import, industry {}", id);
441 DisableGrf(STR_NEWGRF_ERROR_INVALID_ID);
443 }
444 layout = _origin_industry_specs[type].layouts[laynbr];
445 break;
446 }
447
448 it.ti.y = buf.ReadByte(); // Or table definition finalisation
449
450 if (it.ti.x == 0 && it.ti.y == 0x80) {
451 /* Terminator, remove and finish up */
452 layout.pop_back();
453 break;
454 }
455
456 it.gfx = buf.ReadByte();
457
458 if (it.gfx == 0xFE) {
459 /* Use a new tile from this GRF */
460 int local_tile_id = buf.ReadWord();
461
462 /* Read the ID from the _industile_mngr. */
463 int tempid = _industile_mngr.GetID(local_tile_id, _cur_gps.grffile->grfid);
464
465 if (tempid == INVALID_INDUSTRYTILE) {
466 GrfMsg(Severity::Warning, "IndustriesChangeInfo: Attempt to use industry tile {} with industry id {}, not yet defined. Ignoring.", local_tile_id, id);
467 invalid_layout = true;
468 } else {
469 /* Declared as been valid, can be used */
470 it.gfx = tempid;
471 }
472 } else if (it.gfx == 0xFF) {
474 it.ti.x = (int8_t)GB(it.ti.x, 0, 8);
475 it.ti.y = (int8_t)GB(it.ti.y, 0, 8);
476
477 /* When there were only 256x256 maps, TileIndex was a uint16_t and
478 * it.ti was just a TileIndexDiff that was added to it.
479 * As such negative "x" values were shifted into the "y" position.
480 * x = -1, y = 1 -> x = 255, y = 0
481 * Since GRF version 8 the position is interpreted as pair of independent int8.
482 * For GRF version < 8 we need to emulate the old shifting behaviour.
483 */
484 if (_cur_gps.grffile->grf_version < 8 && it.ti.x < 0) it.ti.y += 1;
485 } else if (it.gfx >= NEW_INDUSTRYTILEOFFSET) {
486 GrfMsg(Severity::Warning, "IndustriesChangeInfo: Attempt to use invalid industry tile {} with industry id {}. Ignoring.", it.gfx, id);
487 invalid_layout = true;
488 }
489 }
490
491 if (invalid_layout) continue;
492
493 if (!ValidateIndustryLayout(layout)) {
494 /* The industry layout was not valid, so skip this one. */
495 GrfMsg(Severity::Error, "IndustriesChangeInfo: Invalid industry layout for industry id {}. Ignoring", id);
496 } else {
497 layouts.push_back(layout);
498 }
499 }
500
501 /* Install final layout construction in the industry spec */
502 indsp->layouts = std::move(layouts);
503 break;
504 }
505
506 case 0x0B: // Industry production flags
507 indsp->life_type = IndustryLifeTypes{buf.ReadByte()};
508 break;
509
510 case 0x0C: // Industry closure message
511 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->closure_text);
512 break;
513
514 case 0x0D: // Production increase message
515 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->production_up_text);
516 break;
517
518 case 0x0E: // Production decrease message
519 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->production_down_text);
520 break;
521
522 case 0x0F: // Fund cost multiplier
523 indsp->cost_multiplier = buf.ReadByte();
524 break;
525
526 case 0x10: // Production cargo types
527 for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_OUTPUTS; j++) {
528 indsp->produced_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
529 indsp->produced_cargo_label[j] = CT_INVALID;
530 }
531 break;
532
533 case 0x11: // Acceptance cargo types
534 for (uint8_t j = 0; j < INDUSTRY_ORIGINAL_NUM_INPUTS; j++) {
535 indsp->accepts_cargo[j] = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
536 indsp->accepts_cargo_label[j] = CT_INVALID;
537 }
538 buf.ReadByte(); // Unused, eat it up
539 break;
540
541 case 0x12: // Production multipliers
542 case 0x13:
543 indsp->production_rate[prop - 0x12] = buf.ReadByte();
544 break;
545
546 case 0x14: // Minimal amount of cargo distributed
547 indsp->minimal_cargo = buf.ReadByte();
548 break;
549
550 case 0x15: { // Random sound effects
551 uint8_t num_sounds = buf.ReadByte();
552
553 std::vector<uint8_t> sounds;
554 sounds.reserve(num_sounds);
555 for (uint8_t j = 0; j < num_sounds; ++j) {
556 sounds.push_back(buf.ReadByte());
557 }
558
559 indsp->random_sounds = std::move(sounds);
560 break;
561 }
562
563 case 0x16: // Conflicting industry types
564 for (uint8_t j = 0; j < 3; j++) indsp->conflicting[j] = buf.ReadByte();
565 break;
566
567 case 0x17: // Probability in random game
568 indsp->appear_creation[to_underlying(_settings_game.game_creation.landscape)] = buf.ReadByte();
569 break;
570
571 case 0x18: // Probability during gameplay
572 indsp->appear_ingame[to_underlying(_settings_game.game_creation.landscape)] = buf.ReadByte();
573 break;
574
575 case 0x19: // Map colour
576 indsp->map_colour = PixelColour{buf.ReadByte()};
577 break;
578
579 case 0x1A: // Special industry flags to define special behavior
580 indsp->behaviour = IndustryBehaviours{buf.ReadDWord()};
581 break;
582
583 case 0x1B: // New industry text ID
584 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->new_industry_text);
585 break;
586
587 case 0x1C: // Input cargo multipliers for the three input cargo types
588 case 0x1D:
589 case 0x1E: {
590 uint32_t multiples = buf.ReadDWord();
591 indsp->input_cargo_multiplier[prop - 0x1C][0] = GB(multiples, 0, 16);
592 indsp->input_cargo_multiplier[prop - 0x1C][1] = GB(multiples, 16, 16);
593 break;
594 }
595
596 case 0x1F: // Industry name
597 AddStringForMapping(GRFStringID{buf.ReadWord()}, &indsp->name);
598 break;
599
600 case 0x20: // Prospecting success chance
601 indsp->prospecting_chance = buf.ReadDWord();
602 break;
603
604 case 0x21: // Callback mask
605 case 0x22: { // Callback additional mask
606 auto mask = indsp->callback_mask.base();
607 SB(mask, (prop - 0x21) * 8, 8, buf.ReadByte());
608 indsp->callback_mask = IndustryCallbackMasks{mask};
609 break;
610 }
611
612 case 0x23: // removal cost multiplier
613 indsp->removal_cost_multiplier = buf.ReadDWord();
614 break;
615
616 case 0x24: { // name for nearby station
617 GRFStringID str{buf.ReadWord()};
618 if (str == 0) {
619 indsp->station_name = STR_NULL;
620 } else {
621 AddStringForMapping(str, &indsp->station_name);
622 }
623 break;
624 }
625
626 case 0x25: { // variable length produced cargoes
627 uint8_t num_cargoes = buf.ReadByte();
628 if (num_cargoes > std::size(indsp->produced_cargo)) {
629 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
630 error->param_value[1] = prop;
632 }
633 for (size_t i = 0; i < std::size(indsp->produced_cargo); i++) {
634 if (i < num_cargoes) {
635 CargoType cargo = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
636 indsp->produced_cargo[i] = cargo;
637 } else {
638 indsp->produced_cargo[i] = INVALID_CARGO;
639 }
640 if (i < std::size(indsp->produced_cargo_label)) indsp->produced_cargo_label[i] = CT_INVALID;
641 }
642 break;
643 }
644
645 case 0x26: { // variable length accepted cargoes
646 uint8_t num_cargoes = buf.ReadByte();
647 if (num_cargoes > std::size(indsp->accepts_cargo)) {
648 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
649 error->param_value[1] = prop;
651 }
652 for (size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
653 if (i < num_cargoes) {
654 CargoType cargo = GetCargoTranslation(buf.ReadByte(), _cur_gps.grffile);
655 indsp->accepts_cargo[i] = cargo;
656 } else {
657 indsp->accepts_cargo[i] = INVALID_CARGO;
658 }
659 if (i < std::size(indsp->accepts_cargo_label)) indsp->accepts_cargo_label[i] = CT_INVALID;
660 }
661 break;
662 }
663
664 case 0x27: { // variable length production rates
665 uint8_t num_cargoes = buf.ReadByte();
666 if (num_cargoes > lengthof(indsp->production_rate)) {
667 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
668 error->param_value[1] = prop;
670 }
671 for (uint i = 0; i < lengthof(indsp->production_rate); i++) {
672 if (i < num_cargoes) {
673 indsp->production_rate[i] = buf.ReadByte();
674 } else {
675 indsp->production_rate[i] = 0;
676 }
677 }
678 break;
679 }
680
681 case 0x28: { // variable size input/output production multiplier table
682 uint8_t num_inputs = buf.ReadByte();
683 uint8_t num_outputs = buf.ReadByte();
684 if (num_inputs > std::size(indsp->accepts_cargo) || num_outputs > std::size(indsp->produced_cargo)) {
685 GRFError *error = DisableGrf(STR_NEWGRF_ERROR_LIST_PROPERTY_TOO_LONG);
686 error->param_value[1] = prop;
688 }
689 for (size_t i = 0; i < std::size(indsp->accepts_cargo); i++) {
690 for (size_t j = 0; j < std::size(indsp->produced_cargo); j++) {
691 uint16_t mult = 0;
692 if (i < num_inputs && j < num_outputs) mult = buf.ReadWord();
693 indsp->input_cargo_multiplier[i][j] = mult;
694 }
695 }
696 break;
697 }
698
699 case 0x29: // Badge list
700 indsp->badges = ReadBadgeList(buf, GrfSpecFeature::Industries);
701 break;
702
703 default:
705 break;
706 }
707 }
708
709 return ret;
710}
711
715template <> ChangeInfoResult GrfChangeInfoHandler<GrfSpecFeature::IndustryTiles>::Activation(uint first, uint last, int prop, ByteReader &buf) { return IndustrytilesChangeInfo(first, last, prop, buf); }
716
720template <> ChangeInfoResult GrfChangeInfoHandler<GrfSpecFeature::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:72
CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
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).
size_t GetBytesRead() const
Get number of already read bytes.
uint8_t ReadByte()
Read a single byte (8 bits).
Functions related to debugging.
@ Warning
Warning, wrong but okay if you don't know.
Definition debug_type.h:17
@ Notice
Notice.
Definition debug_type.h:18
@ Error
Error, but we are recovering.
Definition debug_type.h:16
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.
static const IndustryGfx NEW_INDUSTRYTILEOFFSET
original number of tiles
static const IndustryGfx INDUSTRYTILE_NOANIM
Sentinel value 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 constexpr IndustryGfx GFX_WATERTILE_SPECIALCHECK
Sentinel marker in industry layout to perform a water tile check.
static const IndustryGfx NUM_INDUSTRYTILES_PER_GRF
Maximum number of industry tiles per NewGRF.
EnumBitSet< IndustryAnimationTrigger, uint8_t > IndustryAnimationTriggers
Bitset of IndustryAnimationTrigger elements.
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.
EnumBitSet< IndustryLifeType, uint8_t > IndustryLifeTypes
Bitset of IndustryLifeType elements.
std::vector< IndustryTileLayoutTile > IndustryTileLayout
A complete tile layout for an industry is a list of tiles.
EnumBitSet< IndustryBehaviour, uint32_t > IndustryBehaviours
Bitset of IndustryBehaviour elements.
@ None
Always succeeds.
EnumBitSet< IndustryTileSpecialFlag, uint8_t > IndustryTileSpecialFlags
Bitset of IndustryTileSpecialFlag elements.
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:140
@ IndustryTiles
Industry tiles feature.
Definition newgrf.h:89
@ Industries
Industries feature.
Definition newgrf.h:90
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.
EnumBitSet< IndustryTileCallbackMask, uint8_t > IndustryTileCallbackMasks
Bitset of IndustryTileCallbackMask elements.
EnumBitSet< IndustryCallbackMask, uint16_t > IndustryCallbackMasks
Bitset of IndustryCallbackMask elements.
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.
@ Success
Variable was parsed and read.
@ Unhandled
Variable was parsed but unread.
@ Unknown
Variable is unknown.
@ Disabled
GRF was disabled due to error.
@ InvalidId
Attempt to modify an invalid ID.
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:53
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:261
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.
static ChangeInfoResult Reserve(uint first, uint last, int prop, ByteReader &buf)
Implementation of the GrfLoadingStage::Reserve stage of this feature.
static ChangeInfoResult Activation(uint first, uint last, int prop, ByteReader &buf)
Implementation of the GrfLoadingStage::Activation stage of this feature.
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:307
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