OpenTTD
newgrf_airport.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "stdafx.h"
13 #include "debug.h"
14 #include "date_func.h"
15 #include "newgrf_spritegroup.h"
16 #include "newgrf_text.h"
17 #include "station_base.h"
18 #include "newgrf_class_func.h"
19 
20 #include "safeguards.h"
21 
24  struct Station *st;
25  byte airport_id;
26  byte layout;
28 
37  AirportScopeResolver(ResolverObject &ro, TileIndex tile, Station *st, byte airport_id, byte layout)
38  : ScopeResolver(ro), st(st), airport_id(airport_id), layout(layout), tile(tile)
39  {
40  }
41 
42  uint32 GetRandomBits() const override;
43  uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override;
44  void StorePSA(uint pos, int32 value) override;
45 };
46 
49  AirportScopeResolver airport_scope;
50 
52  CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
53 
54  ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override
55  {
56  switch (scope) {
57  case VSG_SCOPE_SELF: return &this->airport_scope;
58  default: return ResolverObject::GetScope(scope, relative);
59  }
60  }
61 
62  const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
63 };
64 
70 template <typename Tspec, typename Tid, Tid Tmax>
72 {
73  AirportClass::Get(AirportClass::Allocate('SMAL'))->name = STR_AIRPORT_CLASS_SMALL;
74  AirportClass::Get(AirportClass::Allocate('LARG'))->name = STR_AIRPORT_CLASS_LARGE;
75  AirportClass::Get(AirportClass::Allocate('HUB_'))->name = STR_AIRPORT_CLASS_HUB;
76  AirportClass::Get(AirportClass::Allocate('HELI'))->name = STR_AIRPORT_CLASS_HELIPORTS;
77 }
78 
79 template <typename Tspec, typename Tid, Tid Tmax>
81 {
82  return true;
83 }
84 
86 
87 
89 
91 
98 /* static */ const AirportSpec *AirportSpec::Get(byte type)
99 {
100  assert(type < lengthof(AirportSpec::specs));
101  const AirportSpec *as = &AirportSpec::specs[type];
102  if (type >= NEW_AIRPORT_OFFSET && !as->enabled) {
103  if (_airport_mngr.GetGRFID(type) == 0) return as;
104  byte subst_id = _airport_mngr.GetSubstituteID(type);
105  if (subst_id == AT_INVALID) return as;
106  as = &AirportSpec::specs[subst_id];
107  }
108  if (as->grf_prop.override != AT_INVALID) return &AirportSpec::specs[as->grf_prop.override];
109  return as;
110 }
111 
119 {
120  assert(type < lengthof(AirportSpec::specs));
121  return &AirportSpec::specs[type];
122 }
123 
126 {
127  if (!this->enabled) return false;
128  if (_cur_year < this->min_year) return false;
130  return _cur_year <= this->max_year;
131 }
132 
140 {
141  if (table >= this->num_table) return false;
142 
143  byte w = this->size_x;
144  byte h = this->size_y;
145  if (this->rotation[table] == DIR_E || this->rotation[table] == DIR_W) Swap(w, h);
146 
147  return TileX(tile) + w < MapSizeX() &&
148  TileY(tile) + h < MapSizeY();
149 }
150 
155 {
156  extern const AirportSpec _origin_airport_specs[];
157  memset(&AirportSpec::specs, 0, sizeof(AirportSpec::specs));
158  memcpy(&AirportSpec::specs, &_origin_airport_specs, sizeof(AirportSpec) * NEW_AIRPORT_OFFSET);
159 
160  _airport_mngr.ResetOverride();
161 }
162 
167 {
168  for (int i = 0; i < NUM_AIRPORTS; i++) {
170  if (as->enabled) AirportClass::Assign(as);
171  }
172 }
173 
174 
175 void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
176 {
177  byte airport_id = this->AddEntityID(as->grf_prop.local_id, as->grf_prop.grffile->grfid, as->grf_prop.subst_id);
178 
179  if (airport_id == invalid_ID) {
180  grfmsg(1, "Airport.SetEntitySpec: Too many airports allocated. Ignoring.");
181  return;
182  }
183 
184  memcpy(AirportSpec::GetWithoutOverride(airport_id), as, sizeof(*as));
185 
186  /* Now add the overrides. */
187  for (int i = 0; i < max_offset; i++) {
188  AirportSpec *overridden_as = AirportSpec::GetWithoutOverride(i);
189 
190  if (entity_overrides[i] != as->grf_prop.local_id || grfid_overrides[i] != as->grf_prop.grffile->grfid) continue;
191 
192  overridden_as->grf_prop.override = airport_id;
193  overridden_as->enabled = false;
194  entity_overrides[i] = invalid_ID;
195  grfid_overrides[i] = 0;
196  }
197 }
198 
199 /* virtual */ uint32 AirportScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
200 {
201  switch (variable) {
202  case 0x40: return this->layout;
203  }
204 
205  if (this->st == nullptr) {
206  *available = false;
207  return UINT_MAX;
208  }
209 
210  switch (variable) {
211  /* Get a variable from the persistent storage */
212  case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
213 
214  case 0xF0: return this->st->facilities;
215  case 0xFA: return Clamp(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
216  }
217 
218  return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
219 }
220 
221 /* virtual */ const SpriteGroup *AirportResolverObject::ResolveReal(const RealSpriteGroup *group) const
222 {
223  /* Airport action 2s should always have only 1 "loaded" state, but some
224  * times things don't follow the spec... */
225  if (group->num_loaded > 0) return group->loaded[0];
226  if (group->num_loading > 0) return group->loading[0];
227 
228  return nullptr;
229 }
230 
231 /* virtual */ uint32 AirportScopeResolver::GetRandomBits() const
232 {
233  return this->st == nullptr ? 0 : this->st->random_bits;
234 }
235 
241 /* virtual */ void AirportScopeResolver::StorePSA(uint pos, int32 value)
242 {
243  if (this->st == nullptr) return;
244 
245  if (this->st->airport.psa == nullptr) {
246  /* There is no need to create a storage if the value is zero. */
247  if (value == 0) return;
248 
249  /* Create storage on first modification. */
250  uint32 grfid = (this->ro.grffile != nullptr) ? this->ro.grffile->grfid : 0;
252  this->st->airport.psa = new PersistentStorage(grfid, GSF_AIRPORTS, this->st->airport.tile);
253  }
254  this->st->airport.psa->StoreValue(pos, value);
255 }
256 
268  CallbackID callback, uint32 param1, uint32 param2)
269  : ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(*this, tile, st, airport_id, layout)
270 {
271  this->root_spritegroup = AirportSpec::Get(airport_id)->grf_prop.spritegroup[0];
272 }
273 
274 SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
275 {
276  AirportResolverObject object(INVALID_TILE, nullptr, as->GetIndex(), layout);
277  const SpriteGroup *group = object.Resolve();
278  if (group == nullptr) return as->preview_sprite;
279 
280  return group->GetResult();
281 }
282 
283 uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile)
284 {
285  AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2);
286  return object.ResolveCallback();
287 }
288 
296 StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
297 {
298  AirportResolverObject object(INVALID_TILE, nullptr, as->GetIndex(), layout, (CallbackID)callback);
299  uint16 cb_res = object.ResolveCallback();
300  if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
301  if (cb_res > 0x400) {
302  ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res);
303  return STR_UNDEFINED;
304  }
305 
306  return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + cb_res);
307 }
Implementation of the NewGRF class&#39; functions.
static void Swap(T &a, T &b)
Type safe swap operation.
Definition: math_func.hpp:277
byte type
Type of this airport,.
Definition: station_base.h:311
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:74
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:81
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:84
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:82
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:207
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:26
StationSettings station
settings related to station management
const SpriteGroup * root_spritegroup
Root SpriteGroup to use for resolving.
Invalid airport.
Definition: airport.h:44
Header of Action 04 "universal holder" structure and functions.
Maximal number of airports in total.
Definition: airport.h:43
Struct containing information relating to NewGRF classes for stations and airports.
Definition: newgrf_class.h:21
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:41
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:312
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:315
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:42
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:18
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:139
uint16 override
id of the entity been replaced by
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
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:19
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:217
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:377
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:216
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:466
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:85
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:452
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:41