OpenTTD Source 20241224-master-gf74b0cf984
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 <http://www.gnu.org/licenses/>.
6 */
7
13#include "stdafx.h"
14#include "debug.h"
15#include "landscape.h"
16#include "house.h"
17#include "industrytype.h"
18#include "newgrf_config.h"
19#include "clear_map.h"
20#include "station_map.h"
21#include "tree_map.h"
22#include "tunnelbridge_map.h"
23#include "newgrf_object.h"
24#include "genworld.h"
25#include "newgrf_spritegroup.h"
26#include "newgrf_text.h"
27#include "company_base.h"
28#include "error.h"
29#include "strings_func.h"
30#include "string_func.h"
31
32#include "table/strings.h"
33
34#include "safeguards.h"
35
42OverrideManagerBase::OverrideManagerBase(uint16_t offset, uint16_t maximum, uint16_t invalid)
43{
44 this->max_offset = offset;
45 this->max_entities = maximum;
46 this->invalid_id = invalid;
47
48 this->mappings.resize(this->max_entities);
49 this->entity_overrides.resize(this->max_offset);
50 std::fill(this->entity_overrides.begin(), this->entity_overrides.end(), this->invalid_id);
51 this->grfid_overrides.resize(this->max_offset);
52}
53
62void OverrideManagerBase::Add(uint16_t local_id, uint32_t grfid, uint entity_type)
63{
64 assert(entity_type < this->max_offset);
65 /* An override can be set only once */
66 if (this->entity_overrides[entity_type] != this->invalid_id) return;
67 this->entity_overrides[entity_type] = local_id;
68 this->grfid_overrides[entity_type] = grfid;
69}
70
73{
74 std::fill(this->mappings.begin(), this->mappings.end(), EntityIDMapping{});
75}
76
79{
80 std::fill(this->entity_overrides.begin(), this->entity_overrides.end(), this->invalid_id);
81 std::fill(this->grfid_overrides.begin(), this->grfid_overrides.end(), uint32_t());
82}
83
90uint16_t OverrideManagerBase::GetID(uint16_t grf_local_id, uint32_t grfid) const
91{
92 for (uint16_t id = 0; id < this->max_entities; id++) {
93 const EntityIDMapping *map = &this->mappings[id];
94 if (map->entity_id == grf_local_id && map->grfid == grfid) {
95 return id;
96 }
97 }
98
99 return this->invalid_id;
100}
101
109uint16_t OverrideManagerBase::AddEntityID(uint16_t grf_local_id, uint32_t grfid, uint16_t substitute_id)
110{
111 uint16_t id = this->GetID(grf_local_id, grfid);
112
113 /* Look to see if this entity has already been added. This is done
114 * separately from the loop below in case a GRF has been deleted, and there
115 * are any gaps in the array.
116 */
117 if (id != this->invalid_id) return id;
118
119 /* This entity hasn't been defined before, so give it an ID now. */
120 for (id = this->max_offset; id < this->max_entities; id++) {
121 EntityIDMapping *map = &this->mappings[id];
122
123 if (CheckValidNewID(id) && map->entity_id == 0 && map->grfid == 0) {
124 map->entity_id = grf_local_id;
125 map->grfid = grfid;
126 map->substitute_id = substitute_id;
127 return id;
128 }
129 }
130
131 return this->invalid_id;
132}
133
139uint32_t OverrideManagerBase::GetGRFID(uint16_t entity_id) const
140{
141 return this->mappings[entity_id].grfid;
142}
143
149uint16_t OverrideManagerBase::GetSubstituteID(uint16_t entity_id) const
150{
151 return this->mappings[entity_id].substitute_id;
152}
153
160{
161 HouseID house_id = this->AddEntityID(hs->grf_prop.local_id, hs->grf_prop.grfid, hs->grf_prop.subst_id);
162
163 if (house_id == this->invalid_id) {
164 GrfMsg(1, "House.SetEntitySpec: Too many houses allocated. Ignoring.");
165 return;
166 }
167
168 auto &house_specs = HouseSpec::Specs();
169
170 /* Now that we know we can use the given id, copy the spec to its final destination. */
171 if (house_id >= house_specs.size()) house_specs.resize(house_id + 1);
172 house_specs[house_id] = *hs;
173
174 /* Now add the overrides. */
175 for (int i = 0; i < this->max_offset; i++) {
176 HouseSpec *overridden_hs = HouseSpec::Get(i);
177
178 if (this->entity_overrides[i] != hs->grf_prop.local_id || this->grfid_overrides[i] != hs->grf_prop.grfid) continue;
179
180 overridden_hs->grf_prop.override = house_id;
181 this->entity_overrides[i] = this->invalid_id;
182 this->grfid_overrides[i] = 0;
183 }
184}
185
192uint16_t IndustryOverrideManager::GetID(uint16_t grf_local_id, uint32_t grfid) const
193{
194 uint16_t id = OverrideManagerBase::GetID(grf_local_id, grfid);
195 if (id != this->invalid_id) return id;
196
197 /* No mapping found, try the overrides */
198 for (id = 0; id < this->max_offset; id++) {
199 if (this->entity_overrides[id] == grf_local_id && this->grfid_overrides[id] == grfid) return id;
200 }
201
202 return this->invalid_id;
203}
204
212uint16_t IndustryOverrideManager::AddEntityID(uint16_t grf_local_id, uint32_t grfid, uint16_t substitute_id)
213{
214 /* This entity hasn't been defined before, so give it an ID now. */
215 for (uint16_t id = 0; id < this->max_entities; id++) {
216 /* Skip overridden industries */
217 if (id < this->max_offset && this->entity_overrides[id] != this->invalid_id) continue;
218
219 /* Get the real live industry */
220 const IndustrySpec *inds = GetIndustrySpec(id);
221
222 /* This industry must be one that is not available(enabled), mostly because of climate.
223 * And it must not already be used by a grf (grffile == nullptr).
224 * So reserve this slot here, as it is the chosen one */
225 if (!inds->enabled && !inds->grf_prop.HasGrfFile()) {
226 EntityIDMapping *map = &this->mappings[id];
227
228 if (map->entity_id == 0 && map->grfid == 0) {
229 /* winning slot, mark it as been used */
230 map->entity_id = grf_local_id;
231 map->grfid = grfid;
232 map->substitute_id = substitute_id;
233 return id;
234 }
235 }
236 }
237
238 return this->invalid_id;
239}
240
248{
249 /* First step : We need to find if this industry is already specified in the savegame data. */
250 IndustryType ind_id = this->GetID(inds->grf_prop.local_id, inds->grf_prop.grfid);
251
252 if (ind_id == this->invalid_id) {
253 /* Not found.
254 * Or it has already been overridden, so you've lost your place.
255 * Or it is a simple substitute.
256 * We need to find a free available slot */
257 ind_id = this->AddEntityID(inds->grf_prop.local_id, inds->grf_prop.grfid, inds->grf_prop.subst_id);
258 inds->grf_prop.override = this->invalid_id; // make sure it will not be detected as overridden
259 }
260
261 if (ind_id == this->invalid_id) {
262 GrfMsg(1, "Industry.SetEntitySpec: Too many industries allocated. Ignoring.");
263 return;
264 }
265
266 /* Now that we know we can use the given id, copy the spec to its final destination... */
267 _industry_specs[ind_id] = *inds;
268 /* ... and mark it as usable*/
269 _industry_specs[ind_id].enabled = true;
270}
271
272void IndustryTileOverrideManager::SetEntitySpec(const IndustryTileSpec *its)
273{
274 IndustryGfx indt_id = this->AddEntityID(its->grf_prop.local_id, its->grf_prop.grfid, its->grf_prop.subst_id);
275
276 if (indt_id == this->invalid_id) {
277 GrfMsg(1, "IndustryTile.SetEntitySpec: Too many industry tiles allocated. Ignoring.");
278 return;
279 }
280
281 _industry_tile_specs[indt_id] = *its;
282
283 /* Now add the overrides. */
284 for (int i = 0; i < this->max_offset; i++) {
285 IndustryTileSpec *overridden_its = &_industry_tile_specs[i];
286
287 if (this->entity_overrides[i] != its->grf_prop.local_id || this->grfid_overrides[i] != its->grf_prop.grfid) continue;
288
289 overridden_its->grf_prop.override = indt_id;
290 overridden_its->enabled = false;
291 this->entity_overrides[i] = this->invalid_id;
292 this->grfid_overrides[i] = 0;
293 }
294}
295
303{
304 /* First step : We need to find if this object is already specified in the savegame data. */
305 ObjectType type = this->GetID(spec->grf_prop.local_id, spec->grf_prop.grfid);
306
307 if (type == this->invalid_id) {
308 /* Not found.
309 * Or it has already been overridden, so you've lost your place.
310 * Or it is a simple substitute.
311 * We need to find a free available slot */
312 type = this->AddEntityID(spec->grf_prop.local_id, spec->grf_prop.grfid, OBJECT_TRANSMITTER);
313 }
314
315 if (type == this->invalid_id) {
316 GrfMsg(1, "Object.SetEntitySpec: Too many objects allocated. Ignoring.");
317 return;
318 }
319
320 extern std::vector<ObjectSpec> _object_specs;
321
322 /* Now that we know we can use the given id, copy the spec to its final destination. */
323 if (type >= _object_specs.size()) _object_specs.resize(type + 1);
324 _object_specs[type] = *spec;
325}
326
335uint32_t GetTerrainType(TileIndex tile, TileContext context)
336{
338 case LT_TROPIC: return GetTropicZone(tile);
339 case LT_ARCTIC: {
340 bool has_snow;
341 switch (GetTileType(tile)) {
342 case MP_CLEAR:
343 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
344 if (_generating_world) goto genworld;
345 has_snow = IsSnowTile(tile) && GetClearDensity(tile) >= 2;
346 break;
347
348 case MP_RAILWAY: {
349 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
350 if (_generating_world) goto genworld; // we do not care about foundations here
351 RailGroundType ground = GetRailGroundType(tile);
352 has_snow = (ground == RAIL_GROUND_ICE_DESERT || (context == TCX_UPPER_HALFTILE && ground == RAIL_GROUND_HALF_SNOW));
353 break;
354 }
355
356 case MP_ROAD:
357 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
358 if (_generating_world) goto genworld; // we do not care about foundations here
359 has_snow = IsOnSnow(tile);
360 break;
361
362 case MP_TREES: {
363 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
364 if (_generating_world) goto genworld;
365 TreeGround ground = GetTreeGround(tile);
366 has_snow = (ground == TREE_GROUND_SNOW_DESERT || ground == TREE_GROUND_ROUGH_SNOW) && GetTreeDensity(tile) >= 2;
367 break;
368 }
369
370 case MP_TUNNELBRIDGE:
371 if (context == TCX_ON_BRIDGE) {
372 has_snow = (GetBridgeHeight(tile) > GetSnowLine());
373 } else {
374 /* During map generation the snowstate may not be valid yet, as the tileloop may not have run yet. */
375 if (_generating_world) goto genworld; // we do not care about foundations here
376 has_snow = HasTunnelBridgeSnowOrDesert(tile);
377 }
378 break;
379
380 case MP_STATION:
381 case MP_HOUSE:
382 case MP_INDUSTRY:
383 case MP_OBJECT:
384 /* These tiles usually have a levelling foundation. So use max Z */
385 has_snow = (GetTileMaxZ(tile) > GetSnowLine());
386 break;
387
388 case MP_VOID:
389 case MP_WATER:
390 genworld:
391 has_snow = (GetTileZ(tile) > GetSnowLine());
392 break;
393
394 default: NOT_REACHED();
395 }
396 return has_snow ? 4 : 0;
397 }
398 default: return 0;
399 }
400}
401
410TileIndex GetNearbyTile(uint8_t parameter, TileIndex tile, bool signed_offsets, Axis axis)
411{
412 int8_t x = GB(parameter, 0, 4);
413 int8_t y = GB(parameter, 4, 4);
414
415 if (signed_offsets && x >= 8) x -= 16;
416 if (signed_offsets && y >= 8) y -= 16;
417
418 /* Swap width and height depending on axis for railway stations */
419 if (axis == INVALID_AXIS && HasStationTileRail(tile)) axis = GetRailStationAxis(tile);
420 if (axis == AXIS_Y) Swap(x, y);
421
422 /* Make sure we never roam outside of the map, better wrap in that case */
423 return Map::WrapToMap(tile + TileDiffXY(x, y));
424}
425
433uint32_t GetNearbyTileInformation(TileIndex tile, bool grf_version8)
434{
435 TileType tile_type = GetTileType(tile);
436
437 /* Fake tile type for trees on shore */
438 if (IsTileType(tile, MP_TREES) && GetTreeGround(tile) == TREE_GROUND_SHORE) tile_type = MP_WATER;
439
440 /* Fake tile type for road waypoints */
441 if (IsRoadWaypointTile(tile)) tile_type = MP_ROAD;
442
443 auto [tileh, z] = GetTilePixelSlope(tile);
444 /* Return 0 if the tile is a land tile */
445 uint8_t terrain_type = (HasTileWaterClass(tile) ? (GetWaterClass(tile) + 1) & 3 : 0) << 5 | GetTerrainType(tile) << 2 | (tile_type == MP_WATER ? 1 : 0) << 1;
446 if (grf_version8) z /= TILE_HEIGHT;
447 return tile_type << 24 | ClampTo<uint8_t>(z) << 16 | terrain_type << 8 | tileh;
448}
449
456uint32_t GetCompanyInfo(CompanyID owner, const Livery *l)
457{
458 if (l == nullptr && Company::IsValidID(owner)) l = &Company::Get(owner)->livery[LS_DEFAULT];
459 return owner | (Company::IsValidAiID(owner) ? 0x10000 : 0) | (l != nullptr ? (l->colour1 << 24) | (l->colour2 << 28) : 0);
460}
461
469CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, const GRFFile *grffile, StringID default_error)
470{
471 CommandCost res;
472
473 if (cb_res < 0x400) {
474 res = CommandCost(GetGRFStringID(grffile->grfid, 0xD000 + cb_res));
475 } else {
476 switch (cb_res) {
477 case 0x400: return res; // No error.
478
479 default: // unknown reason -> default error
480 case 0x401: res = CommandCost(default_error); break;
481
482 case 0x402: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_RAINFOREST); break;
483 case 0x403: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_IN_DESERT); break;
484 case 0x404: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE); break;
485 case 0x405: res = CommandCost(STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE); break;
486 case 0x406: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_SEA); break;
487 case 0x407: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_CANAL); break;
488 case 0x408: res = CommandCost(STR_ERROR_CAN_T_BUILD_ON_RIVER); break;
489 }
490 }
491
492 /* Copy some parameters from the registers to the error message text ref. stack */
493 res.UseTextRefStack(grffile, 4);
494
495 return res;
496}
497
505void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
506{
507 GRFConfig *grfconfig = GetGRFConfig(grfid);
508
509 if (!HasBit(grfconfig->grf_bugs, GBUG_UNKNOWN_CB_RESULT)) {
511 SetDParamStr(0, grfconfig->GetName());
512 SetDParam(1, cbid);
513 SetDParam(2, cb_res);
514 ShowErrorMessage(STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT, WL_CRITICAL);
515 }
516
517 /* debug output */
518 SetDParamStr(0, grfconfig->GetName());
519 Debug(grf, 0, "{}", StrMakeValid(GetString(STR_NEWGRF_BUGGY)));
520
521 SetDParam(1, cbid);
522 SetDParam(2, cb_res);
523 Debug(grf, 0, "{}", StrMakeValid(GetString(STR_NEWGRF_BUGGY_UNKNOWN_CALLBACK_RESULT)));
524}
525
535bool ConvertBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
536{
537 assert(cb_res != CALLBACK_FAILED); // We do not know what to return
538
539 if (grffile->grf_version < 8) return cb_res != 0;
540
541 if (cb_res > 1) ErrorUnknownCallbackResult(grffile->grfid, cbid, cb_res);
542 return cb_res != 0;
543}
544
554bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
555{
556 assert(cb_res != CALLBACK_FAILED); // We do not know what to return
557
558 if (grffile->grf_version < 8) return GB(cb_res, 0, 8) != 0;
559
560 if (cb_res > 1) ErrorUnknownCallbackResult(grffile->grfid, cbid, cb_res);
561 return cb_res != 0;
562}
563
564
565/* static */ std::vector<DrawTileSeqStruct> NewGRFSpriteLayout::result_seq;
566
572{
573 assert(this->seq == nullptr);
574 assert(source != nullptr);
575
576 size_t count = 1; // 1 for the terminator
577 const DrawTileSeqStruct *element;
578 foreach_draw_tile_seq(element, source) count++;
579
580 DrawTileSeqStruct *sprites = MallocT<DrawTileSeqStruct>(count);
581 MemCpyT(sprites, source, count);
582 this->seq = sprites;
583}
584
590{
591 this->Clone((const DrawTileSprites*)source);
592
593 if (source->registers != nullptr) {
594 size_t count = 1; // 1 for the ground sprite
595 const DrawTileSeqStruct *element;
596 foreach_draw_tile_seq(element, source->seq) count++;
597
598 TileLayoutRegisters *regs = MallocT<TileLayoutRegisters>(count);
599 MemCpyT(regs, source->registers, count);
600 this->registers = regs;
601 }
602}
603
604
609void NewGRFSpriteLayout::Allocate(uint num_sprites)
610{
611 assert(this->seq == nullptr);
612
613 DrawTileSeqStruct *sprites = CallocT<DrawTileSeqStruct>(num_sprites + 1);
614 sprites[num_sprites].MakeTerminator();
615 this->seq = sprites;
616}
617
622{
623 assert(this->seq != nullptr);
624 assert(this->registers == nullptr);
625
626 size_t count = 1; // 1 for the ground sprite
627 const DrawTileSeqStruct *element;
628 foreach_draw_tile_seq(element, this->seq) count++;
629
630 this->registers = CallocT<TileLayoutRegisters>(count);
631}
632
645uint32_t NewGRFSpriteLayout::PrepareLayout(uint32_t orig_offset, uint32_t newgrf_ground_offset, uint32_t newgrf_offset, uint constr_stage, bool separate_ground) const
646{
647 result_seq.clear();
648 uint32_t var10_values = 0;
649
650 /* Create a copy of the spritelayout, so we can modify some values.
651 * Also include the groundsprite into the sequence for easier processing. */
652 DrawTileSeqStruct *result = &result_seq.emplace_back();
653 result->image = ground;
654 result->delta_x = 0;
655 result->delta_y = 0;
656 result->delta_z = (int8_t)0x80;
657
658 const DrawTileSeqStruct *dtss;
659 foreach_draw_tile_seq(dtss, this->seq) {
660 result_seq.push_back(*dtss);
661 }
662 result_seq.emplace_back().MakeTerminator();
663 /* Determine the var10 values the action-1-2-3 chains needs to be resolved for,
664 * and apply the default sprite offsets (unless disabled). */
665 const TileLayoutRegisters *regs = this->registers;
666 bool ground = true;
667 foreach_draw_tile_seq(result, result_seq.data()) {
668 TileLayoutFlags flags = TLF_NOTHING;
669 if (regs != nullptr) flags = regs->flags;
670
671 /* Record var10 value for the sprite */
672 if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_SPRITE_REG_FLAGS)) {
673 uint8_t var10 = (flags & TLF_SPRITE_VAR10) ? regs->sprite_var10 : (ground && separate_ground ? 1 : 0);
674 SetBit(var10_values, var10);
675 }
676
677 /* Add default sprite offset, unless there is a custom one */
678 if (!(flags & TLF_SPRITE)) {
679 if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
680 result->image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
681 if (constr_stage > 0 && regs != nullptr) result->image.sprite += GetConstructionStageOffset(constr_stage, regs->max_sprite_offset);
682 } else {
683 result->image.sprite += orig_offset;
684 }
685 }
686
687 /* Record var10 value for the palette */
688 if (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_PALETTE_REG_FLAGS)) {
689 uint8_t var10 = (flags & TLF_PALETTE_VAR10) ? regs->palette_var10 : (ground && separate_ground ? 1 : 0);
690 SetBit(var10_values, var10);
691 }
692
693 /* Add default palette offset, unless there is a custom one */
694 if (!(flags & TLF_PALETTE)) {
695 if (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) {
696 result->image.sprite += ground ? newgrf_ground_offset : newgrf_offset;
697 if (constr_stage > 0 && regs != nullptr) result->image.sprite += GetConstructionStageOffset(constr_stage, regs->max_palette_offset);
698 }
699 }
700
701 ground = false;
702 if (regs != nullptr) regs++;
703 }
704
705 return var10_values;
706}
707
716void NewGRFSpriteLayout::ProcessRegisters(uint8_t resolved_var10, uint32_t resolved_sprite, bool separate_ground) const
717{
718 DrawTileSeqStruct *result;
719 const TileLayoutRegisters *regs = this->registers;
720 bool ground = true;
721 foreach_draw_tile_seq(result, result_seq.data()) {
722 TileLayoutFlags flags = TLF_NOTHING;
723 if (regs != nullptr) flags = regs->flags;
724
725 /* Is the sprite or bounding box affected by an action-1-2-3 chain? */
726 if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_SPRITE_REG_FLAGS)) {
727 /* Does the var10 value apply to this sprite? */
728 uint8_t var10 = (flags & TLF_SPRITE_VAR10) ? regs->sprite_var10 : (ground && separate_ground ? 1 : 0);
729 if (var10 == resolved_var10) {
730 /* Apply registers */
731 if ((flags & TLF_DODRAW) && GetRegister(regs->dodraw) == 0) {
732 result->image.sprite = 0;
733 } else {
734 if (HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE)) result->image.sprite += resolved_sprite;
735 if (flags & TLF_SPRITE) {
736 int16_t offset = (int16_t)GetRegister(regs->sprite); // mask to 16 bits to avoid trouble
737 if (!HasBit(result->image.sprite, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_sprite_offset)) {
738 result->image.sprite += offset;
739 } else {
740 result->image.sprite = SPR_IMG_QUERY;
741 }
742 }
743
744 if (result->IsParentSprite()) {
745 if (flags & TLF_BB_XY_OFFSET) {
746 result->delta_x += (int32_t)GetRegister(regs->delta.parent[0]);
747 result->delta_y += (int32_t)GetRegister(regs->delta.parent[1]);
748 }
749 if (flags & TLF_BB_Z_OFFSET) result->delta_z += (int32_t)GetRegister(regs->delta.parent[2]);
750 } else {
751 if (flags & TLF_CHILD_X_OFFSET) result->delta_x += (int32_t)GetRegister(regs->delta.child[0]);
752 if (flags & TLF_CHILD_Y_OFFSET) result->delta_y += (int32_t)GetRegister(regs->delta.child[1]);
753 }
754 }
755 }
756 }
757
758 /* Is the palette affected by an action-1-2-3 chain? */
759 if (result->image.sprite != 0 && (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (flags & TLF_PALETTE_REG_FLAGS))) {
760 /* Does the var10 value apply to this sprite? */
761 uint8_t var10 = (flags & TLF_PALETTE_VAR10) ? regs->palette_var10 : (ground && separate_ground ? 1 : 0);
762 if (var10 == resolved_var10) {
763 /* Apply registers */
764 if (HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) result->image.pal += resolved_sprite;
765 if (flags & TLF_PALETTE) {
766 int16_t offset = (int16_t)GetRegister(regs->palette); // mask to 16 bits to avoid trouble
767 if (!HasBit(result->image.pal, SPRITE_MODIFIER_CUSTOM_SPRITE) || (offset >= 0 && offset < regs->max_palette_offset)) {
768 result->image.pal += offset;
769 } else {
770 result->image.sprite = SPR_IMG_QUERY;
771 result->image.pal = PAL_NONE;
772 }
773 }
774 }
775 }
776
777 ground = false;
778 if (regs != nullptr) regs++;
779 }
780}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
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.
int GetBridgeHeight(TileIndex t)
Get the height ('z') of a bridge.
Common return value for all commands.
void UseTextRefStack(const GRFFile *grffile, uint num_registers)
Activate usage of the NewGRF TextRefStack for the error message.
Definition command.cpp:422
void SetEntitySpec(const HouseSpec *hs)
Install the specs into the HouseSpecs array It will find itself the proper slot on which it will go.
uint16_t AddEntityID(uint16_t grf_local_id, uint32_t 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...
uint16_t GetID(uint16_t grf_local_id, uint32_t grfid) const override
Return the ID (if ever available) of a previously inserted entity.
void SetEntitySpec(ObjectSpec *spec)
Method to install the new object data in its proper slot The slot assignment is internal of this meth...
uint32_t GetGRFID(uint16_t entity_id) const
Gives the GRFID of the file the entity belongs to.
void ResetMapping()
Resets the mapping, which is used while initializing game.
uint16_t max_entities
what is the amount of entities, old and new summed
virtual uint16_t GetID(uint16_t grf_local_id, uint32_t grfid) const
Return the ID (if ever available) of a previously inserted entity.
uint16_t invalid_id
ID used to detected invalid entities.
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...
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 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.
uint16_t max_offset
what is the length of the original entity's array of specs
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.
Map accessors for 'clear' tiles.
bool IsSnowTile(Tile t)
Test if a tile is covered with snow.
Definition clear_map.h:35
uint GetClearDensity(Tile t)
Get the density of a non-field clear tile.
Definition clear_map.h:83
Definition of stuff that is very close to a company, like the company struct itself.
Owner
Enum for all companies/owners.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition debug.h:37
Axis
Allow incrementing of DiagDirDiff variables.
@ INVALID_AXIS
Flag for an invalid Axis.
@ AXIS_Y
The y axis.
Functions related to errors.
void ShowErrorMessage(StringID summary_msg, int x, int y, CommandCost cc)
Display an error message in a window.
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition error.h:27
bool _generating_world
Whether we are generating the map or not.
Definition genworld.cpp:67
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:13
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
Industry type specs.
Functions related to OTTD's landscape.
TileIndexDiff TileDiffXY(int x, int y)
Calculates an offset for the given coordinate(-offset).
Definition map_func.h:389
constexpr void Swap(T &a, T &b)
Type safe swap operation.
void MemCpyT(T *destination, const T *source, size_t num=1)
Type-safe version of memcpy().
Definition mem_func.hpp:23
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, const GRFFile *grffile, StringID default_error)
Get the error message from a shape/location/slope check callback result.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
bool Convert8bitBooleanCallback(const GRFFile *grffile, uint16_t cbid, uint16_t cb_res)
Converts a callback result into a boolean.
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.
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.
@ TCX_UPPER_HALFTILE
Querying information about the upper part of a tile with halftile foundation.
@ TCX_ON_BRIDGE
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(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
Functions to find and configure NewGRFs.
@ GBUG_UNKNOWN_CB_RESULT
A callback returned an unknown/invalid result.
std::vector< ObjectSpec > _object_specs
All the object specifications.
Functions related to NewGRF objects.
Action 2 handling.
uint32_t GetRegister(uint i)
Gets the value of a so-called newgrf "register".
StringID GetGRFStringID(uint32_t grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
uint16_t ObjectType
Types of objects.
Definition object_type.h:14
static const ObjectType OBJECT_TRANSMITTER
The large antenna.
Definition object_type.h:16
RailGroundType
The ground 'under' the rail.
Definition rail_map.h:485
@ RAIL_GROUND_ICE_DESERT
Icy or sandy.
Definition rail_map.h:498
@ RAIL_GROUND_HALF_SNOW
Snow only on higher part of slope (steep or one corner raised)
Definition rail_map.h:500
bool IsOnSnow(Tile t)
Check if a road tile has snow/desert.
Definition road_map.h:459
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:57
#define foreach_draw_tile_seq(idx, list)
Iterate through all DrawTileSeqStructs in DrawTileSprites.
Definition sprite.h:79
static constexpr uint8_t SPRITE_MODIFIER_CUSTOM_SPRITE
these masks change the colours of the palette for a sprite.
Definition sprites.h:1545
Maps accessors for stations.
bool HasStationTileRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
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(T &dst, const char *str, const char *last, StringValidationSettings settings)
Copies the valid (UTF-8) characters from str up to last to the dst.
Definition string.cpp:107
Functions related to low-level strings.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition strings.cpp:104
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Definition strings.cpp:333
void SetDParamStr(size_t n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition strings.cpp:371
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static bool IsValidAiID(size_t 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:25
int8_t delta_z
0x80 identifies child sprites
Definition sprite.h:28
bool IsParentSprite() const
Check whether this is a parent sprite with a boundingbox.
Definition sprite.h:47
void MakeTerminator()
Make this struct a sequence terminator.
Definition sprite.h:35
int8_t delta_x
0x80 is sequence terminator
Definition sprite.h:26
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:58
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition sprite.h:60
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:59
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.
uint32_t grfid
The GRF ID of the file the entity belongs to.
uint16_t entity_id
The entity ID within the GRF file.
Information about GRF, used in the game and (part of it) in savegames.
uint32_t grf_bugs
NOSAVE: bugs in this GRF in this run,.
const char * GetName() const
Get the name of this grf.
bool HasGrfFile() const
Test if this entity was introduced by NewGRF.
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
uint16_t override
id of the entity been replaced by
Dynamic data of a loaded NewGRF.
Definition newgrf.h:108
uint8_t landscape
the landscape we're currently in
GameCreationSettings game_creation
settings used during the creation of a game (map)
static HouseSpec * Get(size_t house_id)
Get the spec for a house ID.
GRFFileProps grf_prop
Properties related the the grf file.
Definition house.h:109
static std::vector< HouseSpec > & Specs()
Get a reference to all HouseSpecs.
Defines the data structure for constructing industry.
GRFFileProps 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.
GRFFileProps 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:78
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:81
Colours colour1
First colour, for all vehicles.
Definition livery.h:80
static TileIndex WrapToMap(TileIndex tile)
'Wraps' the given "tile" so it is within the map.
Definition map_func.h:317
NewGRF supplied spritelayout.
void Allocate(uint num_sprites)
Allocate a spritelayout for num_sprites building sprites.
uint32_t PrepareLayout(uint32_t orig_offset, uint32_t newgrf_ground_offset, uint32_t newgrf_offset, uint constr_stage, bool separate_ground) const
Prepares a sprite layout before resolving action-1-2-3 chains.
void ProcessRegisters(uint8_t resolved_var10, uint32_t resolved_sprite, bool separate_ground) const
Evaluates the register modifiers and integrates them into the preprocessed sprite layout.
void Clone(const DrawTileSeqStruct *source)
Clone the building sprites of a spritelayout.
void AllocateRegisters()
Allocate memory for register modifiers.
static std::vector< DrawTileSeqStruct > result_seq
Temporary storage when preprocessing spritelayouts.
Allow incrementing of ObjectClassID variables.
GRFFilePropsBase< 2 > grf_prop
Properties related the the grf file.
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:25
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * Get(size_t index)
Returns Titem with given index.
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.
uint16_t max_sprite_offset
Maximum offset to add to the sprite. (limited by size of the spriteset)
uint8_t palette
Register specifying a signed offset for the palette.
uint8_t sprite_var10
Value for variable 10 when resolving the sprite.
uint16_t max_palette_offset
Maximum offset to add to the palette. (limited by size of the spriteset)
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:136
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
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 debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
static const 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:47
@ MP_TREES
Tile got trees.
Definition tile_type.h:52
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
@ MP_HOUSE
A house by a town.
Definition tile_type.h:51
@ MP_WATER
Water tile.
Definition tile_type.h:54
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
@ MP_INDUSTRY
Part of an industry.
Definition tile_type.h:56
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition tile_type.h:58
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
@ TREE_GROUND_SHORE
shore
Definition tree_map.h:56
@ TREE_GROUND_ROUGH_SNOW
A snow tile that is rough underneath.
Definition tree_map.h:57
@ TREE_GROUND_SNOW_DESERT
a desert or snow tile, depend on landscape
Definition tree_map.h:55
uint GetTreeDensity(Tile t)
Returns the 'density' of a tile with trees.
Definition tree_map.h:127
Functions that have tunnels and bridges in common.
bool HasTunnelBridgeSnowOrDesert(Tile t)
Tunnel: Is this tunnel entrance in a snowy or desert area? Bridge: Does the bridge ramp lie in a snow...
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:101
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:112