# HG changeset patch # User michi_cc # Date 2011-10-31 22:31:40 # Node ID c04963816211288c253e7b1a09bb4494903cceab # Parent 4c81f615ad472e80b7f581b5a0efa12b975861f5 (svn r23072) -Feature: [NewGRF] House callback 0x148. diff --git a/src/house.h b/src/house.h --- a/src/house.h +++ b/src/house.h @@ -120,6 +120,7 @@ struct HouseSpec { AnimationInfo animation; ///< information about the animation. byte processing_time; ///< Periodic refresh multiplier byte minimum_life; ///< The minimum number of years this house will survive before the town rebuilds it + uint32 watched_cargoes; ///< Cargo types watched for acceptance. Money GetRemovalCost() const; diff --git a/src/newgrf.cpp b/src/newgrf.cpp --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -2031,7 +2031,6 @@ static ChangeInfoResult IgnoreTownHouseP case 0x20: { byte count = buf->ReadByte(); for (byte j = 0; j < count; j++) buf->ReadByte(); - ret = CIR_UNHANDLED; break; } @@ -2251,10 +2250,12 @@ static ChangeInfoResult TownHouseChangeI housespec->minimum_life = buf->ReadByte(); break; - case 0x20: { // @todo Cargo acceptance watch list + case 0x20: { // Cargo acceptance watch list byte count = buf->ReadByte(); - for (byte j = 0; j < count; j++) buf->ReadByte(); - ret = CIR_UNHANDLED; + for (byte j = 0; j < count; j++) { + CargoID cargo = GetCargoTranslation(buf->ReadByte(), _cur.grffile); + if (cargo != CT_INVALID) SetBit(housespec->watched_cargoes, cargo); + } break; } diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h --- a/src/newgrf_callbacks.h +++ b/src/newgrf_callbacks.h @@ -208,7 +208,7 @@ enum CallbackID { CBID_CANALS_SPRITE_OFFSET = 0x147, // 15 bit callback /** Called when a cargo type specified in property 20 is accepted. */ - CBID_HOUSE_WATCHED_CARGO_ACCEPTED = 0x148, // 15 bit callback, not implemented + CBID_HOUSE_WATCHED_CARGO_ACCEPTED = 0x148, // 15 bit callback /** Callback done for each tile of a station to check the slope. */ CBID_STATION_LAND_SLOPE_CHECK = 0x149, // 15 bit callback diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -332,6 +332,9 @@ static uint32 HouseGetVariable(const Res if (HasBit(st->goods[cid].acceptance_pickup, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(res, 3); } + /* Cargo triggered CB 148? */ + if (HasBit(object->u.house.watched_cargo_triggers, cid)) SetBit(res, 4); + return res; } @@ -427,7 +430,7 @@ static void NewHouseResolver(ResolverObj res->grffile = (hs != NULL ? hs->grf_prop.grffile : NULL); } -uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed, uint8 initial_random_bits) +uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed, uint8 initial_random_bits, uint32 watched_cargo_triggers) { ResolverObject object; const SpriteGroup *group; @@ -440,6 +443,7 @@ uint16 GetHouseCallback(CallbackID callb object.callback_param2 = param2; object.u.house.not_yet_constructed = not_yet_constructed; object.u.house.initial_random_bits = initial_random_bits; + object.u.house.watched_cargo_triggers = watched_cargo_triggers; group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->grf_prop.spritegroup[0], &object); if (group == NULL) return CALLBACK_FAILED; @@ -507,7 +511,7 @@ void DrawNewHouseTile(TileInfo *ti, Hous /* Simple wrapper for GetHouseCallback to keep the animation unified. */ uint16 GetSimpleHouseCallback(CallbackID callback, uint32 param1, uint32 param2, const HouseSpec *spec, Town *town, TileIndex tile, uint32 extra_data) { - return GetHouseCallback(callback, param1, param2, spec - HouseSpec::Get(0), town, tile); + return GetHouseCallback(callback, param1, param2, spec - HouseSpec::Get(0), town, tile, false, 0, extra_data); } /** Helper class for animation control. */ @@ -659,6 +663,49 @@ void TriggerHouse(TileIndex t, HouseTrig } /** + * Run the watched cargo accepted callback for a single house tile. + * @param tile The house tile. + * @param origin The triggering tile. + * @param trigger_cargoes Cargo types that triggered the callback. + * @param random Random bits. + */ +void DoWatchedCargoCallback(TileIndex tile, TileIndex origin, uint32 trigger_cargoes, uint16 random) +{ + TileIndexDiffC diff = TileIndexToTileIndexDiffC(origin, tile); + uint32 cb_info = random << 16 | (uint8)diff.y << 8 | (uint8)diff.x; + HouseAnimationBase::ChangeAnimationFrame(CBID_HOUSE_WATCHED_CARGO_ACCEPTED, HouseSpec::Get(GetHouseType(tile)), Town::GetByTile(tile), tile, 0, cb_info, trigger_cargoes); +} + +/** + * Run watched cargo accepted callback for a house. + * @param tile House tile. + * @param trigger_cargoes Triggering cargo types. + * @pre IsTileType(t, MP_HOUSE) + */ +void WatchedCargoCallback(TileIndex tile, uint32 trigger_cargoes) +{ + assert(IsTileType(tile, MP_HOUSE)); + HouseID id = GetHouseType(tile); + const HouseSpec *hs = HouseSpec::Get(id); + + trigger_cargoes &= hs->watched_cargoes; + /* None of the trigger cargoes is watched? */ + if (trigger_cargoes == 0) return; + + /* Same random value for all tiles of a multi-tile house. */ + uint16 r = Random(); + + /* Do the callback, start at northern tile. */ + TileIndex north = tile + GetHouseNorthPart(id); + hs = HouseSpec::Get(id); + + DoWatchedCargoCallback(north, tile, trigger_cargoes, r); + if (hs->building_flags & BUILDING_2_TILES_Y) DoWatchedCargoCallback(TILE_ADDXY(north, 0, 1), tile, trigger_cargoes, r); + if (hs->building_flags & BUILDING_2_TILES_X) DoWatchedCargoCallback(TILE_ADDXY(north, 1, 0), tile, trigger_cargoes, r); + if (hs->building_flags & BUILDING_HAS_4_TILES) DoWatchedCargoCallback(TILE_ADDXY(north, 1, 1), tile, trigger_cargoes, r); +} + +/** * Resolve a house's spec and such so we can get a variable. * @param ro The resolver object to fill. * @param index The house tile to get the data from. diff --git a/src/newgrf_house.h b/src/newgrf_house.h --- a/src/newgrf_house.h +++ b/src/newgrf_house.h @@ -44,7 +44,8 @@ void DrawNewHouseTile(TileInfo *ti, Hous void AnimateNewHouseTile(TileIndex tile); void AnimateNewHouseConstruction(TileIndex tile); -uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed = false, uint8 initial_random_bits = 0); +uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed = false, uint8 initial_random_bits = 0, uint32 watched_cargo_triggers = 0); +void WatchedCargoCallback(TileIndex tile, uint32 trigger_cargoes); bool CanDeleteHouse(TileIndex tile); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -341,6 +341,7 @@ struct ResolverObject { HouseID house_id; uint16 initial_random_bits; ///< Random bits during construction checks bool not_yet_constructed; ///< True for construction check + uint32 watched_cargo_triggers; ///< Cargo types that triggered the watched cargo callback. } house; struct { TileIndex tile; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -49,6 +49,7 @@ #include "table/airporttile_ids.h" #include "newgrf_airporttiles.h" #include "order_backup.h" +#include "newgrf_house.h" #include "table/strings.h" @@ -2987,6 +2988,31 @@ static VehicleEnterTileStatus VehicleEnt } /** + * Run the watched cargo callback for all houses in the catchment area. + * @param st Station. + */ +void TriggerWatchedCargoCallbacks(Station *st) +{ + /* Collect cargoes accepted since the last big tick. */ + uint cargoes = 0; + for (CargoID cid = 0; cid < NUM_CARGO; cid++) { + if (HasBit(st->goods[cid].acceptance_pickup, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cid); + } + + /* Anything to do? */ + if (cargoes == 0) return; + + /* Loop over all houses in the catchment. */ + Rect r = st->GetCatchmentRect(); + TileArea ta(TileXY(r.left, r.top), TileXY(r.right, r.bottom)); + TILE_AREA_LOOP(tile, ta) { + if (IsTileType(tile, MP_HOUSE)) { + WatchedCargoCallback(tile, cargoes); + } + } +} + +/** * This function is called for each station once every 250 ticks. * Not all stations will get the tick at the same time. * @param st the station receiving the tick. @@ -3000,6 +3026,8 @@ static bool StationHandleBigTick(BaseSta } if (Station::IsExpected(st)) { + TriggerWatchedCargoCallbacks(Station::From(st)); + for (CargoID i = 0; i < NUM_CARGO; i++) { ClrBit(Station::From(st)->goods[i].acceptance_pickup, GoodsEntry::GES_ACCEPTED_BIGTICK); } diff --git a/src/table/town_land.h b/src/table/town_land.h --- a/src/table/town_land.h +++ b/src/table/town_land.h @@ -1813,7 +1813,7 @@ assert_compile(lengthof(_town_draw_tile_ */ #define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \ {mnd, mxd, p, rc, bn, rr, mg, {ca1, ca2, ca3}, {cg1, cg2, cg3}, bf, ba, true, \ - GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0} + GRFFileProps(INVALID_HOUSE_ID), 0, {0, 0, 0, 0}, 16, NO_EXTRA_FLAG, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0} /** House specifications from original data */ static const HouseSpec _original_house_specs[] = { /**