OpenTTD
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"
12 #include "date_func.h"
13 #include "newgrf_spritegroup.h"
14 #include "newgrf_text.h"
15 #include "station_base.h"
16 #include "newgrf_class_func.h"
17 
18 #include "safeguards.h"
19 
22  struct Station *st;
23  byte airport_id;
24  byte layout;
26 
35  AirportScopeResolver(ResolverObject &ro, TileIndex tile, Station *st, byte airport_id, byte layout)
36  : ScopeResolver(ro), st(st), airport_id(airport_id), layout(layout), tile(tile)
37  {
38  }
39 
40  uint32 GetRandomBits() const override;
41  uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override;
42  void StorePSA(uint pos, int32 value) override;
43 };
44 
47  AirportScopeResolver airport_scope;
48 
50  CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
51 
52  ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override
53  {
54  switch (scope) {
55  case VSG_SCOPE_SELF: return &this->airport_scope;
56  default: return ResolverObject::GetScope(scope, relative);
57  }
58  }
59 
60  const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
61 };
62 
68 template <typename Tspec, typename Tid, Tid Tmax>
70 {
71  AirportClass::Get(AirportClass::Allocate('SMAL'))->name = STR_AIRPORT_CLASS_SMALL;
72  AirportClass::Get(AirportClass::Allocate('LARG'))->name = STR_AIRPORT_CLASS_LARGE;
73  AirportClass::Get(AirportClass::Allocate('HUB_'))->name = STR_AIRPORT_CLASS_HUB;
74  AirportClass::Get(AirportClass::Allocate('HELI'))->name = STR_AIRPORT_CLASS_HELIPORTS;
75 }
76 
77 template <typename Tspec, typename Tid, Tid Tmax>
79 {
80  return true;
81 }
82 
84 
85 
87 
89 
96 /* static */ const AirportSpec *AirportSpec::Get(byte type)
97 {
98  assert(type < lengthof(AirportSpec::specs));
99  const AirportSpec *as = &AirportSpec::specs[type];
100  if (type >= NEW_AIRPORT_OFFSET && !as->enabled) {
101  if (_airport_mngr.GetGRFID(type) == 0) return as;
102  byte subst_id = _airport_mngr.GetSubstituteID(type);
103  if (subst_id == AT_INVALID) return as;
104  as = &AirportSpec::specs[subst_id];
105  }
106  if (as->grf_prop.override != AT_INVALID) return &AirportSpec::specs[as->grf_prop.override];
107  return as;
108 }
109 
117 {
118  assert(type < lengthof(AirportSpec::specs));
119  return &AirportSpec::specs[type];
120 }
121 
124 {
125  if (!this->enabled) return false;
126  if (_cur_year < this->min_year) return false;
128  return _cur_year <= this->max_year;
129 }
130 
138 {
139  if (table >= this->num_table) return false;
140 
141  byte w = this->size_x;
142  byte h = this->size_y;
143  if (this->rotation[table] == DIR_E || this->rotation[table] == DIR_W) Swap(w, h);
144 
145  return TileX(tile) + w < MapSizeX() &&
146  TileY(tile) + h < MapSizeY();
147 }
148 
153 {
154  extern const AirportSpec _origin_airport_specs[];
155  memset(&AirportSpec::specs, 0, sizeof(AirportSpec::specs));
156  memcpy(&AirportSpec::specs, &_origin_airport_specs, sizeof(AirportSpec) * NEW_AIRPORT_OFFSET);
157 
158  _airport_mngr.ResetOverride();
159 }
160 
165 {
166  for (int i = 0; i < NUM_AIRPORTS; i++) {
168  if (as->enabled) AirportClass::Assign(as);
169  }
170 }
171 
172 
173 void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
174 {
175  byte airport_id = this->AddEntityID(as->grf_prop.local_id, as->grf_prop.grffile->grfid, as->grf_prop.subst_id);
176 
177  if (airport_id == invalid_ID) {
178  grfmsg(1, "Airport.SetEntitySpec: Too many airports allocated. Ignoring.");
179  return;
180  }
181 
182  memcpy(AirportSpec::GetWithoutOverride(airport_id), as, sizeof(*as));
183 
184  /* Now add the overrides. */
185  for (int i = 0; i < max_offset; i++) {
186  AirportSpec *overridden_as = AirportSpec::GetWithoutOverride(i);
187 
188  if (entity_overrides[i] != as->grf_prop.local_id || grfid_overrides[i] != as->grf_prop.grffile->grfid) continue;
189 
190  overridden_as->grf_prop.override = airport_id;
191  overridden_as->enabled = false;
192  entity_overrides[i] = invalid_ID;
193  grfid_overrides[i] = 0;
194  }
195 }
196 
197 /* virtual */ uint32 AirportScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
198 {
199  switch (variable) {
200  case 0x40: return this->layout;
201  }
202 
203  if (this->st == nullptr) {
204  *available = false;
205  return UINT_MAX;
206  }
207 
208  switch (variable) {
209  /* Get a variable from the persistent storage */
210  case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
211 
212  case 0xF0: return this->st->facilities;
213  case 0xFA: return Clamp(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
214  }
215 
216  return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
217 }
218 
219 /* virtual */ const SpriteGroup *AirportResolverObject::ResolveReal(const RealSpriteGroup *group) const
220 {
221  /* Airport action 2s should always have only 1 "loaded" state, but some
222  * times things don't follow the spec... */
223  if (group->num_loaded > 0) return group->loaded[0];
224  if (group->num_loading > 0) return group->loading[0];
225 
226  return nullptr;
227 }
228 
229 /* virtual */ uint32 AirportScopeResolver::GetRandomBits() const
230 {
231  return this->st == nullptr ? 0 : this->st->random_bits;
232 }
233 
239 /* virtual */ void AirportScopeResolver::StorePSA(uint pos, int32 value)
240 {
241  if (this->st == nullptr) return;
242 
243  if (this->st->airport.psa == nullptr) {
244  /* There is no need to create a storage if the value is zero. */
245  if (value == 0) return;
246 
247  /* Create storage on first modification. */
248  uint32 grfid = (this->ro.grffile != nullptr) ? this->ro.grffile->grfid : 0;
250  this->st->airport.psa = new PersistentStorage(grfid, GSF_AIRPORTS, this->st->airport.tile);
251  }
252  this->st->airport.psa->StoreValue(pos, value);
253 }
254 
266  CallbackID callback, uint32 param1, uint32 param2)
267  : ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, airport_id, layout)
268 {
269  this->root_spritegroup = AirportSpec::Get(airport_id)->grf_prop.spritegroup[0];
270 }
271 
272 SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
273 {
274  AirportResolverObject object(INVALID_TILE, nullptr, as->GetIndex(), layout);
275  const SpriteGroup *group = object.Resolve();
276  if (group == nullptr) return as->preview_sprite;
277 
278  return group->GetResult();
279 }
280 
281 uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile)
282 {
283  AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2);
284  return object.ResolveCallback();
285 }
286 
294 StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
295 {
296  AirportResolverObject object(INVALID_TILE, nullptr, as->GetIndex(), layout, (CallbackID)callback);
297  uint16 cb_res = object.ResolveCallback();
298  if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
299  if (cb_res > 0x400) {
300  ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res);
301  return STR_UNDEFINED;
302  }
303 
304  return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + cb_res);
305 }
Implementation of the NewGRF class&#39; functions.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:275
byte type
Type of this airport,.
Definition: station_base.h:309
Interface to query and set values specific to a single VarSpriteGroupScope (action 2 scope)...
TileIndex tile
Tile for the callback, only valid for airporttile callbacks.
StationFacility facilities
The facilities that this station has.
static uint MapSizeX()
Get the size of the map along the X.
Definition: map_func.h:72
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:79
void StorePSA(uint pos, int32 value) override
Store a value into the object&#39;s persistent storage.
bool IsAvailable() const
Check whether this airport is available to build.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
static uint MapSizeY()
Get the size of the map along the Y.
Definition: map_func.h:82
AirportClassID
List of default airport classes.
static AirportSpec * GetWithoutOverride(byte type)
Retrieve airport spec for the given airport.
ResolverObject & ro
Surrounding resolver object.
#define DAYS_TILL_ORIGINAL_BASE_YEAR
The offset in days from the &#39;_date == 0&#39; till &#39;ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)&#39;.
Definition: date_type.h:80
VarSpriteGroupScope
Functions related to dates.
West.
Functions related to debugging.
Interface for SpriteGroup-s to access the gamestate.
uint32 GetGRFID(uint16 entity_id) const
Gives the GRFID of the file the entity belongs to.
byte GetIndex() const
Get the index of this spec.
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:205
bool never_expire_airports
never expire airports
Set when using the callback resolve system, but not to resolve a callback.
AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout, CallbackID callback=CBID_NO_CALLBACK, uint32 callback_param1=0, uint32 callback_param2=0)
Constructor of the airport resolver.
#define INSTANTIATE_NEWGRF_CLASS_METHODS(name, Tspec, Tid, Tmax)
Force instantiation of the methods so we don&#39;t get linker errors.
AirportScopeResolver(ResolverObject &ro, TileIndex tile, Station *st, byte airport_id, byte layout)
Constructor of the scope resolver for an airport.
virtual ScopeResolver * GetScope(VarSpriteGroupScope scope=VSG_SCOPE_SELF, byte relative=0)
Get a resolver for the scope.
StringID GetGRFStringID(uint32 grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
byte num_loaded
Number of loaded groups.
uint32 GetRandomBits() const override
Get a few random bits.
bool IsUIAvailable(uint index) const
Check whether the spec will be available to the user at some point in time.
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:24
StationSettings station
settings related to station management
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
Invalid airport.
Definition: airport.h:42
Header of Action 04 "universal holder" structure and functions.
Maximal number of airports in total.
Definition: airport.h:41
Struct containing information relating to NewGRF classes for stations and airports.
Definition: newgrf_class.h:19
virtual const SpriteGroup * Resolve(ResolverObject &object) const
Base sprite group resolver.
Action 2 handling.
TYPE GetValue(uint pos) const
Gets the value from a given position.
const SpriteGroup ** loaded
List of loaded groups (can be SpriteIDs or Callback results)
Number of the first newgrf airport.
Definition: airport.h:39
void StoreValue(uint pos, int32 value)
Stores some value at a given position.
uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override
Get a variable value.
East.
maximum number of airport classes
static void ResetAirports()
This function initializes the airportspec array.
byte layout
Airport layout number.
Definition: station_base.h:310
Definition of base types and functions in a cross-platform compatible way.
A number of safeguards to prevent using unsafe methods.
Class for pooled persistent storage of data.
static const AirportSpec * Get(byte type)
Retrieve airport spec for the given airport.
PersistentStorage * psa
Persistent storage for NewGRF airports.
Definition: station_base.h:313
const SpriteGroup ** loading
List of loading groups (can be SpriteIDs or Callback results)
Resolver for the airport scope.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
static AirportSpec specs[NUM_AIRPORTS]
Specs of the airports.
Resolved object itself.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
const struct SpriteGroup * spritegroup[Tcnt]
pointer to the different sprites of the entity
struct Station * st
Station of the airport for which the callback is run, or nullptr for build gui.
byte layout
Layout of the airport to build.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
uint16 override
id of the entity been replaced by
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:17
void BindAirportSpecs()
Tie all airportspecs to their class.
byte num_loading
Number of loading groups.
const GRFFile * grffile
GRFFile the resolved SpriteGroup belongs to.
void ErrorUnknownCallbackResult(uint32 grfid, uint16 cbid, uint16 cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:17
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:215
bool IsWithinMapBounds(byte table, TileIndex index) const
Check if the airport would be within the map bounds at the given tile.
void CDECL grfmsg(int severity, const char *str,...)
DEBUG() function dedicated to newGRF debugging messages Function is essentially the same as DEBUG(grf...
Definition: newgrf.cpp:375
CallbackID callback
Callback being resolved.
static NewGRFClass * Get(Tid cls_id)
Get a particular class.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function() ...
Definition: pool_type.hpp:261
byte airport_id
Type of airport for which the callback is run.
uint16 local_id
id defined by the grf file for this entity
Resolver object for airports.
static void InsertDefaults()
Initialise the defaults.
ScopeResolver * GetScope(VarSpriteGroupScope scope=VSG_SCOPE_SELF, byte relative=0) override
Get a resolver for the scope.
uint16 random_bits
Random bits assigned to this station.
Airport airport
Tile area the airport covers.
Definition: station_base.h:464
void ResetOverride()
Resets the override, which is used while initializing game.
const struct GRFFile * grffile
grf file that introduced this entity
bool enabled
Entity still available (by default true). Newgrf can disable it, though.
CallbackID
List of implemented NewGRF callbacks.
SpriteID preview_sprite
preview sprite for this airport
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
Defines the data structure for an airport.
Base classes/functions for stations.
StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
Get a custom text for the airport.
Station data structure.
Definition: station_base.h:450
struct GRFFileProps grf_prop
Properties related to the grf file.
const SpriteGroup * ResolveReal(const RealSpriteGroup *group) const override
Get the real sprites of the grf.
Date build_date
Date of construction.
uint16 GetSubstituteID(uint16 entity_id) const
Gives the substitute of the entity, as specified by the grf file.
StringID name
Name of this class.
Definition: newgrf_class.h:39