src/newgrf_house.cpp
branchNewGRF_ports
changeset 6871 5a9dc001e1ad
parent 6870 ca3fd1fbe311
child 6872 1c4a4a609f85
--- a/src/newgrf_house.cpp	Sat Oct 06 21:16:00 2007 +0000
+++ b/src/newgrf_house.cpp	Mon Dec 03 23:39:38 2007 +0000
@@ -25,6 +25,7 @@
 #include "newgrf_town.h"
 #include "newgrf_sound.h"
 #include "newgrf_commons.h"
+#include "transparency.h"
 
 static BuildingCounts    _building_counts;
 static HouseClassMapping _class_mapping[HOUSE_CLASS_MAX];
@@ -210,7 +211,7 @@
 		case 0x40: return (IsTileType(tile, MP_HOUSE) ? GetHouseBuildingStage(tile) : 0) | OriginalTileRandomiser(TileX(tile), TileY(tile)) << 2;
 
 		/* Building age. */
-		case 0x41: return clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
+		case 0x41: return Clamp(_cur_year - GetHouseConstructionYear(tile), 0, 0xFF);
 
 		/* Town zone */
 		case 0x42: return GetTownRadiusGroup(town, tile);
@@ -320,14 +321,14 @@
 
 		if (IS_CUSTOM_SPRITE(image)) image += stage;
 
-		if ((HASBIT(image, SPRITE_MODIFIER_OPAQUE) || !HASBIT(_transparent_opt, TO_HOUSES)) && HASBIT(image, PALETTE_MODIFIER_COLOR)) {
+		if ((HasBit(image, SPRITE_MODIFIER_OPAQUE) || !IsTransparencySet(TO_HOUSES)) && HasBit(image, PALETTE_MODIFIER_COLOR)) {
 			if (pal == 0) {
 				const HouseSpec *hs = GetHouseSpecs(house_id);
-				if (HASBIT(hs->callback_mask, CBM_HOUSE_COLOUR)) {
+				if (HasBit(hs->callback_mask, CBM_HOUSE_COLOUR)) {
 					uint16 callback = GetHouseCallback(CBID_HOUSE_COLOUR, 0, 0, house_id, GetTownByTile(ti->tile), ti->tile);
 					if (callback != CALLBACK_FAILED) {
 						/* If bit 14 is set, we should use a 2cc colour map, else use the callback value. */
-						pal = HASBIT(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
+						pal = HasBit(callback, 14) ? GB(callback, 0, 8) + SPR_2CCMAP_BASE : callback;
 					}
 				} else {
 					pal = hs->random_colour[OriginalTileRandomiser(ti->x, ti->y)] + PALETTE_RECOLOR_START;
@@ -343,10 +344,10 @@
 				ti->x + dtss->delta_x, ti->y + dtss->delta_y,
 				dtss->size_x, dtss->size_y,
 				dtss->size_z, ti->z + dtss->delta_z,
-				HASBIT(_transparent_opt, TO_HOUSES)
+				IsTransparencySet(TO_HOUSES)
 			);
 		} else {
-			AddChildSpriteScreen(image, pal, dtss->delta_x, dtss->delta_y, HASBIT(_transparent_opt, TO_HOUSES));
+			AddChildSpriteScreen(image, pal, (byte)dtss->delta_x, (byte)dtss->delta_y, IsTransparencySet(TO_HOUSES));
 		}
 	}
 }
@@ -368,7 +369,7 @@
 	} else {
 		/* Limit the building stage to the number of stages supplied. */
 		byte stage = GetHouseBuildingStage(ti->tile);
-		stage = clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
+		stage = Clamp(stage - 4 + group->g.layout.num_sprites, 0, group->g.layout.num_sprites - 1);
 		DrawTileLayout(ti, group, stage, house_id);
 	}
 }
