OpenTTD Source  1.10.0-RC1
newgrf_generic.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 "newgrf_spritegroup.h"
13 #include "industrytype.h"
14 #include "core/random_func.hpp"
15 #include "newgrf_sound.h"
16 #include "water_map.h"
17 #include <list>
18 
19 #include "safeguards.h"
20 
23  CargoID cargo_type;
24  uint8 default_selection;
25  uint8 src_industry;
26  uint8 dst_industry;
27  uint8 distance;
28  AIConstructionEvent event;
29  uint8 count;
30  uint8 station_size;
31 
32  uint8 feature;
33 
40  : ScopeResolver(ro), cargo_type(0), default_selection(0), src_industry(0), dst_industry(0), distance(0),
41  event(), count(0), station_size(0), feature(GSF_INVALID), ai_callback(ai_callback)
42  {
43  }
44 
45  uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override;
46 
47 private:
48  bool ai_callback;
49 };
50 
51 
54  GenericScopeResolver generic_scope;
55 
57 
58  ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0) override
59  {
60  switch (scope) {
61  case VSG_SCOPE_SELF: return &this->generic_scope;
62  default: return ResolverObject::GetScope(scope, relative);
63  }
64  }
65 
66  const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const override;
67 
68  GrfSpecFeature GetFeature() const override
69  {
70  return (GrfSpecFeature)this->generic_scope.feature;
71  }
72 
73  uint32 GetDebugID() const override
74  {
75  return 0;
76  }
77 };
78 
80  const GRFFile *file;
81  const SpriteGroup *group;
82 
83  GenericCallback(const GRFFile *file, const SpriteGroup *group) :
84  file(file),
85  group(group)
86  { }
87 };
88 
89 typedef std::list<GenericCallback> GenericCallbackList;
90 
91 static GenericCallbackList _gcl[GSF_END];
92 
93 
98 {
99  for (uint8 feature = 0; feature < lengthof(_gcl); feature++) {
100  _gcl[feature].clear();
101  }
102 }
103 
104 
111 void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *group)
112 {
113  if (feature >= lengthof(_gcl)) {
114  grfmsg(5, "AddGenericCallback: Unsupported feature 0x%02X", feature);
115  return;
116  }
117 
118  /* Generic feature callbacks are evaluated in reverse (i.e. the last group
119  * to be added is evaluated first, etc) thus we push the group to the
120  * beginning of the list so a standard iterator will do the right thing. */
121  _gcl[feature].push_front(GenericCallback(file, group));
122 }
123 
124 /* virtual */ uint32 GenericScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
125 {
126  if (this->ai_callback) {
127  switch (variable) {
128  case 0x40: return this->ro.grffile->cargo_map[this->cargo_type];
129 
130  case 0x80: return this->cargo_type;
131  case 0x81: return CargoSpec::Get(this->cargo_type)->bitnum;
132  case 0x82: return this->default_selection;
133  case 0x83: return this->src_industry;
134  case 0x84: return this->dst_industry;
135  case 0x85: return this->distance;
136  case 0x86: return this->event;
137  case 0x87: return this->count;
138  case 0x88: return this->station_size;
139 
140  default: break;
141  }
142  }
143 
144  DEBUG(grf, 1, "Unhandled generic feature variable 0x%02X", variable);
145 
146  *available = false;
147  return UINT_MAX;
148 }
149 
150 
151 /* virtual */ const SpriteGroup *GenericResolverObject::ResolveReal(const RealSpriteGroup *group) const
152 {
153  if (group->num_loaded == 0) return nullptr;
154 
155  return group->loaded[0];
156 }
157 
163 GenericResolverObject::GenericResolverObject(bool ai_callback, CallbackID callback) : ResolverObject(nullptr, callback), generic_scope(*this, ai_callback)
164 {
165 }
166 
167 
178 static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject &object, uint32 param1_grfv7, uint32 param1_grfv8, const GRFFile **file)
179 {
180  assert(feature < lengthof(_gcl));
181 
182  /* Test each feature callback sprite group. */
183  for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
184  object.grffile = it->file;
185  object.root_spritegroup = it->group;
186  /* Set callback param based on GRF version. */
187  object.callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7;
188  uint16 result = object.ResolveCallback();
189  if (result == CALLBACK_FAILED) continue;
190 
191  /* Return NewGRF file if necessary */
192  if (file != nullptr) *file = it->file;
193 
194  return result;
195  }
196 
197  /* No callback returned a valid result, so we've failed. */
198  return CALLBACK_FAILED;
199 }
200 
201 
217 uint16 GetAiPurchaseCallbackResult(uint8 feature, CargoID cargo_type, uint8 default_selection, IndustryType src_industry, IndustryType dst_industry, uint8 distance, AIConstructionEvent event, uint8 count, uint8 station_size, const GRFFile **file)
218 {
220 
221  if (src_industry != IT_AI_UNKNOWN && src_industry != IT_AI_TOWN) {
222  const IndustrySpec *is = GetIndustrySpec(src_industry);
223  /* If this is no original industry, use the substitute type */
224  if (is->grf_prop.subst_id != INVALID_INDUSTRYTYPE) src_industry = is->grf_prop.subst_id;
225  }
226 
227  if (dst_industry != IT_AI_UNKNOWN && dst_industry != IT_AI_TOWN) {
228  const IndustrySpec *is = GetIndustrySpec(dst_industry);
229  /* If this is no original industry, use the substitute type */
230  if (is->grf_prop.subst_id != INVALID_INDUSTRYTYPE) dst_industry = is->grf_prop.subst_id;
231  }
232 
233  object.generic_scope.cargo_type = cargo_type;
234  object.generic_scope.default_selection = default_selection;
235  object.generic_scope.src_industry = src_industry;
236  object.generic_scope.dst_industry = dst_industry;
237  object.generic_scope.distance = distance;
238  object.generic_scope.event = event;
239  object.generic_scope.count = count;
240  object.generic_scope.station_size = station_size;
241  object.generic_scope.feature = feature;
242 
243  uint16 callback = GetGenericCallbackResult(feature, object, 0, 0, file);
244  if (callback != CALLBACK_FAILED) callback = GB(callback, 0, 8);
245  return callback;
246 }
247 
248 
254 {
255  assert(IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES) || IsTileType(tile, MP_WATER));
256 
257  /* Only run every 1/200-th time. */
258  uint32 r; // Save for later
259  if (!Chance16R(1, 200, r) || !_settings_client.sound.ambient) return;
260 
261  /* Prepare resolver object. */
263  object.generic_scope.feature = GSF_SOUNDFX;
264 
265  uint32 param1_v7 = GetTileType(tile) << 28 | Clamp(TileHeight(tile), 0, 15) << 24 | GB(r, 16, 8) << 16 | GetTerrainType(tile);
266  uint32 param1_v8 = GetTileType(tile) << 24 | GetTileZ(tile) << 16 | GB(r, 16, 8) << 8 | (HasTileWaterClass(tile) ? GetWaterClass(tile) : 0) << 3 | GetTerrainType(tile);
267 
268  /* Run callback. */
269  const GRFFile *grf_file;
270  uint16 callback = GetGenericCallbackResult(GSF_SOUNDFX, object, param1_v7, param1_v8, &grf_file);
271 
272  if (callback != CALLBACK_FAILED) PlayTileSound(grf_file, callback, tile);
273 }
static TileType GetTileType(TileIndex tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
Interface to query and set values specific to a single VarSpriteGroupScope (action 2 scope)...
Scope resolver for generic objects and properties.
Resolver object for generic objects/properties.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
uint8 dst_industry
Destination industry substitute type. 0xFF for "town", 0xFE for "unknown".
ResolverObject & ro
Surrounding resolver object.
VarSpriteGroupScope
static WaterClass GetWaterClass(TileIndex t)
Get the water class at a tile.
Definition: water_map.h:106
Functions related to debugging.
Interface for SpriteGroup-s to access the gamestate.
uint32 GetTerrainType(TileIndex tile, TileContext context)
Function used by houses (and soon industries) to get information on type of "terrain" the tile it is ...
uint32 GetDebugID() const override
Get an identifier for the item being resolved.
GenericResolverObject(bool ai_callback, CallbackID callback=CBID_NO_CALLBACK)
Generic resolver.
Set when using the callback resolve system, but not to resolve a callback.
bool ambient
Play ambient, industry and town sounds.
Industry type specs.
virtual ScopeResolver * GetScope(VarSpriteGroupScope scope=VSG_SCOPE_SELF, byte relative=0)
Get a resolver for the scope.
AI construction/purchase selection.
byte num_loaded
Number of loaded groups.
An invalid spec feature.
Definition: newgrf.h:92
void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *group)
Add a generic feature callback sprite group to the appropriate feature list.
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition: tile_map.cpp:121
Pseudo random number generator.
AIConstructionEvent
AI events for asking the NewGRF for information.
GrfSpecFeature
Definition: newgrf.h:66
Action 2 handling.
static const IndustryType IT_AI_UNKNOWN
The AI has no specific industry in mind.
static bool IsTileType(TileIndex tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
const SpriteGroup ** loaded
List of loaded groups (can be SpriteIDs or Callback results)
static const IndustryType IT_AI_TOWN
The AI actually wants to transport to/from a town, not an industry.
SoundSettings sound
sound effect settings
bool ai_callback
Callback comes from the AI.
void PlayTileSound(const GRFFile *file, SoundID sound_id, TileIndex tile)
Play a NewGRF sound effect at the location of a specific tile.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
Map accessors for water tiles.
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
Definition of base types and functions in a cross-platform compatible way.
uint16 GetAiPurchaseCallbackResult(uint8 feature, CargoID cargo_type, uint8 default_selection, IndustryType src_industry, IndustryType dst_industry, uint8 distance, AIConstructionEvent event, uint8 count, uint8 station_size, const GRFFile **file)
&#39;Execute&#39; an AI purchase selection callback
A number of safeguards to prevent using unsafe methods.
Water tile.
Definition: tile_type.h:47
Defines the data structure for constructing industry.
Definition: industrytype.h:106
const SpriteGroup * ResolveReal(const RealSpriteGroup *group) const override
Get the real sprites of the grf.
uint8 cargo_map[NUM_CARGO]
Inverse cargo translation table (CargoID -> local ID)
Definition: newgrf.h:127
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
GRFFileProps grf_prop
properties related to the grf file
Definition: industrytype.h:140
Resolved object itself.
static bool Chance16R(const uint a, const uint b, uint32 &r)
Flips a coin with a given probability and saves the randomize-number in a variable.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:35
const GRFFile * grffile
GRFFile the resolved SpriteGroup belongs to.
Tile got trees.
Definition: tile_type.h:45
void AmbientSoundEffectCallback(TileIndex tile)
&#39;Execute&#39; the ambient sound effect callback.
GrfSpecFeature GetFeature() const override
Get the feature number being resolved for.
static const IndustryType INVALID_INDUSTRYTYPE
one above amount is considered invalid
Definition: industry_type.h:27
ScopeResolver * GetScope(VarSpriteGroupScope scope=VSG_SCOPE_SELF, byte relative=0) override
Get a resolver for the scope.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:117
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
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:380
CallbackID callback
Callback being resolved.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint8 src_industry
Source industry substitute type. 0xFF for "town", 0xFE for "unknown".
void ResetGenericCallbacks()
Reset all generic feature callback sprite groups.
static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject &object, uint32 param1_grfv7, uint32 param1_grfv8, const GRFFile **file)
Follow a generic feature callback list and return the first successful answer.
static uint TileHeight(TileIndex tile)
Returns the height of a tile.
Definition: tile_map.h:29
uint8 bitnum
Cargo bit number, is INVALID_CARGO for a non-used spec.
Definition: cargotype.h:56
CallbackID
List of implemented NewGRF callbacks.
Select an ambient sound to play for a given type of tile.
static bool HasTileWaterClass(TileIndex t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:95
Functions related to NewGRF provided sounds.
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition: tile_type.h:41
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:20
GenericScopeResolver(ResolverObject &ro, bool ai_callback)
Generic scope resolver.
uint32 GetVariable(byte variable, uint32 parameter, bool *available) const override
Get a variable value.
Dynamic data of a loaded NewGRF.
Definition: newgrf.h:105