changeset 18236:b3e5d5d70f00 draft

(svn r23072) -Feature: [NewGRF] House callback 0x148.
author michi_cc <michi_cc@openttd.org>
date Mon, 31 Oct 2011 22:31:40 +0000
parents 06aefc7e77d0
children 594f7483c683
files src/house.h src/newgrf.cpp src/newgrf_callbacks.h src/newgrf_house.cpp src/newgrf_house.h src/newgrf_spritegroup.h src/station_cmd.cpp src/table/town_land.h
diffstat 8 files changed, 88 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/house.h
+++ b/src/house.h
@@ -120,6 +120,7 @@
 	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;
 
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2031,7 +2031,6 @@
 		case 0x20: {
 			byte count = buf->ReadByte();
 			for (byte j = 0; j < count; j++) buf->ReadByte();
-			ret = CIR_UNHANDLED;
 			break;
 		}
 
@@ -2251,10 +2250,12 @@
 				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;
 			}
 
--- a/src/newgrf_callbacks.h
+++ b/src/newgrf_callbacks.h
@@ -208,7 +208,7 @@
 	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
--- a/src/newgrf_house.cpp
+++ b/src/newgrf_house.cpp
@@ -332,6 +332,9 @@
 				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 @@
 	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 @@
 	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 @@
 /* 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 @@
 }
 
 /**
+ * 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.
--- a/src/newgrf_house.h
+++ b/src/newgrf_house.h
@@ -44,7 +44,8 @@
 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);
 
--- a/src/newgrf_spritegroup.h
+++ b/src/newgrf_spritegroup.h
@@ -341,6 +341,7 @@
 			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;
--- 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 @@
 }
 
 /**
+ * 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 @@
 	}
 
 	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);
 		}
--- a/src/table/town_land.h
+++ b/src/table/town_land.h
@@ -1813,7 +1813,7 @@
  */
 #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[] = {
 	/**