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