00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "landscape.h"
00015 #include "newgrf_house.h"
00016 #include "newgrf_spritegroup.h"
00017 #include "newgrf_town.h"
00018 #include "newgrf_sound.h"
00019 #include "company_func.h"
00020 #include "company_base.h"
00021 #include "town.h"
00022 #include "genworld.h"
00023 #include "newgrf_animation_base.h"
00024 #include "newgrf_cargo.h"
00025 #include "station_base.h"
00026
00027 static BuildingCounts<uint32> _building_counts;
00028 static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
00029
00030 HouseOverrideManager _house_mngr(NEW_HOUSE_OFFSET, NUM_HOUSES, INVALID_HOUSE_ID);
00031
00042 HouseScopeResolver::HouseScopeResolver(ResolverObject &ro, HouseID house_id, TileIndex tile, Town *town,
00043 bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
00044 : ScopeResolver(ro)
00045 {
00046 this->house_id = house_id;
00047 this->tile = tile;
00048 this->town = town;
00049 this->not_yet_constructed = not_yet_constructed;
00050 this->initial_random_bits = initial_random_bits;
00051 this->watched_cargo_triggers = watched_cargo_triggers;
00052 }
00053
00059 static const GRFFile *GetHouseSpecGrf(HouseID house_id)
00060 {
00061 const HouseSpec *hs = HouseSpec::Get(house_id);
00062 return (hs != NULL) ? hs->grf_prop.grffile : NULL;
00063 }
00064
00077 HouseResolverObject::HouseResolverObject(HouseID house_id, TileIndex tile, Town *town,
00078 CallbackID callback, uint32 param1, uint32 param2,
00079 bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
00080 : ResolverObject(GetHouseSpecGrf(house_id), callback, param1, param2),
00081 house_scope(*this, house_id, tile, town, not_yet_constructed, initial_random_bits, watched_cargo_triggers),
00082 town_scope(*this, town, not_yet_constructed)
00083 {
00084 this->root_spritegroup = HouseSpec::Get(house_id)->grf_prop.spritegroup[0];
00085 }
00086
00087 HouseClassID AllocateHouseClassID(byte grf_class_id, uint32 grfid)
00088 {
00089
00090 for (int i = 1; i != lengthof(_class_mapping); i++) {
00091 HouseClassMapping *map = &_class_mapping[i];
00092
00093 if (map->class_id == grf_class_id && map->grfid == grfid) return (HouseClassID)i;
00094
00095 if (map->class_id == 0 && map->grfid == 0) {
00096 map->class_id = grf_class_id;
00097 map->grfid = grfid;
00098 return (HouseClassID)i;
00099 }
00100 }
00101 return HOUSE_NO_CLASS;
00102 }
00103
00104 void InitializeBuildingCounts()
00105 {
00106 memset(&_building_counts, 0, sizeof(_building_counts));
00107
00108 Town *t;
00109 FOR_ALL_TOWNS(t) {
00110 memset(&t->cache.building_counts, 0, sizeof(t->cache.building_counts));
00111 }
00112 }
00113
00120 void IncreaseBuildingCount(Town *t, HouseID house_id)
00121 {
00122 HouseClassID class_id = HouseSpec::Get(house_id)->class_id;
00123
00124 if (!_loaded_newgrf_features.has_newhouses) return;
00125
00126 t->cache.building_counts.id_count[house_id]++;
00127 _building_counts.id_count[house_id]++;
00128
00129 if (class_id == HOUSE_NO_CLASS) return;
00130
00131 t->cache.building_counts.class_count[class_id]++;
00132 _building_counts.class_count[class_id]++;
00133 }
00134
00141 void DecreaseBuildingCount(Town *t, HouseID house_id)
00142 {
00143 HouseClassID class_id = HouseSpec::Get(house_id)->class_id;
00144
00145 if (!_loaded_newgrf_features.has_newhouses) return;
00146
00147 if (t->cache.building_counts.id_count[house_id] > 0) t->cache.building_counts.id_count[house_id]--;
00148 if (_building_counts.id_count[house_id] > 0) _building_counts.id_count[house_id]--;
00149
00150 if (class_id == HOUSE_NO_CLASS) return;
00151
00152 if (t->cache.building_counts.class_count[class_id] > 0) t->cache.building_counts.class_count[class_id]--;
00153 if (_building_counts.class_count[class_id] > 0) _building_counts.class_count[class_id]--;
00154 }
00155
00156 uint32 HouseScopeResolver::GetRandomBits() const
00157 {
00158
00159 assert(IsValidTile(this->tile) && (this->not_yet_constructed || IsTileType(this->tile, MP_HOUSE)));
00160 return this->not_yet_constructed ? this->initial_random_bits : GetHouseRandomBits(this->tile);
00161 }
00162
00163 uint32 HouseScopeResolver::GetTriggers() const
00164 {
00165
00166 assert(IsValidTile(this->tile) && (this->not_yet_constructed || IsTileType(this->tile, MP_HOUSE)));
00167 return this->not_yet_constructed ? 0 : GetHouseTriggers(this->tile);
00168 }
00169
00170 void HouseScopeResolver::SetTriggers(int triggers) const
00171 {
00172 assert(!this->not_yet_constructed && IsValidTile(this->tile) && IsTileType(this->tile, MP_HOUSE));
00173 SetHouseTriggers(this->tile, triggers);
00174 }
00175
00176 static uint32 GetNumHouses(HouseID house_id, const Town *town)
00177 {
00178 uint8 map_id_count, town_id_count, map_class_count, town_class_count;
00179 HouseClassID class_id = HouseSpec::Get(house_id)->class_id;
00180
00181 map_id_count = ClampU(_building_counts.id_count[house_id], 0, 255);
00182 map_class_count = ClampU(_building_counts.class_count[class_id], 0, 255);
00183 town_id_count = ClampU(town->cache.building_counts.id_count[house_id], 0, 255);
00184 town_class_count = ClampU(town->cache.building_counts.class_count[class_id], 0, 255);
00185
00186 return map_class_count << 24 | town_class_count << 16 | map_id_count << 8 | town_id_count;
00187 }
00188
00196 static uint32 GetNearbyTileInformation(byte parameter, TileIndex tile, bool grf_version8)
00197 {
00198 tile = GetNearbyTile(parameter, tile);
00199 return GetNearbyTileInformation(tile, grf_version8);
00200 }
00201
00203 struct SearchNearbyHouseData {
00204 const HouseSpec *hs;
00205 TileIndex north_tile;
00206 };
00207
00214 static bool SearchNearbyHouseID(TileIndex tile, void *user_data)
00215 {
00216 if (IsTileType(tile, MP_HOUSE)) {
00217 HouseID house = GetHouseType(tile);
00218 const HouseSpec *hs = HouseSpec::Get(house);
00219 if (hs->grf_prop.grffile != NULL) {
00220 SearchNearbyHouseData *nbhd = (SearchNearbyHouseData *)user_data;
00221
00222 TileIndex north_tile = tile + GetHouseNorthPart(house);
00223 if (north_tile == nbhd->north_tile) return false;
00224
00225 return hs->grf_prop.local_id == nbhd->hs->grf_prop.local_id &&
00226 hs->grf_prop.grffile->grfid == nbhd->hs->grf_prop.grffile->grfid;
00227 }
00228 }
00229 return false;
00230 }
00231
00238 static bool SearchNearbyHouseClass(TileIndex tile, void *user_data)
00239 {
00240 if (IsTileType(tile, MP_HOUSE)) {
00241 HouseID house = GetHouseType(tile);
00242 const HouseSpec *hs = HouseSpec::Get(house);
00243 if (hs->grf_prop.grffile != NULL) {
00244 SearchNearbyHouseData *nbhd = (SearchNearbyHouseData *)user_data;
00245
00246 TileIndex north_tile = tile + GetHouseNorthPart(house);
00247 if (north_tile == nbhd->north_tile) return false;
00248
00249 return hs->class_id == nbhd->hs->class_id &&
00250 hs->grf_prop.grffile->grfid == nbhd->hs->grf_prop.grffile->grfid;
00251 }
00252 }
00253 return false;
00254 }
00255
00262 static bool SearchNearbyHouseGRFID(TileIndex tile, void *user_data)
00263 {
00264 if (IsTileType(tile, MP_HOUSE)) {
00265 HouseID house = GetHouseType(tile);
00266 const HouseSpec *hs = HouseSpec::Get(house);
00267 if (hs->grf_prop.grffile != NULL) {
00268 SearchNearbyHouseData *nbhd = (SearchNearbyHouseData *)user_data;
00269
00270 TileIndex north_tile = tile + GetHouseNorthPart(house);
00271 if (north_tile == nbhd->north_tile) return false;
00272
00273 return hs->grf_prop.grffile->grfid == nbhd->hs->grf_prop.grffile->grfid;
00274 }
00275 }
00276 return false;
00277 }
00278
00289 static uint32 GetDistanceFromNearbyHouse(uint8 parameter, TileIndex tile, HouseID house)
00290 {
00291 static TestTileOnSearchProc * const search_procs[3] = {
00292 SearchNearbyHouseID,
00293 SearchNearbyHouseClass,
00294 SearchNearbyHouseGRFID,
00295 };
00296 TileIndex found_tile = tile;
00297 uint8 searchtype = GB(parameter, 6, 2);
00298 uint8 searchradius = GB(parameter, 0, 6);
00299 if (searchtype >= lengthof(search_procs)) return 0;
00300 if (searchradius < 1) return 0;
00301
00302 SearchNearbyHouseData nbhd;
00303 nbhd.hs = HouseSpec::Get(house);
00304 nbhd.north_tile = tile + GetHouseNorthPart(house);
00305
00306
00307 if (CircularTileSearch(&found_tile, 2 * searchradius + 1, search_procs[searchtype], &nbhd)) {
00308 return DistanceManhattan(found_tile, tile);
00309 }
00310 return 0;
00311 }
00312
00316 uint32 HouseScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
00317 {
00318 switch (variable) {
00319
00320 case 0x40: return (IsTileType(this->tile, MP_HOUSE) ? GetHouseBuildingStage(this->tile) : 0) | TileHash2Bit(TileX(this->tile), TileY(this->tile)) << 2;
00321
00322
00323 case 0x41: return IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile) : 0;
00324
00325
00326 case 0x42: return GetTownRadiusGroup(this->town, this->tile);
00327
00328
00329 case 0x43: return GetTerrainType(this->tile);
00330
00331
00332 case 0x44: return GetNumHouses(this->house_id, this->town);
00333
00334
00335 case 0x45: return _generating_world ? 1 : 0;
00336
00337
00338 case 0x46: return IsTileType(this->tile, MP_HOUSE) ? GetAnimationFrame(this->tile) : 0;
00339
00340
00341 case 0x47: return TileY(this->tile) << 16 | TileX(this->tile);
00342
00343
00344 case 0x60: return parameter < NEW_HOUSE_OFFSET ? GetNumHouses(parameter, this->town) : 0;
00345
00346
00347 case 0x61: {
00348 const HouseSpec *hs = HouseSpec::Get(this->house_id);
00349 if (hs->grf_prop.grffile == NULL) return 0;
00350
00351 HouseID new_house = _house_mngr.GetID(parameter, hs->grf_prop.grffile->grfid);
00352 return new_house == INVALID_HOUSE_ID ? 0 : GetNumHouses(new_house, this->town);
00353 }
00354
00355
00356 case 0x62: return GetNearbyTileInformation(parameter, this->tile, this->ro.grffile->grf_version >= 8);
00357
00358
00359 case 0x63: {
00360 TileIndex testtile = GetNearbyTile(parameter, this->tile);
00361 return IsTileType(testtile, MP_HOUSE) ? GetAnimationFrame(testtile) : 0;
00362 }
00363
00364
00365 case 0x64: {
00366 CargoID cid = GetCargoTranslation(parameter, this->ro.grffile);
00367 if (cid == CT_INVALID) return 0;
00368
00369
00370 int8 x_offs = GB(GetRegister(0x100), 0, 8);
00371 int8 y_offs = GB(GetRegister(0x100), 8, 8);
00372 TileIndex testtile = TILE_MASK(this->tile + TileDiffXY(x_offs, y_offs));
00373
00374 StationFinder stations(TileArea(testtile, 1, 1));
00375 const StationList *sl = stations.GetStations();
00376
00377
00378 uint32 res = 0;
00379 for (Station * const * st_iter = sl->Begin(); st_iter != sl->End(); st_iter++) {
00380 const Station *st = *st_iter;
00381 if (HasBit(st->goods[cid].status, GoodsEntry::GES_EVER_ACCEPTED)) SetBit(res, 0);
00382 if (HasBit(st->goods[cid].status, GoodsEntry::GES_LAST_MONTH)) SetBit(res, 1);
00383 if (HasBit(st->goods[cid].status, GoodsEntry::GES_CURRENT_MONTH)) SetBit(res, 2);
00384 if (HasBit(st->goods[cid].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(res, 3);
00385 }
00386
00387
00388 if (HasBit(this->watched_cargo_triggers, cid)) SetBit(res, 4);
00389
00390 return res;
00391 }
00392
00393
00394 case 0x65: return GetDistanceFromNearbyHouse(parameter, this->tile, this->house_id);
00395
00396
00397 case 0x66: {
00398 TileIndex testtile = GetNearbyTile(parameter, this->tile);
00399 if (!IsTileType(testtile, MP_HOUSE)) return 0xFFFFFFFF;
00400 HouseSpec *hs = HouseSpec::Get(GetHouseType(testtile));
00401
00402 uint houseclass = 0;
00403 if (hs->class_id != HOUSE_NO_CLASS) {
00404 houseclass = (hs->grf_prop.grffile == this->ro.grffile ? 1 : 2) << 8;
00405 houseclass |= _class_mapping[hs->class_id].class_id;
00406 }
00407
00408 uint local_houseid = 0;
00409 if (this->house_id < NEW_HOUSE_OFFSET) {
00410 local_houseid = this->house_id;
00411 } else {
00412 local_houseid = (hs->grf_prop.grffile == this->ro.grffile ? 1 : 2) << 8;
00413 local_houseid |= hs->grf_prop.local_id;
00414 }
00415 return houseclass << 16 | local_houseid;
00416 }
00417
00418
00419 case 0x67: {
00420 TileIndex testtile = GetNearbyTile(parameter, this->tile);
00421 if (!IsTileType(testtile, MP_HOUSE)) return 0xFFFFFFFF;
00422 HouseID house_id = GetHouseType(testtile);
00423 if (house_id < NEW_HOUSE_OFFSET) return 0;
00424
00425
00426 return _house_mngr.GetGRFID(house_id);
00427 }
00428 }
00429
00430 DEBUG(grf, 1, "Unhandled house variable 0x%X", variable);
00431
00432 *available = false;
00433 return UINT_MAX;
00434 }
00435
00436 uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile,
00437 bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers)
00438 {
00439 assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE)));
00440
00441 HouseResolverObject object(house_id, tile, town, callback, param1, param2,
00442 not_yet_constructed, initial_random_bits, watched_cargo_triggers);
00443 return object.ResolveCallback();
00444 }
00445
00446 static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, byte stage, HouseID house_id)
00447 {
00448 const DrawTileSprites *dts = group->ProcessRegisters(&stage);
00449
00450 const HouseSpec *hs = HouseSpec::Get(house_id);
00451 PaletteID palette = hs->random_colour[TileHash2Bit(ti->x, ti->y)] + PALETTE_RECOLOUR_START;
00452 if (HasBit(hs->callback_mask, CBM_HOUSE_COLOUR)) {
00453 uint16 callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, Town::GetByTile(ti->tile), ti->tile);
00454 if (callback != CALLBACK_FAILED) {
00455
00456 palette = HasBit(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
00457 }
00458 }
00459
00460 SpriteID image = dts->ground.sprite;
00461 PaletteID pal = dts->ground.pal;
00462
00463 if (HasBit(image, SPRITE_MODIFIER_CUSTOM_SPRITE)) image += stage;
00464 if (HasBit(pal, SPRITE_MODIFIER_CUSTOM_SPRITE)) pal += stage;
00465
00466 if (GB(image, 0, SPRITE_WIDTH) != 0) {
00467 DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
00468 }
00469
00470 DrawNewGRFTileSeq(ti, dts, TO_HOUSES, stage, palette);
00471 }
00472
00473 void DrawNewHouseTile(TileInfo *ti, HouseID house_id)
00474 {
00475 const HouseSpec *hs = HouseSpec::Get(house_id);
00476
00477 if (ti->tileh != SLOPE_FLAT) {
00478 bool draw_old_one = true;
00479 if (HasBit(hs->callback_mask, CBM_HOUSE_DRAW_FOUNDATIONS)) {
00480
00481 uint32 callback_res = GetHouseCallback(CBID_HOUSE_DRAW_FOUNDATIONS, 0, 0, house_id, Town::GetByTile(ti->tile), ti->tile);
00482 if (callback_res != CALLBACK_FAILED) draw_old_one = ConvertBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DRAW_FOUNDATIONS, callback_res);
00483 }
00484
00485 if (draw_old_one) DrawFoundation(ti, FOUNDATION_LEVELED);
00486 }
00487
00488 HouseResolverObject object(house_id, ti->tile, Town::GetByTile(ti->tile));
00489
00490 const SpriteGroup *group = object.Resolve();
00491 if (group != NULL && group->type == SGT_TILELAYOUT) {
00492
00493 const TileLayoutSpriteGroup *tlgroup = (const TileLayoutSpriteGroup *)group;
00494 byte stage = GetHouseBuildingStage(ti->tile);
00495 DrawTileLayout(ti, tlgroup, stage, house_id);
00496 }
00497 }
00498
00499
00500 uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2, const HouseSpec *spec, Town *town, TileIndex tile, uint32 extra_data)
00501 {
00502 return GetHouseCallback(callback, param1, param2, spec - HouseSpec::Get(0), town, tile, false, 0, extra_data);
00503 }
00504
00506 struct HouseAnimationBase : public AnimationBase<HouseAnimationBase, HouseSpec, Town, uint32, GetSimpleHouseCallback> {
00507 static const CallbackID cb_animation_speed = CBID_HOUSE_ANIMATION_SPEED;
00508 static const CallbackID cb_animation_next_frame = CBID_HOUSE_ANIMATION_NEXT_FRAME;
00509
00510 static const HouseCallbackMask cbm_animation_speed = CBM_HOUSE_ANIMATION_SPEED;
00511 static const HouseCallbackMask cbm_animation_next_frame = CBM_HOUSE_ANIMATION_NEXT_FRAME;
00512 };
00513
00514 void AnimateNewHouseTile(TileIndex tile)
00515 {
00516 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
00517 if (hs == NULL) return;
00518
00519 HouseAnimationBase::AnimateTile(hs, Town::GetByTile(tile), tile, HasBit(hs->extra_flags, CALLBACK_1A_RANDOM_BITS));
00520 }
00521
00522 void AnimateNewHouseConstruction(TileIndex tile)
00523 {
00524 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
00525
00526 if (HasBit(hs->callback_mask, CBM_HOUSE_CONSTRUCTION_STATE_CHANGE)) {
00527 HouseAnimationBase::ChangeAnimationFrame(CBID_HOUSE_CONSTRUCTION_STATE_CHANGE, hs, Town::GetByTile(tile), tile, 0, 0);
00528 }
00529 }
00530
00531 bool CanDeleteHouse(TileIndex tile)
00532 {
00533 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
00534
00535
00536
00537 if (Company::IsValidHumanID(_current_company) || _current_company == OWNER_WATER || _current_company == OWNER_NONE || _game_mode == GM_EDITOR || _generating_world) {
00538 return true;
00539 }
00540
00541 if (HasBit(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
00542 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), Town::GetByTile(tile), tile);
00543 return (callback_res == CALLBACK_FAILED || !ConvertBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DENY_DESTRUCTION, callback_res));
00544 } else {
00545 return !(hs->extra_flags & BUILDING_IS_PROTECTED);
00546 }
00547 }
00548
00549 static void AnimationControl(TileIndex tile, uint16 random_bits)
00550 {
00551 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
00552
00553 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
00554 uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
00555 HouseAnimationBase::ChangeAnimationFrame(CBID_HOUSE_ANIMATION_START_STOP, hs, Town::GetByTile(tile), tile, param, 0);
00556 }
00557 }
00558
00559 bool NewHouseTileLoop(TileIndex tile)
00560 {
00561 const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
00562
00563 if (GetHouseProcessingTime(tile) > 0) {
00564 DecHouseProcessingTime(tile);
00565 return true;
00566 }
00567
00568 TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP);
00569 if (hs->building_flags & BUILDING_HAS_1_TILE) TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP_TOP);
00570
00571 if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
00572
00573
00574
00575
00576 if (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) {
00577 uint16 random = GB(Random(), 0, 16);
00578
00579 if (hs->building_flags & BUILDING_HAS_1_TILE) AnimationControl(tile, random);
00580 if (hs->building_flags & BUILDING_2_TILES_Y) AnimationControl(TILE_ADDXY(tile, 0, 1), random);
00581 if (hs->building_flags & BUILDING_2_TILES_X) AnimationControl(TILE_ADDXY(tile, 1, 0), random);
00582 if (hs->building_flags & BUILDING_HAS_4_TILES) AnimationControl(TILE_ADDXY(tile, 1, 1), random);
00583 } else {
00584 AnimationControl(tile, 0);
00585 }
00586 }
00587
00588
00589 if (HasBit(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
00590 uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), Town::GetByTile(tile), tile);
00591 if (callback_res != CALLBACK_FAILED && Convert8bitBooleanCallback(hs->grf_prop.grffile, CBID_HOUSE_DESTRUCTION, callback_res)) {
00592 ClearTownHouse(Town::GetByTile(tile), tile);
00593 return false;
00594 }
00595 }
00596
00597 SetHouseProcessingTime(tile, hs->processing_time);
00598 MarkTileDirtyByTile(tile);
00599 return true;
00600 }
00601
00602 static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_random, bool first)
00603 {
00604
00605 assert(IsTileType(tile, MP_HOUSE));
00606
00607 HouseID hid = GetHouseType(tile);
00608 HouseSpec *hs = HouseSpec::Get(hid);
00609
00610 if (hs->grf_prop.spritegroup[0] == NULL) return;
00611
00612 HouseResolverObject object(hid, tile, Town::GetByTile(tile), CBID_RANDOM_TRIGGER);
00613 object.trigger = trigger;
00614
00615 const SpriteGroup *group = object.Resolve();
00616 if (group == NULL) return;
00617
00618 byte new_random_bits = Random();
00619 byte random_bits = GetHouseRandomBits(tile);
00620 uint32 reseed = object.GetReseedSum();
00621 random_bits &= ~reseed;
00622 random_bits |= (first ? new_random_bits : base_random) & reseed;
00623 SetHouseRandomBits(tile, random_bits);
00624
00625 switch (trigger) {
00626 case HOUSE_TRIGGER_TILE_LOOP:
00627
00628 break;
00629
00630 case HOUSE_TRIGGER_TILE_LOOP_TOP:
00631 if (!first) {
00632
00633 MarkTileDirtyByTile(tile);
00634 break;
00635 }
00636
00637 if (hs->building_flags & BUILDING_2_TILES_Y) DoTriggerHouse(TILE_ADDXY(tile, 0, 1), trigger, random_bits, false);
00638 if (hs->building_flags & BUILDING_2_TILES_X) DoTriggerHouse(TILE_ADDXY(tile, 1, 0), trigger, random_bits, false);
00639 if (hs->building_flags & BUILDING_HAS_4_TILES) DoTriggerHouse(TILE_ADDXY(tile, 1, 1), trigger, random_bits, false);
00640 break;
00641 }
00642 }
00643
00644 void TriggerHouse(TileIndex t, HouseTrigger trigger)
00645 {
00646 DoTriggerHouse(t, trigger, 0, true);
00647 }
00648
00656 void DoWatchedCargoCallback(TileIndex tile, TileIndex origin, uint32 trigger_cargoes, uint16 random)
00657 {
00658 TileIndexDiffC diff = TileIndexToTileIndexDiffC(origin, tile);
00659 uint32 cb_info = random << 16 | (uint8)diff.y << 8 | (uint8)diff.x;
00660 HouseAnimationBase::ChangeAnimationFrame(CBID_HOUSE_WATCHED_CARGO_ACCEPTED, HouseSpec::Get(GetHouseType(tile)), Town::GetByTile(tile), tile, 0, cb_info, trigger_cargoes);
00661 }
00662
00669 void WatchedCargoCallback(TileIndex tile, uint32 trigger_cargoes)
00670 {
00671 assert(IsTileType(tile, MP_HOUSE));
00672 HouseID id = GetHouseType(tile);
00673 const HouseSpec *hs = HouseSpec::Get(id);
00674
00675 trigger_cargoes &= hs->watched_cargoes;
00676
00677 if (trigger_cargoes == 0) return;
00678
00679
00680 uint16 r = Random();
00681
00682
00683 TileIndex north = tile + GetHouseNorthPart(id);
00684 hs = HouseSpec::Get(id);
00685
00686 DoWatchedCargoCallback(north, tile, trigger_cargoes, r);
00687 if (hs->building_flags & BUILDING_2_TILES_Y) DoWatchedCargoCallback(TILE_ADDXY(north, 0, 1), tile, trigger_cargoes, r);
00688 if (hs->building_flags & BUILDING_2_TILES_X) DoWatchedCargoCallback(TILE_ADDXY(north, 1, 0), tile, trigger_cargoes, r);
00689 if (hs->building_flags & BUILDING_HAS_4_TILES) DoWatchedCargoCallback(TILE_ADDXY(north, 1, 1), tile, trigger_cargoes, r);
00690 }
00691