00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "date_func.h"
00015 #include "newgrf_spritegroup.h"
00016 #include "newgrf_text.h"
00017 #include "station_base.h"
00018 #include "newgrf_class_func.h"
00019
00021 struct AirportScopeResolver : public ScopeResolver {
00022 struct Station *st;
00023 byte airport_id;
00024 byte layout;
00025 TileIndex tile;
00026
00027 AirportScopeResolver(ResolverObject *ro, TileIndex tile, Station *st, byte airport_id, byte layout);
00028
00029 uint32 GetRandomBits() const;
00030 uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
00031 void StorePSA(uint pos, int32 value);
00032 };
00033
00035 struct AirportResolverObject : public ResolverObject {
00036 AirportScopeResolver airport_scope;
00037
00038 AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout,
00039 CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
00040
00041 ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
00042 {
00043 switch (scope) {
00044 case VSG_SCOPE_SELF: return &this->airport_scope;
00045 default: return ResolverObject::GetScope(scope, relative);
00046 }
00047 }
00048
00049 const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
00050 };
00051
00057 template <typename Tspec, typename Tid, Tid Tmax>
00058 void NewGRFClass<Tspec, Tid, Tmax>::InsertDefaults()
00059 {
00060 AirportClass::Get(AirportClass::Allocate('SMAL'))->name = STR_AIRPORT_CLASS_SMALL;
00061 AirportClass::Get(AirportClass::Allocate('LARG'))->name = STR_AIRPORT_CLASS_LARGE;
00062 AirportClass::Get(AirportClass::Allocate('HUB_'))->name = STR_AIRPORT_CLASS_HUB;
00063 AirportClass::Get(AirportClass::Allocate('HELI'))->name = STR_AIRPORT_CLASS_HELIPORTS;
00064 }
00065
00066 template <typename Tspec, typename Tid, Tid Tmax>
00067 bool NewGRFClass<Tspec, Tid, Tmax>::IsUIAvailable(uint index) const
00068 {
00069 return true;
00070 }
00071
00072 INSTANTIATE_NEWGRF_CLASS_METHODS(AirportClass, AirportSpec, AirportClassID, APC_MAX)
00073
00074
00075 AirportOverrideManager _airport_mngr(NEW_AIRPORT_OFFSET, NUM_AIRPORTS, AT_INVALID);
00076
00077 AirportSpec AirportSpec::specs[NUM_AIRPORTS];
00078
00085 const AirportSpec *AirportSpec::Get(byte type)
00086 {
00087 assert(type < lengthof(AirportSpec::specs));
00088 const AirportSpec *as = &AirportSpec::specs[type];
00089 if (type >= NEW_AIRPORT_OFFSET && !as->enabled) {
00090 byte subst_id = _airport_mngr.GetSubstituteID(type);
00091 if (subst_id == AT_INVALID) return as;
00092 as = &AirportSpec::specs[subst_id];
00093 }
00094 if (as->grf_prop.override != AT_INVALID) return &AirportSpec::specs[as->grf_prop.override];
00095 return as;
00096 }
00097
00104 AirportSpec *AirportSpec::GetWithoutOverride(byte type)
00105 {
00106 assert(type < lengthof(AirportSpec::specs));
00107 return &AirportSpec::specs[type];
00108 }
00109
00111 bool AirportSpec::IsAvailable() const
00112 {
00113 if (!this->enabled) return false;
00114 if (_cur_year < this->min_year) return false;
00115 if (_settings_game.station.never_expire_airports) return true;
00116 return _cur_year <= this->max_year;
00117 }
00118
00122 void AirportSpec::ResetAirports()
00123 {
00124 extern const AirportSpec _origin_airport_specs[];
00125 memset(&AirportSpec::specs, 0, sizeof(AirportSpec::specs));
00126 memcpy(&AirportSpec::specs, &_origin_airport_specs, sizeof(AirportSpec) * NEW_AIRPORT_OFFSET);
00127
00128 _airport_mngr.ResetOverride();
00129 }
00130
00134 void BindAirportSpecs()
00135 {
00136 for (int i = 0; i < NUM_AIRPORTS; i++) {
00137 AirportSpec *as = AirportSpec::GetWithoutOverride(i);
00138 if (as->enabled) AirportClass::Assign(as);
00139 }
00140 }
00141
00142
00143 void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
00144 {
00145 byte airport_id = this->AddEntityID(as->grf_prop.local_id, as->grf_prop.grffile->grfid, as->grf_prop.subst_id);
00146
00147 if (airport_id == invalid_ID) {
00148 grfmsg(1, "Airport.SetEntitySpec: Too many airports allocated. Ignoring.");
00149 return;
00150 }
00151
00152 memcpy(AirportSpec::GetWithoutOverride(airport_id), as, sizeof(*as));
00153
00154
00155 for (int i = 0; i < max_offset; i++) {
00156 AirportSpec *overridden_as = AirportSpec::GetWithoutOverride(i);
00157
00158 if (entity_overrides[i] != as->grf_prop.local_id || grfid_overrides[i] != as->grf_prop.grffile->grfid) continue;
00159
00160 overridden_as->grf_prop.override = airport_id;
00161 overridden_as->enabled = false;
00162 entity_overrides[i] = invalid_ID;
00163 grfid_overrides[i] = 0;
00164 }
00165 }
00166
00167 uint32 AirportScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
00168 {
00169 switch (variable) {
00170 case 0x40: return this->layout;
00171 }
00172
00173 if (this->st == NULL) {
00174 *available = false;
00175 return UINT_MAX;
00176 }
00177
00178 switch (variable) {
00179
00180 case 0x7C: return (this->st->airport.psa != NULL) ? this->st->airport.psa->GetValue(parameter) : 0;
00181
00182 case 0xF0: return this->st->facilities;
00183 case 0xFA: return Clamp(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 65535);
00184 }
00185
00186 return this->st->GetNewGRFVariable(this->ro, variable, parameter, available);
00187 }
00188
00189 const SpriteGroup *AirportResolverObject::ResolveReal(const RealSpriteGroup *group) const
00190 {
00191
00192
00193 if (group->num_loaded > 0) return group->loaded[0];
00194 if (group->num_loading > 0) return group->loading[0];
00195
00196 return NULL;
00197 }
00198
00199 uint32 AirportScopeResolver::GetRandomBits() const
00200 {
00201 return this->st == NULL ? 0 : this->st->random_bits;
00202 }
00203
00210 void AirportScopeResolver::StorePSA(uint pos, int32 value)
00211 {
00212 if (this->st == NULL) return;
00213
00214 if (this->st->airport.psa == NULL) {
00215
00216 if (value == 0) return;
00217
00218
00219 uint32 grfid = (this->ro->grffile != NULL) ? this->ro->grffile->grfid : 0;
00220 assert(PersistentStorage::CanAllocateItem());
00221 this->st->airport.psa = new PersistentStorage(grfid);
00222 }
00223 this->st->airport.psa->StoreValue(pos, value);
00224 }
00225
00236 AirportResolverObject::AirportResolverObject(TileIndex tile, Station *st, byte airport_id, byte layout,
00237 CallbackID callback, uint32 param1, uint32 param2)
00238 : ResolverObject(AirportSpec::Get(airport_id)->grf_prop.grffile, callback, param1, param2), airport_scope(this, tile, st, airport_id, layout)
00239 {
00240 }
00241
00250 AirportScopeResolver::AirportScopeResolver(ResolverObject *ro, TileIndex tile, Station *st, byte airport_id, byte layout) : ScopeResolver(ro)
00251 {
00252 this->st = st;
00253 this->airport_id = airport_id;
00254 this->layout = layout;
00255 this->tile = tile;
00256 }
00257
00258 SpriteID GetCustomAirportSprite(const AirportSpec *as, byte layout)
00259 {
00260 AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout);
00261 const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], &object);
00262 if (group == NULL) return as->preview_sprite;
00263
00264 return group->GetResult();
00265 }
00266
00267 uint16 GetAirportCallback(CallbackID callback, uint32 param1, uint32 param2, Station *st, TileIndex tile)
00268 {
00269 AirportResolverObject object(tile, st, st->airport.type, st->airport.layout, callback, param1, param2);
00270 const SpriteGroup *group = SpriteGroup::Resolve(st->airport.GetSpec()->grf_prop.spritegroup[0], &object);
00271 if (group == NULL) return CALLBACK_FAILED;
00272
00273 return group->GetCallbackResult();
00274 }
00275
00283 StringID GetAirportTextCallback(const AirportSpec *as, byte layout, uint16 callback)
00284 {
00285 AirportResolverObject object(INVALID_TILE, NULL, as->GetIndex(), layout, (CallbackID)callback);
00286 const SpriteGroup *group = SpriteGroup::Resolve(as->grf_prop.spritegroup[0], &object);
00287 uint16 cb_res = (group != NULL) ? group->GetCallbackResult() : CALLBACK_FAILED;
00288 if (cb_res == CALLBACK_FAILED || cb_res == 0x400) return STR_UNDEFINED;
00289 if (cb_res > 0x400) {
00290 ErrorUnknownCallbackResult(as->grf_prop.grffile->grfid, callback, cb_res);
00291 return STR_UNDEFINED;
00292 }
00293
00294 return GetGRFStringID(as->grf_prop.grffile->grfid, 0xD000 + cb_res);
00295 }