OpenTTD Source 20260820-master-g39da062c0c
newgrf_commons.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 "landscape.h"
13#include "house.h"
14#include "industrytype.h"
15#include "newgrf_config.h"
16#include "company_func.h"
17#include "clear_map.h"
18#include "station_map.h"
19#include "tree_map.h"
20#include "tunnelbridge_map.h"
21#include "newgrf_object.h"
22#include "genworld.h"
23#include "newgrf_spritegroup.h"
24#include "newgrf_text.h"
25#include "company_base.h"
26#include "error.h"
27#include "strings_func.h"
28#include "string_func.h"
29
30#include "table/strings.h"
31
32#include "safeguards.h"
33
40OverrideManagerBase::OverrideManagerBase(uint16_t offset, uint16_t maximum, uint16_t invalid)
41 : max_offset(offset), max_entities(maximum), invalid_id(invalid)
42{
43 this->mappings.resize(this->max_entities);
44 this->entity_overrides.resize(this->max_offset);
45 std::fill(this->entity_overrides.begin(), this->entity_overrides.end(), this->invalid_id);
46 this->grfid_overrides.resize(this->max_offset);
47}
48
57void OverrideManagerBase::Add(uint16_t local_id, GrfID grfid, uint entity_type)
58{
59 assert(entity_type < this->max_offset);
60 /* An override can be set only once */
61 if (this->entity_overrides[entity_type] != this->invalid_id) return;
62 this->entity_overrides[entity_type] = local_id;
63 this->grfid_overrides[entity_type] = grfid;
64}
65
68{
69 std::fill(this->mappings.begin(), this->mappings.end(), EntityIDMapping{});
70}
71
74{
75 std::fill(this->entity_overrides.begin(), this->entity_overrides.end(), this->invalid_id);
76 std::fill(this->grfid_overrides.begin(), this->grfid_overrides.end(), GrfID{});
77}
78
85uint16_t OverrideManagerBase::GetID(uint16_t grf_local_id, GrfID grfid) const
86{
87 for (uint16_t id = 0; id < this->max_entities; id++) {
88 const EntityIDMapping *map = &this->mappings[id];
89 if (map->entity_id == grf_local_id && map->grfid == grfid) {
90 return id;
91 }
92 }
93
94 return this->invalid_id;
95}
96
104uint16_t OverrideManagerBase::AddEntityID(uint16_t grf_local_id, GrfID grfid, uint16_t substitute_id)
105{
106 uint16_t id = this->GetID(grf_local_id, grfid);
107
108 /* Look to see if this entity has already been added. This is done
109 * separately from the loop below in case a GRF has been deleted, and there
110 * are any gaps in the array.
111 */
112 if (id != this->invalid_id) return id;
113
114 /* This entity hasn't been defined before, so give it an ID now. */
115 for (id = this->max_offset; id < this->max_entities; id++) {
116 EntityIDMapping *map = &this->mappings[id];
117
118 if (map->entity_id == 0 && map->grfid.Empty()) {
119 map->entity_id = grf_local_id;
120 map->grfid = grfid;
121 map->substitute_id = substitute_id;
122 return id;
123 }
124 }
125
126 return this->invalid_id;
127}
128
134GrfID OverrideManagerBase::GetGRFID(uint16_t entity_id) const
135{
136 return this->mappings[entity_id].grfid;
137}
138
144uint16_t OverrideManagerBase::GetSubstituteID(uint16_t entity_id) const
145{
146 return this->mappings[entity_id].substitute_id;
147}
148
155{
156 HouseID house_id = this->AddEntityID(hs.grf_prop.local_id, hs.grf_prop.grfid, hs.grf_prop.subst_id);
157
158 if (house_id == this->invalid_id) {
159 GrfMsg(1, "House.SetEntitySpec: Too many houses allocated. Ignoring.");
160 return;
161 }
162
163 auto &house_specs = HouseSpec::Specs();
164
165 /* Now that we know we can use the given id, copy the spec to its final destination. */
166 if (house_id >= house_specs.size()) house_specs.resize(house_id + 1);
167 house_specs[house_id] = std::move(hs);
168
169 /* Now add the overrides. */
170 for (int i = 0; i < this->max_offset; i++) {
171 HouseSpec *overridden_hs = HouseSpec::Get(i);
172
173 if (this->entity_overrides[i] != house_specs[house_id].grf_prop.local_id || this->grfid_overrides[i] != house_specs[house_id].grf_prop.grfid) continue;
174
175 overridden_hs->grf_prop.override_id = house_id;
176 this->entity_overrides[i] = this->invalid_id;
177 this->grfid_overrides[i] = {};
178 }
179}
180
187uint16_t IndustryOverrideManager::GetID(uint16_t grf_local_id, GrfID grfid) const
188{
189 uint16_t id = OverrideManagerBase::GetID(grf_local_id, grfid);
190 if (id != this->invalid_id) return id;
191
192 /* No mapping found, try the overrides */
193 for (id = 0; id < this->max_offset; id++) {
194 if (this->entity_overrides[id] == grf_local_id && this->grfid_overrides[id] == grfid) return id;
195 }
196
197 return this->invalid_id;
198}
199
207uint16_t IndustryOverrideManager::AddEntityID(uint16_t grf_local_id, GrfID grfid, uint16_t substitute_id)
208{
209 /* This entity hasn't been defined before, so give it an ID now. */
210 for (uint16_t id = 0; id < this->max_entities; id++) {
211 /* Skip overridden industries */
212 if (id < this->max_offset && this->entity_overrides[id] != this->invalid_id) continue;
213
214 /* Get the real live industry */
215 const IndustrySpec *inds = GetIndustrySpec(id);
216
217 /* This industry must be one that is not available(enabled), mostly because of climate.
218 * And it must not already be used by a grf (grffile == nullptr).
219 * So reserve this slot here, as it is the chosen one */
220 if (!inds->enabled && !inds->grf_prop.HasGrfFile()) {
221 EntityIDMapping *map = &this->mappings[id];
222
223 if (map->entity_id == 0 && map->grfid.Empty()) {
224 /* winning slot, mark it as been used */
225 map->entity_id = grf_local_id;
226 map->grfid = grfid;
227 map->substitute_id = substitute_id;
228 return id;
229 }
230 }
231 }
232
233 return this->invalid_id;
234}
235
243{
244 /* First step : We need to find if this industry is already specified in the savegame data. */
245 IndustryType ind_id = this->GetID(inds.grf_prop.local_id, inds.grf_prop.grfid);
246
247 if (ind_id == this->invalid_id) {
248 /* Not found.
249 * Or it has already been overridden, so you've lost your place.
250 * Or it is a simple substitute.
251 * We need to find a free available slot */
252 ind_id = this->AddEntityID(inds.grf_prop.local_id, inds.grf_prop.grfid, inds.grf_prop.subst_id);
253 inds.grf_prop.override_id = this->invalid_id; // make sure it will not be detected as overridden
254 }
255
256 if (ind_id == this->invalid_id) {
257 GrfMsg(1, "Industry.SetEntitySpec: Too many industries allocated. Ignoring.");
258 return;
259 }
260
261 /* Now that we know we can use the given id, copy the spec to its final destination... */
262 _industry_specs[ind_id] = std::move(inds);
263 /* ... and mark it as usable*/
264 _industry_specs[ind_id].enabled = true;
265}
266
267void IndustryTileOverrideManager::SetEntitySpec(IndustryTileSpec &&its)
268{
269 IndustryGfx indt_id = this->AddEntityID(its.grf_prop.local_id, its.grf_prop.grfid, its.grf_prop.subst_id);
270
271 if (indt_id == this->invalid_id) {
272 GrfMsg(1, "IndustryTile.SetEntitySpec: Too many industry tiles allocated. Ignoring.");
273 return;
274 }
275
276 _industry_tile_specs[indt_id] = std::move(its);
277
278 /* Now add the overrides. */
279 for (int i = 0; i < this->max_offset; i++) {
280 IndustryTileSpec *overridden_its = &_industry_tile_specs[i];
281
282 if (this->entity_overrides[i] != _industry_tile_specs[indt_id].grf_prop.local_id || this->grfid_overrides[i] != _industry_tile_specs[indt_id].grf_prop.grfid) continue;
283
284 overridden_its->grf_prop.override_id = indt_id;
285 overridden_its->enabled = false;
286 this->entity_overrides[i] = this->invalid_id;
287 this->grfid_overrides[i] = {};
288 }
289}
290
298{
299 /* First step : We need to find if this object is already specified in the savegame data. */
300 ObjectType type = this->GetID(spec.grf_prop.local_id, spec.grf_prop.grfid);
301
302 if (type == this->invalid_id) {
303 /* Not found.
304 * Or it has already been overridden, so you've lost your place.
305 * Or it is a simple substitute.
306 * We need to find a free available slot */
307 type = this->AddEntityID(spec.grf_prop.local_id, spec.grf_prop.grfid, OBJECT_TRANSMITTER);
308 }
309
310 if (type == this->invalid_id) {
311 GrfMsg(1, "Object.SetEntitySpec: Too many objects allocated. Ignoring.");
312 return;
313 }
314
315 extern std::vector<ObjectSpec> _object_specs;
316
317 /* Now that we know we can use the given id, copy the spec to its final destination. */
318 if (type >= _object_specs.size()) _object_specs.resize(type + 1);
319 _object_specs[type] = std::move(spec);
320}
321
330uint32_t GetTerrainType(TileIndex tile, TileContext context)
331{
332 switch (_settings_game.game_creation.landscape) {
335 bool has_snow;
336 switch (GetTileType(tile)) {
337 case TileType::Clear:
338 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
339 if (_generating_world) goto genworld;
340 has_snow = IsSnowTile(tile) && GetClearDensity(tile) >= 2;
341 break;
342
343 case TileType::Railway: {
344 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
345 if (_generating_world) goto genworld; // we do not care about foundations here
346 RailGroundType ground = GetRailGroundType(tile);
347 has_snow = (ground == RailGroundType::SnowOrDesert || (context == TileContext::UpperHalftile && ground == RailGroundType::HalfTileSnow));
348 break;
349 }
350
351 case TileType::Road:
352 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
353 if (_generating_world) goto genworld; // we do not care about foundations here
354 has_snow = IsOnSnowOrDesert(tile);
355 break;
356
357 case TileType::Trees: {
358 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
359 if (_generating_world) goto genworld;
360 TreeGround ground = GetTreeGround(tile);
361 has_snow = (ground == TreeGround::SnowOrDesert || ground == TreeGround::RoughSnow) && GetTreeDensity(tile) >= 2;
362 break;
363 }
364
366 if (context == TileContext::OnBridge) {
367 has_snow = (GetBridgeHeight(tile) > GetSnowLine());
368 } else {
369 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
370 if (_generating_world) goto genworld; // we do not care about foundations here
371 has_snow = HasTunnelBridgeSnowOrDesert(tile);
372 }
373 break;
374
376 case TileType::House:
378 case TileType::Object:
379 /* These tiles usually have a levelling foundation. So use max Z */
380 has_snow = (GetTileMaxZ(tile) > GetSnowLine());
381 break;
382
383 case TileType::Void:
384 case TileType::Water:
385 genworld:
386 has_snow = (GetTileZ(tile) > GetSnowLine());
387 break;
388
389 default: NOT_REACHED();
390 }
391 return has_snow ? 4 : 0;
392 }
393 default: return 0;
394 }
395}
396
405TileIndex GetNearbyTile(uint8_t parameter, TileIndex tile, bool signed_offsets, Axis axis)
406{
407 int8_t x = GB(parameter, 0, 4);
408 int8_t y = GB(parameter, 4, 4);
409
410 if (signed_offsets && x >= 8) x -= 16;
411 if (signed_offsets && y >= 8) y -= 16;
412
413 /* Swap width and height depending on axis for railway stations */
414 if (axis == Axis::Invalid && HasStationTileRail(tile)) axis = GetRailStationAxis(tile);
415 if (axis == Axis::Y) std::swap(x, y);
416
417 /* Make sure we never roam outside of the map, better wrap in that case */
418 return Map::WrapToMap(tile + TileDiffXY(x, y));
419}
420
428uint32_t GetNearbyTileInformation(TileIndex tile, bool grf_version8)
429{
430 TileType tile_type = GetTileType(tile);
431
432 /* Fake tile type for trees on shore */
434
435 /* Fake tile type for road waypoints */
436 if (IsRoadWaypointTile(tile)) tile_type = TileType::Road;
437
438 auto [tileh, z] = GetTilePixelSlope(tile);
439 /* Return 0 if the tile is a land tile */
440 uint8_t terrain_type = (HasTileWaterClass(tile) ? (to_underlying(GetWaterClass(tile)) + 1) & 3 : 0) << 5 | GetTerrainType(tile) << 2 | (tile_type == TileType::Water ? 1 : 0) << 1;
441 if (grf_version8) z /= TILE_HEIGHT;
442 return to_underlying(tile_type) << 24 | ClampTo<uint8_t>(z) << 16 | terrain_type << 8 | tileh;
443}
444
451uint32_t GetCompanyInfo(CompanyID owner, const Livery *l)
452{
453 if (l == nullptr && Company::IsValidID(owner)) l = &Company::Get(owner)->livery[LiveryScheme::Default];
454 return owner.base() | (Company::IsValidAiID(owner) ? 0x10000 : 0) | (l != nullptr ? (to_underlying(l->colour1) << 24) | (to_underlying(l->colour2) << 28) : 0);
455}
456
465CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span<const int32_t> textstack, const GRFFile *grffile, StringID default_error)
466{
467 auto get_newgrf_text = [&grffile](GRFStringID text_id, std::span<const int32_t> textstack) {
468 CommandCost res = CommandCost(GetGRFStringID(grffile->grfid, text_id));
469
470 /* If this error isn't for the local player then it won't be seen, so don't bother encoding anything. */
471 if (IsLocalCompany()) {
472 StringID stringid = GetGRFStringID(grffile->grfid, text_id);
473 auto params = GetGRFStringTextStackParameters(grffile, stringid, textstack);
474 res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params));
475 }
476
477 return res;
478 };
479
480 CommandCost res;
481 if (cb_res < 0x400) {
482 res = get_newgrf_text(GRFSTR_MISC_GRF_TEXT + cb_res, textstack);
483 } else {
484 switch (cb_res) {
485 case 0x400: return res; // No error.
486
487 default: // unknown reason -> default error
488 case 0x401: res = CommandCost(default_error); break;
489
490 case 0x402: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST); break;
491 case 0x403: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT); break;
492 case 0x404: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE); break;
493 case 0x405: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE); break;
494 case 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break;
495 case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); break;
496 case 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break;
497 case 0x40F: res = get_newgrf_text(static_cast<GRFStringID>(textstack[0]), textstack.subspan(1)); break;
498 }
499 }
500
501 return res;
502}
503
511void ErrorUnknownCallbackResult(GrfID grfid, uint16_t cbid, uint16_t cb_res)
512{
513 GRFConfig *grfconfig = GetGRFConfig(grfid);
514
515 if (grfconfig->grf_bugs.Test(GRFBug::UnknownCbResult)) {
517 ShowErrorMessage(GetEncodedString(STR_NEWGRF_BUGGY, grfconfig->GetName()),
518 GetEncodedString(STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT, std::monostate{}, cbid, cb_res),
520 }
521
522 /* debug output */
523 Debug(grf, 0, "{}", StrMakeValid(GetString(STR_NEWGRF_BUGGY, grfconfig->GetName())));
524
525 Debug(grf, 0, "{}", StrMakeValid(GetString(STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT, std::monostate{}, cbid, cb_res)));
526}
527
537bool ConvertBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
538{
539 assert(cb_res != CALLBACK_FAILED); // We do not know what to return
540
541 if (grffile->grf_version < 8) return cb_res != 0;
542
543 if (cb_res > 1) ErrorUnknownCallbackResult(grffile->grfid, cbid, cb_res);
544 return cb_res != 0;
545}
546
556bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
557{
558 assert(cb_res != CALLBACK_FAILED); // We do not know what to return
559
560 if (grffile->grf_version < 8) return GB(cb_res, 0, 8) != 0;
561
562 if (cb_res > 1) ErrorUnknownCallbackResult(grffile->grfid, cbid, cb_res);
563 return cb_res != 0;
564}
565
570void NewGRFSpriteLayout::Allocate(uint num_sprites)
571{
572 assert(this->seq.empty());
573
574 this->seq.resize(num_sprites, {});
575}
576
581{
582 assert(this->registers.empty());
583
584 this->registers.resize(1 + this->seq.size(), {}); // 1 for the ground sprite
585}
586
597SpriteLayoutProcessor::SpriteLayoutProcessor(const NewGRFSpriteLayout &raw_layout, uint32_t orig_offset, uint32_t newgrf_ground_offset, uint32_t newgrf_offset, uint constr_stage, bool separate_ground) :
598 raw_layout(&raw_layout), separate_ground(separate_ground)
599{
600 this->result_seq.reserve(this->raw_layout->seq.size() + 1);
601
602 /* Create a copy of the spritelayout, so we can modify some values.
603 * Also include the groundsprite into the sequence for easier processing. */
604 DrawTileSeqStruct &copy = this->result_seq.emplace_back();
605 copy.image = this->raw_layout->ground;
606 copy.origin.z = static_cast<int8_t>(0x80);
607
608 this->result_seq.insert(this->result_seq.end(), this->raw_layout->seq.begin(), this->raw_layout->seq.end());
609
610 /* Determine the var10 values the action-1-2-3 chains needs to be resolved for,
611 * and apply the default sprite offsets (unless disabled). */
612 const TileLayoutRegisters *regs = this->raw_layout->registers.empty() ? nullptr : this->raw_layout->registers.data();
613 bool ground = true;
614 for (DrawTileSeqStruct &result : this->result_seq) {
615 TileLayoutFlags flags = TLF_NOTHING;
616 if (regs != nullptr) flags = regs->flags;
617
618 /* Record var10 value for the sprite */
619 if (HasBit(result.image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_SPRITE_REG_FLAGS)) {
620 uint8_t var10 = (flags & TLF_SPRITE_VAR10) ? regs->sprite_var10 : (ground && this->separate_ground ? 1 : 0);
621 SetBit(this->var10_values, var10);
622 }
623
624 /* Add default sprite offset, unless there is a custom one */
625 if (!(flags & TLF_SPRITE)) {
626 if (HasBit(result.image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
627 result.image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
628 if (constr_stage > 0 && regs != nullptr) result.image.sprite += GetConstructionStageOffset(constr_stage, regs->max_sprite_offset);
629 } else {
630 result.image.sprite += orig_offset;
631 }
632 }
633
634 /* Record var10 value for the palette */
635 if (HasBit(result.image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_PALETTE_REG_FLAGS)) {
636 uint8_t var10 = (flags & TLF_PALETTE_VAR10) ? regs->palette_var10 : (ground && this->separate_ground ? 1 : 0);
637 SetBit(this->var10_values, var10);
638 }
639
640 /* Add default palette offset, unless there is a custom one */
641 if (!(flags & TLF_PALETTE)) {
642 if (HasBit(result.image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
643 result.image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
644 if (constr_stage > 0 && regs != nullptr) result.image.sprite += GetConstructionStageOffset(constr_stage, regs->max_palette_offset);
645 }
646 }
647
648 ground = false;
649 if (regs != nullptr) regs++;
650 }
651}
652
659void SpriteLayoutProcessor::ProcessRegisters(const ResolverObject &object, uint8_t resolved_var10, uint32_t resolved_sprite)
660{
661 assert(this->raw_layout != nullptr);
662 const TileLayoutRegisters *regs = this->raw_layout->registers.empty() ? nullptr : this->raw_layout->registers.data();
663 bool ground = true;
664 for (DrawTileSeqStruct &result : this->result_seq) {
665 TileLayoutFlags flags = TLF_NOTHING;
666 if (regs != nullptr) flags = regs->flags;
667
668 /* Is the sprite or bounding box affected by an action-1-2-3 chain? */
669 if (HasBit(result.image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_SPRITE_REG_FLAGS)) {
670 /* Does the var10 value apply to this sprite? */
671 uint8_t var10 = (flags & TLF_SPRITE_VAR10) ? regs->sprite_var10 : (ground && this->separate_ground ? 1 : 0);
672 if (var10 == resolved_var10) {
673 /* Apply registers */
674 if ((flags & TLF_DODRAW) && object.GetRegister(regs->dodraw) == 0) {
675 result.image.sprite = 0;
676 } else {
677 if (HasBit(result.image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) result.image.sprite += resolved_sprite;
678 if (flags & TLF_SPRITE) {
679 int16_t offset = static_cast<int16_t>(object.GetRegister(regs->sprite)); // mask to 16 bits to avoid trouble
680 if (!HasBit(result.image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_sprite_offset)) {
681 result.image.sprite += offset;
682 } else {
683 result.image.sprite = SPR_IMG_QUERY;
684 }
685 }
686
687 if (result.IsParentSprite()) {
688 if (flags & TLF_BB_XY_OFFSET) {
689 result.origin.x += object.GetRegister(regs->delta.parent[0]);
690 result.origin.y += object.GetRegister(regs->delta.parent[1]);
691 }
692 if (flags & TLF_BB_Z_OFFSET) result.origin.z += object.GetRegister(regs->delta.parent[2]);
693 } else {
694 if (flags & TLF_CHILD_X_OFFSET) result.origin.x += object.GetRegister(regs->delta.child[0]);
695 if (flags & TLF_CHILD_Y_OFFSET) result.origin.y += object.GetRegister(regs->delta.child[1]);
696 }
697 }
698 }
699 }
700
701 /* Is the palette affected by an action-1-2-3 chain? */
702 if (result.image.sprite != 0 && (HasBit(result.image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_PALETTE_REG_FLAGS))) {
703 /* Does the var10 value apply to this sprite? */
704 uint8_t var10 = (flags & TLF_PALETTE_VAR10) ? regs->palette_var10 : (ground && this->separate_ground ? 1 : 0);
705 if (var10 == resolved_var10) {
706 /* Apply registers */
707 if (HasBit(result.image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) result.image.pal += resolved_sprite;
708 if (flags & TLF_PALETTE) {
709 int16_t offset = static_cast<int16_t>(object.GetRegister(regs->palette)); // mask to 16 bits to avoid trouble
710 if (!HasBit(result.image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_palette_offset)) {
711 result.image.pal += offset;
712 } else {
713 result.image.sprite = SPR_IMG_QUERY;
714 result.image.pal = PAL_NONE;
715 }
716 }
717 }
718 }
719
720 ground = false;
721 if (regs != nullptr) regs++;
722 }
723}
724
730{
731 this->grffile = grffile;
732 this->grfid = grffile == nullptr ? GrfID{} : grffile->grfid;
733}
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
int GetBridgeHeight(TileIndex t)
Get the height ('z') of a bridge.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
Common return value for all commands.
void SetEncodedMessage(EncodedString &&message)
Set the encoded message string.
void SetEntitySpec(HouseSpec &&hs)
Install the specs into the HouseSpecs array It will find itself the proper slot on which it will go.
uint16_t GetID(uint16_t grf_local_id, GrfID grfid) const override
Return the ID (if ever available) of a previously inserted entity.
uint16_t AddEntityID(uint16_t grf_local_id, GrfID grfid, uint16_t substitute_id) override
Method to find an entity ID and to mark it as reserved for the Industry to be included.
void SetEntitySpec(IndustrySpec &&inds)
Method to install the new industry data in its proper slot The slot assignment is internal of this me...
void SetEntitySpec(ObjectSpec &&spec)
Method to install the new object data in its proper slot The slot assignment is internal of this meth...
virtual uint16_t GetID(uint16_t grf_local_id, GrfID grfid) const
Return the ID (if ever available) of a previously inserted entity.
const uint16_t max_entities
what is the amount of entities, old and new summed
const uint16_t max_offset
what is the length of the original entity's array of specs
const uint16_t invalid_id
ID used to detected invalid entities.
void ResetMapping()
Resets the mapping, which is used while initializing game.
GrfID GetGRFID(uint16_t entity_id) const
Gives the GRFID of the file the entity belongs to.
OverrideManagerBase(uint16_t offset, uint16_t maximum, uint16_t invalid)
Constructor of generic class.
std::vector< EntityIDMapping > mappings
mapping of ids from grf files. Public out of convenience
void Add(uint16_t local_id, GrfID grfid, uint entity_type)
Since the entity IDs defined by the GRF file does not necessarily correlate to those used by the game...
void ResetOverride()
Resets the override, which is used while initializing game.
uint16_t GetSubstituteID(uint16_t entity_id) const
Gives the substitute of the entity, as specified by the grf file.
virtual uint16_t AddEntityID(uint16_t grf_local_id, GrfID grfid, uint16_t substitute_id)
Reserves a place in the mapping array for an entity to be installed.
void ProcessRegisters(const struct ResolverObject &object, uint8_t resolved_var10, uint32_t resolved_sprite)
Evaluates the register modifiers and integrates them into the preprocessed sprite layout.
Map accessors for 'clear' tiles.
bool IsSnowTile(Tile t)
Test if a tile is covered with snow.
Definition clear_map.h:40
uint GetClearDensity(Tile t)
Get the density of a non-field clear tile.
Definition clear_map.h:77
Definition of stuff that is very close to a company, like the company struct itself.
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Axis
Enumeration for the two axis X and Y.
@ Invalid
Flag for an invalid Axis.
@ Y
The y axis.
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
Functions related to errors.
@ Critical
Critical errors, the MessageBox is shown in all cases.
Definition error.h:27
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:74
Functions related to world/map generation.
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
Definition of HouseSpec and accessors.
uint16_t HouseID
OpenTTD ID of house types.
Definition house_type.h:15
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
Industry type specs.
Functions related to OTTD's landscape.
@ Arctic
Landscape with snow levels.
@ Tropic
Landscape with distinct rainforests and deserts,.
@ Default
Default scheme.
Definition livery.h:24
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:392
constexpr To ClampTo(From value)
Clamp the given value down to lie within the requested type.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
Converts a callback result into a boolean.
CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span< const int32_t > textstack, const GRFFile *grffile, StringID default_error)
Get the error message from a shape/location/slope check callback result.
uint32_t GetCompanyInfo(CompanyID owner, const Livery *l)
Returns company information like in vehicle var 43 or station var 43.
uint32_t GetNearbyTileInformation(TileIndex tile, bool grf_version8)
Common part of station var 0x67, house var 0x62, indtile var 0x60, industry var 0x62,...
bool ConvertBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
Converts a callback result into a boolean.
void ErrorUnknownCallbackResult(GrfID grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
uint32_t GetTerrainType(TileIndex tile, TileContext context)
Function used by houses (and soon industries) to get information on type of "terrain" the tile it is ...
TileIndex GetNearbyTile(uint8_t parameter, TileIndex tile, bool signed_offsets, Axis axis)
Get the tile at the given offset.
TileContext
Context for tile accesses.
@ UpperHalftile
Querying information about the upper part of a tile with halftile foundation.
@ OnBridge
Querying information about stuff on the bridge (via some bridgehead).
TileLayoutFlags
Flags to enable register usage in sprite layouts.
@ TLF_BB_Z_OFFSET
Add signed offset to bounding box Z positions from register TileLayoutRegisters::delta....
@ TLF_SPRITE
Add signed offset to sprite from register TileLayoutRegisters::sprite.
@ TLF_CHILD_X_OFFSET
Add signed offset to child sprite X positions from register TileLayoutRegisters::delta....
@ TLF_DODRAW
Only draw sprite if value of register TileLayoutRegisters::dodraw is non-zero.
@ TLF_PALETTE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the palette, even if it is no action-1 palet...
@ TLF_BB_XY_OFFSET
Add signed offset to bounding box X and Y positions from register TileLayoutRegisters::delta....
@ TLF_SPRITE_REG_FLAGS
Flags which require resolving the action-1-2-3 chain for the sprite, even if it is no action-1 sprite...
@ TLF_PALETTE_VAR10
Resolve palette with a specific value in variable 10.
@ TLF_SPRITE_VAR10
Resolve sprite with a specific value in variable 10.
@ TLF_PALETTE
Add signed offset to palette from register TileLayoutRegisters::palette.
@ TLF_CHILD_Y_OFFSET
Add signed offset to child sprite Y positions from register TileLayoutRegisters::delta....
uint GetConstructionStageOffset(uint construction_stage, uint num_sprites)
Determines which sprite to use from a spriteset for a specific construction stage.
GRFConfig * GetGRFConfig(GrfID grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
Functions to find and configure NewGRFs.
@ UnknownCbResult
A callback returned an unknown/invalid result.
std::vector< ObjectSpec > _object_specs
All the object specifications.
Functions related to NewGRF objects.
Action 2 handling.
std::vector< StringParameter > GetGRFStringTextStackParameters(const GRFFile *grffile, StringID stringid, std::span< const int32_t > textstack)
Process the text ref stack for a GRF String and return its parameters.
StringID GetGRFStringID(GrfID grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
static constexpr GRFStringID GRFSTR_MISC_GRF_TEXT
Miscellaneous GRF text range.
Label< struct GrfIDTag > GrfID
The unique identifier of a NewGRF.
Definition newgrf_type.h:17
uint16_t ObjectType
Types of objects.
Definition object_type.h:16
static const ObjectType OBJECT_TRANSMITTER
The large antenna.
Definition object_type.h:18
RailGroundType GetRailGroundType(Tile t)
Get the ground type for rail tiles.
Definition rail_map.h:601
RailGroundType
The ground 'under' the rail.
Definition rail_map.h:568
@ HalfTileSnow
Snow only on higher part of slope (steep or one corner raised).
Definition rail_map.h:583
@ SnowOrDesert
Icy or sandy.
Definition rail_map.h:581
bool IsOnSnowOrDesert(Tile t)
Check if a road tile has snow/desert.
Definition road_map.h:456
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
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
Definition sprites.h:1731
static const SpriteID SPR_IMG_QUERY
Definition sprites.h:1274
Maps accessors for stations.
bool HasStationTileRail(Tile t)
Has this station tile a rail?
Axis GetRailStationAxis(Tile t)
Get the rail direction of a rail station.
bool IsRoadWaypointTile(Tile t)
Is this tile a station tile and a road waypoint?
Definition of base types and functions in a cross-platform compatible way.
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
Functions related to low-level strings.
EncodedString GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
Definition strings.cpp:102
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
Functions related to OTTD's strings.
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > StringID
Numeric value that represents a string, independent of the selected language.
constexpr bool Empty() const
Check whether the label is empty.
static bool IsValidAiID(auto index)
Is this company a valid company, controlled by the computer (a NoAI program)?
A tile child sprite and palette to draw for stations etc, with 3D bounding box.
Definition sprite.h:33
Maps an entity id stored on the map to a GRF file.
uint16_t substitute_id
The (original) entity ID to use if this GRF is not available.
uint16_t entity_id
The entity ID within the GRF file.
GrfID grfid
The GRF ID of the file the entity belongs to.
Information about GRF, used in the game and (part of it) in savegames.
GRFBugs grf_bugs
NOSAVE: bugs in this GRF in this run,.
std::string GetName() const
Get the name of this grf.
GrfID grfid
grfid that introduced this entity.
const struct GRFFile * grffile
grf file that introduced this entity
void SetGRFFile(const struct GRFFile *grffile)
Set the NewGRF file, and its grfid, associated with grf props.
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
Dynamic data of a loaded NewGRF.
Definition newgrf.h:124
SubstituteGRFFileProps grf_prop
Properties related the the grf file.
Definition house.h:122
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
Defines the data structure for constructing industry.
SubstituteGRFFileProps grf_prop
properties related to the grf file
bool enabled
entity still available (by default true).newgrf can disable it, though
Defines the data structure of each individual tile of an industry.
SubstituteGRFFileProps grf_prop
properties related to the grf file
bool enabled
entity still available (by default true).newgrf can disable it, though
Information about a particular livery.
Definition livery.h:82
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:94
Colours colour1
First colour, for all vehicles.
Definition livery.h:93
static TileIndex WrapToMap(TileIndex tile)
'Wraps' the given "tile" so it is within the map.
Definition map_func.h:320
NewGRF supplied spritelayout.
void Allocate(uint num_sprites)
Allocate a spritelayout for num_sprites building sprites.
void AllocateRegisters()
Allocate memory for register modifiers.
An object that isn't use for transport, industries or houses.
static Company * Get(auto index)
Interface for SpriteGroup-s to access the gamestate.
uint16_t override_id
The id of the entity been replaced by.
Additional modifiers for items in sprite layouts.
uint8_t parent[3]
Registers for signed offsets for the bounding box position of parent sprites.
TileLayoutFlags flags
Flags defining which members are valid and to be used.
uint8_t dodraw
Register deciding whether the sprite shall be drawn at all. Non-zero means drawing.
uint8_t palette
Register specifying a signed offset for the palette.
uint8_t sprite_var10
Value for variable 10 when resolving the sprite.
uint8_t palette_var10
Value for variable 10 when resolving the palette.
uint8_t child[2]
Registers for signed offsets for the position of child sprites.
uint8_t sprite
Register specifying a signed offset for the sprite.
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:135
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:115
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
TileType
The different types of tiles.
Definition tile_type.h:48
@ TunnelBridge
Tunnel entry/exit and bridge heads.
Definition tile_type.h:58
@ Water
Water tile.
Definition tile_type.h:55
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Object
Contains objects such as transmitters and owned land.
Definition tile_type.h:59
@ Industry
Part of an industry.
Definition tile_type.h:57
@ Railway
A tile with railway.
Definition tile_type.h:50
@ Void
Invisible tiles at the SW and SE border.
Definition tile_type.h:56
@ Trees
Tile with one or more trees.
Definition tile_type.h:53
@ House
A house by a town.
Definition tile_type.h:52
@ Road
A tile with road and/or tram tracks.
Definition tile_type.h:51
@ Clear
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:49
Map accessors for tree tiles.
TreeGround GetTreeGround(Tile t)
Returns the groundtype for tree tiles.
Definition tree_map.h:102
TreeGround
Enumeration for ground types of tiles with trees.
Definition tree_map.h:52
@ SnowOrDesert
Snow or desert, depending on landscape.
Definition tree_map.h:55
@ Shore
Shore.
Definition tree_map.h:56
@ RoughSnow
A snow tile that is rough underneath.
Definition tree_map.h:57
uint GetTreeDensity(Tile t)
Returns the 'density' of a tile with trees.
Definition tree_map.h:128
Functions that have tunnels and bridges in common.
bool HasTunnelBridgeSnowOrDesert(Tile t)
Tunnel: Is this tunnel entrance in a snowy or desert area?
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:103
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114