@@ -379,9 +380,9 @@
 	byte animation_speed = hs->animation_speed;
 	bool frame_set_by_callback = false;
 
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_SPEED)) {
 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_SPEED, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
-		if (callback_res != CALLBACK_FAILED) animation_speed = clamp(callback_res & 0xFF, 2, 16);
+		if (callback_res != CALLBACK_FAILED) animation_speed = Clamp(callback_res & 0xFF, 2, 16);
 	}
 
 	/* An animation speed of 2 means the animation frame changes 4 ticks, and
@@ -393,7 +394,7 @@
 	byte frame      = GetHouseAnimationFrame(tile);
 	byte num_frames = GB(hs->animation_frames, 0, 7);
 
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_NEXT_FRAME)) {
 		uint32 param = (hs->extra_flags & CALLBACK_1A_RANDOM_BITS) ? Random() : 0;
 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_NEXT_FRAME, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
@@ -422,7 +423,7 @@
 	if (!frame_set_by_callback) {
 		if (frame < num_frames) {
 			frame++;
-		} else if (frame == num_frames && HASBIT(hs->animation_frames, 7)) {
+		} else if (frame == num_frames && HasBit(hs->animation_frames, 7)) {
 			/* This animation loops, so start again from the beginning */
 			frame = 0;
 		} else {
@@ -460,7 +461,7 @@
 	if ((IsValidPlayer(_current_player) && IsHumanPlayer(_current_player))
 			|| _current_player == OWNER_WATER || _current_player == OWNER_NONE) return true;
 
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_DENY_DESTRUCTION)) {
 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DENY_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		return (callback_res == CALLBACK_FAILED || callback_res == 0);
 	} else {
@@ -472,7 +473,7 @@
 {
 	const HouseSpec *hs = GetHouseSpecs(GetHouseType(tile));
 
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
 		uint32 param = (hs->extra_flags & SYNCHRONISED_CALLBACK_1B) ? (GB(Random(), 0, 16) | random_bits << 16) : Random();
 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_ANIMATION_START_STOP, param, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 
@@ -489,13 +490,10 @@
 		return true;
 	}
 
-	/* @todo: Magic with triggers goes here.  Got to implement that, one day. ..
-	 * Process randomizing of tiles following specs.
-	 * Once done, redraw the house
-	 * MarkTileDirtyByTile(tile);
-	 */
+	TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP);
+	TriggerHouse(tile, HOUSE_TRIGGER_TILE_LOOP_TOP);
 
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_ANIMATION_START_STOP)) {
 		/* If this house is marked as having a synchronised callback, all the
 		 * tiles will have the callback called at once, rather than when the
 		 * tile loop reaches them. This should only be enabled for the northern
@@ -513,7 +511,7 @@
 	}
 
 	/* Check callback 21, which determines if a house should be destroyed. */
-	if (HASBIT(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
+	if (HasBit(hs->callback_mask, CBM_HOUSE_DESTRUCTION)) {
 		uint16 callback_res = GetHouseCallback(CBID_HOUSE_DESTRUCTION, 0, 0, GetHouseType(tile), GetTownByTile(tile), tile);
 		if (callback_res != CALLBACK_FAILED && callback_res > 0) {
 			ClearTownHouse(GetTownByTile(tile), tile);
@@ -524,3 +522,47 @@
 	SetHouseProcessingTime(tile, hs->processing_time);
 	return true;
 }
+
+static void DoTriggerHouse(TileIndex tile, HouseTrigger trigger, byte base_random, bool first)
+{
+	ResolverObject object;
+
+	/* We can't trigger a non-existent building... */
+	assert(IsTileType(tile, MP_HOUSE));
+
+	HouseID hid = GetHouseType(tile);
+	HouseSpec *hs = GetHouseSpecs(hid);
+
+	NewHouseResolver(&object, hid, tile, GetTownByTile(tile));
+
+	object.callback = CBID_RANDOM_TRIGGER;
+	object.trigger = trigger;
+
+	const SpriteGroup *group = Resolve(hs->spritegroup, &object);
+	if (group == NULL) return;
+
+	byte new_random_bits = Random();
+	byte random_bits = GetHouseRandomBits(tile);
+	random_bits &= ~object.reseed;
+	random_bits |= (first ? new_random_bits : base_random) & object.reseed;
+	SetHouseRandomBits(tile, random_bits);
+
+	switch (trigger) {
+		case HOUSE_TRIGGER_TILE_LOOP:
+			/* Random value already set. */
+			break;
+
+		case HOUSE_TRIGGER_TILE_LOOP_TOP:
+			if (!first) break;
+			/* Random value of first tile already set. */
+			if (hs->building_flags & BUILDING_2_TILES_Y)   DoTriggerHouse(TILE_ADDXY(tile, 0, 1), trigger, random_bits, false);
+			if (hs->building_flags & BUILDING_2_TILES_X)   DoTriggerHouse(TILE_ADDXY(tile, 1, 0), trigger, random_bits, false);
+			if (hs->building_flags & BUILDING_HAS_4_TILES) DoTriggerHouse(TILE_ADDXY(tile, 1, 1), trigger, random_bits, false);
+			break;
+	}
+}
+
+void TriggerHouse(TileIndex t, HouseTrigger trigger)
+{
+	DoTriggerHouse(t, trigger, 0, true);
+}