OpenTTD Source 20250529-master-g10c159a79f
newgrf_airport.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"
13#include "newgrf_badge.h"
14#include "newgrf_spritegroup.h"
15#include "newgrf_text.h"
16#include "station_base.h"
17#include "town.h"
18
19#include "table/strings.h"
20
21#include "newgrf_class_func.h"
22
23#include "safeguards.h"
24
30template <>
32{
33 AirportClass::Get(AirportClass::Allocate('SMAL'))->name = STR_AIRPORT_CLASS_SMALL;
34 AirportClass::Get(AirportClass::Allocate('LARG'))->name = STR_AIRPORT_CLASS_LARGE;
35 AirportClass::Get(AirportClass::Allocate('HUB_'))->name = STR_AIRPORT_CLASS_HUB;
36 AirportClass::Get(AirportClass::Allocate('HELI'))->name = STR_AIRPORT_CLASS_HELIPORTS;
37}
38
39template <>
41{
42 return true;
43}
44
45/* Instantiate AirportClass. */
47
48
50
52
59/* static */ const AirportSpec *AirportSpec::Get(uint8_t type)
60{
61 assert(type < lengthof(AirportSpec::specs));
62 const AirportSpec *as = &AirportSpec::specs[type];
63 if (type >= NEW_AIRPORT_OFFSET && !as->enabled) {
64 if (_airport_mngr.GetGRFID(type) == 0) return as;
65 uint8_t subst_id = _airport_mngr.GetSubstituteID(type);
66 if (subst_id == AT_INVALID) return as;
67 as = &AirportSpec::specs[subst_id];
68 }
70 return as;
71}
72
80{
81 assert(type < lengthof(AirportSpec::specs));
82 return &AirportSpec::specs[type];
83}
84
87{
88 if (!this->enabled) return false;
89 if (TimerGameCalendar::year < this->min_year) return false;
91 return TimerGameCalendar::year <= this->max_year;
92}
93
100bool AirportSpec::IsWithinMapBounds(uint8_t table, TileIndex tile) const
101{
102 if (table >= this->layouts.size()) return false;
103
104 uint8_t w = this->size_x;
105 uint8_t h = this->size_y;
106 if (this->layouts[table].rotation == DIR_E || this->layouts[table].rotation == DIR_W) std::swap(w, h);
107
108 return TileX(tile) + w < Map::SizeX() &&
109 TileY(tile) + h < Map::SizeY();
110}
111
116{
117 extern const AirportSpec _origin_airport_specs[NEW_AIRPORT_OFFSET];
118
119 auto insert = std::copy(std::begin(_origin_airport_specs), std::end(_origin_airport_specs), std::begin(AirportSpec::specs));
120 std::fill(insert, std::end(AirportSpec::specs), AirportSpec{});
121
122 _airport_mngr.ResetOverride();
123}
124
129{
130 for (int i = 0; i < NUM_AIRPORTS; i++) {
132 if (as->enabled) AirportClass::Assign(as);
133 }
134}
135
136
137void AirportOverrideManager::SetEntitySpec(AirportSpec &&as)
138{
139 uint8_t airport_id = this->AddEntityID(as.grf_prop.local_id, as.grf_prop.grfid, as.grf_prop.subst_id);
140
141 if (airport_id == this->invalid_id) {
142 GrfMsg(1, "Airport.SetEntitySpec: Too many airports allocated. Ignoring.");
143 return;
144 }
145
146 AirportSpec::specs[airport_id] = std::move(as);
147
148 /* Now add the overrides. */
149 for (int i = 0; i < this->max_offset; i++) {
151
152 if (this->entity_overrides[i] != AirportSpec::specs[airport_id].grf_prop.local_id || this->grfid_overrides[i] != AirportSpec::specs[airport_id].grf_prop.grfid) continue;
153
154 overridden_as->grf_prop.override_id = airport_id;
155 overridden_as->enabled = false;
156 this->entity_overrides[i] = this->invalid_id;
157 this->grfid_overrides[i] = 0;
158 }
159}
160
161/* virtual */ uint32_t AirportScopeResolver::GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const
162{
163 switch (variable) {
164 case 0x40: return this->layout;
165
166 case 0x7A: return GetBadgeVariableResult(*this->ro.grffile, this->spec->badges, parameter);
167 }
168
169 if (this->st == nullptr) {
170 available = false;
171 return UINT_MAX;
172 }
173
174 switch (variable) {
175 /* Get a variable from the persistent storage */
176 case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
177
178 case 0xF0: return this->st->facilities.base();
179 case 0xFA: return ClampTo<uint16_t>(this->st->build_date - CalendarTime::DAYS_TILL_ORIGINAL_BASE_YEAR);
180 }
181
182 return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
183}
184
186{
187 return GSF_AIRPORTS;
188}
189
191{
192 return this->airport_scope.spec->grf_prop.local_id;
193}
194
195/* virtual */ uint32_t AirportScopeResolver::GetRandomBits() const
196{
197 return this->st == nullptr ? 0 : this->st->random_bits;
198}
199
205/* virtual */ void AirportScopeResolver::StorePSA(uint pos, int32_t value)
206{
207 if (this->st == nullptr) return;
208
209 if (this->st->airport.psa == nullptr) {
210 /* There is no need to create a storage if the value is zero. */
211 if (value == 0) return;
212
213 /* Create storage on first modification. */
214 uint32_t grfid = (this->ro.grffile != nullptr) ? this->ro.grffile->grfid : 0;
216 this->st->airport.psa = new PersistentStorage(grfid, GSF_AIRPORTS, this->st->airport.tile);
217 }
218 this->st->airport.psa->StoreValue(pos, value);
219}
220
227{
228 if (!this->town_scope.has_value()) {
229 Town *t = nullptr;
230 if (this->airport_scope.st != nullptr) {
231 t = this->airport_scope.st->town;
232 } else if (this->airport_scope.tile != INVALID_TILE) {
233 t = ClosestTownFromTile(this->airport_scope.tile, UINT_MAX);
234 }
235 if (t == nullptr) return nullptr;
236 this->town_scope.emplace(*this, t, this->airport_scope.st == nullptr);
237 }
238 return &*this->town_scope;
239}
240
252 CallbackID callback, uint32_t param1, uint32_t param2)
253 : ResolverObject(spec->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, spec, layout)
254{
255 this->root_spritegroup = spec->grf_prop.GetSpriteGroup(st != nullptr);
256}
257
258SpriteID GetCustomAirportSprite(const AirportSpec *as, uint8_t layout)
259{
260 AirportResolverObject object(INVALID_TILE, nullptr, as, layout);
261 const auto *group = object.Resolve<ResultSpriteGroup>();
262 if (group == nullptr || group->num_sprites == 0) return as->preview_sprite;
263
264 return group->sprite;
265}
266
267uint16_t GetAirportCallback(CallbackID callback, uint32_t param1, uint32_t param2, Station *st, TileIndex tile, std::span<int32_t> regs100)
268{
269 AirportResolverObject object(tile, st, AirportSpec::Get(st->airport.type), st->airport.layout, callback, param1, param2);
270 return object.ResolveCallback(regs100);
271}
272
280StringID GetAirportTextCallback(const AirportSpec *as, uint8_t layout, uint16_t callback)
281{
282 AirportResolverObject object(INVALID_TILE, nullptr, as, layout, (CallbackID)callback);
283 std::array<int32_t, 1> regs100;
284 uint16_t cb_res = object.ResolveCallback(regs100);
285 if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
286 if (cb_res == 0x40F) {
287 return GetGRFStringID(as->grf_prop.grfid, static_cast<GRFStringID>(regs100[0]));
288 }
289 if (cb_res > 0x400) {
290 ErrorUnknownCallbackResult(as->grf_prop.grfid, callback, cb_res);
291 return STR_UNDEFINED;
292 }
293
295}
@ AT_INVALID
Invalid airport.
Definition airport.h:42
@ NUM_AIRPORTS
Maximal number of airports in total.
Definition airport.h:41
@ NEW_AIRPORT_OFFSET
Number of the first newgrf airport.
Definition airport.h:39
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
Struct containing information relating to NewGRF classes for stations and airports.
static void Assign(Tspec *spec)
Assign a spec to one of the classes.
StringID name
Name of this class.
bool IsUIAvailable(uint index) const
Check whether the spec will be available to the user at some point in time.
static NewGRFClass * Get(Tindex class_index)
Get a particular class.
static Tindex Allocate(uint32_t global_id)
Allocate a class with a given global class ID.
static void InsertDefaults()
Initialise the defaults.
uint32_t GetGRFID(uint16_t entity_id) const
Gives the GRFID of the file the entity belongs to.
uint16_t invalid_id
ID used to detected invalid entities.
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.
static Year year
Current year, starting at 0.
static constexpr TimerGame< struct Calendar >::Date DAYS_TILL_ORIGINAL_BASE_YEAR
The date of the first day of the original base year.
Functions related to debugging.
@ DIR_W
West.
@ DIR_E
East.
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:424
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:414
GrfSpecFeature
Definition newgrf.h:69
void BindAirportSpecs()
Tie all airportspecs to their class.
StringID GetAirportTextCallback(const AirportSpec *as, uint8_t layout, uint16_t callback)
Get a custom text for the airport.
uint32_t GetBadgeVariableResult(const GRFFile &grffile, std::span< const BadgeID > badges, uint32_t parameter)
Test for a matching badge in a list of badges, returning the number of matching bits.
Functions related to NewGRF badges.
CallbackID
List of implemented NewGRF callbacks.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
Implementation of the NewGRF class' functions.
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Action 2 handling.
StringID GetGRFStringID(uint32_t grfid, GRFStringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
static constexpr GRFStringID GRFSTR_MISC_GRF_TEXT
Miscellaneous GRF text range.
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
Base classes/functions for stations.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Resolver object for airports.
GrfSpecFeature GetFeature() const override
Get the feature number being resolved for.
AirportResolverObject(TileIndex tile, Station *st, const AirportSpec *spec, uint8_t layout, CallbackID callback=CBID_NO_CALLBACK, uint32_t callback_param1=0, uint32_t callback_param2=0)
Constructor of the airport resolver.
TownScopeResolver * GetTown()
Get the town scope associated with a station, if it exists.
uint32_t GetDebugID() const override
Get an identifier for the item being resolved.
std::optional< TownScopeResolver > town_scope
The town scope resolver (created on the first call).
uint32_t GetRandomBits() const override
Get a few random bits.
const AirportSpec * spec
AirportSpec for which the callback is run.
uint8_t layout
Layout of the airport to build.
void StorePSA(uint pos, int32_t value) override
Store a value into the object's persistent storage.
TileIndex tile
Tile for the callback, only valid for airporttile callbacks.
uint32_t GetVariable(uint8_t variable, uint32_t parameter, bool &available) const override
Get a variable value.
struct Station * st
Station of the airport for which the callback is run, or nullptr for build gui.
Defines the data structure for an airport.
SubstituteGRFFileProps grf_prop
Properties related to the grf file.
SpriteID preview_sprite
preview sprite for this airport
TimerGameCalendar::Year min_year
first year the airport is available
static void ResetAirports()
This function initializes the airportspec array.
std::vector< AirportTileLayout > layouts
List of layouts composing the airport.
static AirportSpec specs[NUM_AIRPORTS]
Specs of the airports.
bool IsWithinMapBounds(uint8_t table, TileIndex index) const
Check if the airport would be within the map bounds at the given tile.
static AirportSpec * GetWithoutOverride(uint8_t type)
Retrieve airport spec for the given airport.
TimerGameCalendar::Year max_year
last year the airport is available
bool enabled
Entity still available (by default true). Newgrf can disable it, though.
uint8_t size_y
size of airport in y direction
uint8_t size_x
size of airport in x direction
static const AirportSpec * Get(uint8_t type)
Retrieve airport spec for the given airport.
bool IsAvailable() const
Check whether this airport is available to build.
uint8_t type
Type of this airport,.
PersistentStorage * psa
Persistent storage for NewGRF airports.
uint8_t layout
Airport layout number.
StationFacilities facilities
The facilities that this station has.
Town * town
The town this station is associated with.
uint16_t random_bits
Random bits assigned to this station.
TimerGameCalendar::Date build_date
Date of construction.
uint16_t local_id
id defined by the grf file for this entity
uint32_t grfid
grfid that introduced this entity.
StationSettings station
settings related to station management
static uint SizeY()
Get the size of the map along the Y.
Definition map_func.h:278
static debug_inline uint SizeX()
Get the size of the map along the X.
Definition map_func.h:269
TileIndex tile
The base tile of the area.
TYPE GetValue(uint pos) const
Gets the value from a given position.
void StoreValue(uint pos, int32_t value)
Stores some value at a given position.
Class for pooled persistent storage of data.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Interface for SpriteGroup-s to access the gamestate.
const GRFFile * grffile
GRFFile the resolved SpriteGroup belongs to.
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
ResolverObject & ro
Surrounding resolver object.
const struct SpriteGroup * GetSpriteGroup(bool entity_exists) const
Get the standard sprite group.
bool never_expire_airports
never expire airports
Station data structure.
Airport airport
Tile area the airport covers.
uint16_t override_id
id of the entity been replaced by
Scope resolver for a town.
Definition newgrf_town.h:22
Town data structure.
Definition town.h:52
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
Definition of the game-calendar-timer.
Base of the town class.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.