00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "newgrf.h"
00015 #include "newgrf_spritegroup.h"
00016 #include "industrytype.h"
00017 #include "core/bitmath_func.hpp"
00018 #include "core/random_func.hpp"
00019 #include "tile_map.h"
00020 #include "newgrf_sound.h"
00021 #include "water_map.h"
00022 #include <list>
00023
00024
00025 struct GenericCallback {
00026 const GRFFile *file;
00027 const SpriteGroup *group;
00028
00029 GenericCallback(const GRFFile *file, const SpriteGroup *group) :
00030 file(file),
00031 group(group)
00032 { }
00033 };
00034
00035 typedef std::list<GenericCallback> GenericCallbackList;
00036
00037 static GenericCallbackList _gcl[GSF_END];
00038
00039
00043 void ResetGenericCallbacks()
00044 {
00045 for (uint8 feature = 0; feature < lengthof(_gcl); feature++) {
00046 _gcl[feature].clear();
00047 }
00048 }
00049
00050
00057 void AddGenericCallback(uint8 feature, const GRFFile *file, const SpriteGroup *group)
00058 {
00059 if (feature >= lengthof(_gcl)) {
00060 grfmsg(5, "AddGenericCallback: Unsupported feature 0x%02X", feature);
00061 return;
00062 }
00063
00064
00065
00066
00067 _gcl[feature].push_front(GenericCallback(file, group));
00068 }
00069
00070
00071 static uint32 GenericCallbackGetRandomBits(const ResolverObject *object)
00072 {
00073 return 0;
00074 }
00075
00076
00077 static uint32 GenericCallbackGetTriggers(const ResolverObject *object)
00078 {
00079 return 0;
00080 }
00081
00082
00083 static void GenericCallbackSetTriggers(const ResolverObject *object, int triggers)
00084 {
00085 return;
00086 }
00087
00088
00089 static uint32 GenericCallbackGetVariable(const ResolverObject *object, byte variable, uint32 parameter, bool *available)
00090 {
00091 DEBUG(grf, 1, "Unhandled generic feature variable 0x%02X", variable);
00092
00093 *available = false;
00094 return UINT_MAX;
00095 }
00096
00097 static uint32 GenericAiCallbackGetVariable(const ResolverObject *object, byte variable, uint32 parameter, bool *available)
00098 {
00099 switch (variable) {
00100 case 0x40: return object->grffile->cargo_map[object->u.generic.cargo_type];
00101
00102 case 0x80: return object->u.generic.cargo_type;
00103 case 0x81: return CargoSpec::Get(object->u.generic.cargo_type)->bitnum;
00104 case 0x82: return object->u.generic.default_selection;
00105 case 0x83: return object->u.generic.src_industry;
00106 case 0x84: return object->u.generic.dst_industry;
00107 case 0x85: return object->u.generic.distance;
00108 case 0x86: return object->u.generic.event;
00109 case 0x87: return object->u.generic.count;
00110 case 0x88: return object->u.generic.station_size;
00111
00112 default: break;
00113 }
00114
00115 DEBUG(grf, 1, "Unhandled generic feature variable 0x%02X", variable);
00116
00117 *available = false;
00118 return UINT_MAX;
00119 }
00120
00121
00122 static const SpriteGroup *GenericCallbackResolveReal(const ResolverObject *object, const RealSpriteGroup *group)
00123 {
00124 if (group->num_loaded == 0) return NULL;
00125
00126 return group->loaded[0];
00127 }
00128
00129
00130 static inline void NewGenericResolver(ResolverObject *res, bool ai_callback)
00131 {
00132 res->GetRandomBits = &GenericCallbackGetRandomBits;
00133 res->GetTriggers = &GenericCallbackGetTriggers;
00134 res->SetTriggers = &GenericCallbackSetTriggers;
00135 res->GetVariable = ai_callback ? &GenericAiCallbackGetVariable : &GenericCallbackGetVariable;
00136 res->ResolveReal = &GenericCallbackResolveReal;
00137
00138 res->callback = CBID_NO_CALLBACK;
00139 res->callback_param1 = 0;
00140 res->callback_param2 = 0;
00141 res->ResetState();
00142 }
00143
00144
00156 static uint16 GetGenericCallbackResult(uint8 feature, ResolverObject *object, uint32 param1_grfv7, uint32 param1_grfv8, const GRFFile **file)
00157 {
00158 assert(feature < lengthof(_gcl));
00159
00160
00161 for (GenericCallbackList::const_iterator it = _gcl[feature].begin(); it != _gcl[feature].end(); ++it) {
00162 const SpriteGroup *group = it->group;
00163 object->grffile = it->file;
00164
00165 object->callback_param1 = it->file->grf_version >= 8 ? param1_grfv8 : param1_grfv7;
00166 group = SpriteGroup::Resolve(group, object);
00167 if (group == NULL || group->GetCallbackResult() == CALLBACK_FAILED) continue;
00168
00169
00170 if (file != NULL) *file = it->file;
00171
00172 return group->GetCallbackResult();
00173 }
00174
00175
00176 return CALLBACK_FAILED;
00177 }
00178
00179
00196 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)
00197 {
00198 ResolverObject object;
00199
00200 NewGenericResolver(&object, true);
00201
00202 if (src_industry != IT_AI_UNKNOWN && src_industry != IT_AI_TOWN) {
00203 const IndustrySpec *is = GetIndustrySpec(src_industry);
00204
00205 if (is->grf_prop.subst_id != INVALID_INDUSTRYTYPE) src_industry = is->grf_prop.subst_id;
00206 }
00207
00208 if (dst_industry != IT_AI_UNKNOWN && dst_industry != IT_AI_TOWN) {
00209 const IndustrySpec *is = GetIndustrySpec(dst_industry);
00210
00211 if (is->grf_prop.subst_id != INVALID_INDUSTRYTYPE) dst_industry = is->grf_prop.subst_id;
00212 }
00213
00214 object.callback = CBID_GENERIC_AI_PURCHASE_SELECTION;
00215 object.u.generic.cargo_type = cargo_type;
00216 object.u.generic.default_selection = default_selection;
00217 object.u.generic.src_industry = src_industry;
00218 object.u.generic.dst_industry = dst_industry;
00219 object.u.generic.distance = distance;
00220 object.u.generic.event = event;
00221 object.u.generic.count = count;
00222 object.u.generic.station_size = station_size;
00223
00224 uint16 callback = GetGenericCallbackResult(feature, &object, 0, 0, file);
00225 if (callback != CALLBACK_FAILED) callback = GB(callback, 0, 8);
00226 return callback;
00227 }
00228
00229
00234 void AmbientSoundEffectCallback(TileIndex tile)
00235 {
00236 assert(IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES) || IsTileType(tile, MP_WATER));
00237
00238
00239 if (!HasGrfMiscBit(GMB_AMBIENT_SOUND_CALLBACK)) return;
00240
00241 uint32 r;
00242 if (!Chance16R(1, 200, r)) return;
00243
00244 ResolverObject object;
00245
00246
00247 NewGenericResolver(&object, false);
00248 object.callback = CBID_SOUNDS_AMBIENT_EFFECT;
00249
00250 uint32 param1_v7 = GetTileType(tile) << 28 | Clamp(TileHeight(tile), 0, 15) << 24 | GB(r, 16, 8) << 16 | GetTerrainType(tile);
00251 uint32 param1_v8 = GetTileType(tile) << 24 | GetTileZ(tile) << 16 | GB(r, 16, 8) << 8 | (HasTileWaterClass(tile) ? GetWaterClass(tile) : 0) << 3 | GetTerrainType(tile);
00252
00253
00254 const GRFFile *grf_file;
00255 uint16 callback = GetGenericCallbackResult(GSF_SOUNDFX, &object, param1_v7, param1_v8, &grf_file);
00256
00257 if (callback != CALLBACK_FAILED) PlayTileSound(grf_file, callback, tile);
00258 }