(svn r12006) -Fix: implement FS#1697 without the nasty side effects as specified in FS#1712.
authorrubidium
Tue, 29 Jan 2008 00:36:55 +0000
changeset 8436 c2600da0d3e3
parent 8435 6425e2ecd2a6
child 8437 0da2a03711b9
(svn r12006) -Fix: implement FS#1697 without the nasty side effects as specified in FS#1712.
src/industry_cmd.cpp
src/industry_gui.cpp
src/newgrf_industries.cpp
src/newgrf_industries.h
--- a/src/industry_cmd.cpp	Tue Jan 29 00:29:28 2008 +0000
+++ b/src/industry_cmd.cpp	Tue Jan 29 00:36:55 2008 +0000
@@ -1548,9 +1548,10 @@
  * @param flags of operations to conduct
  * @param indspec pointer to industry specifications
  * @param itspec_index the index of the itsepc to build/fund
+ * @param seed random seed (possibly) used by industries
  * @return the pointer of the newly created industry, or NULL if it failed
  */
-static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index)
+static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint32 flags, const IndustrySpec *indspec, uint itspec_index, uint32 seed)
 {
 	const IndustryTileTable *it = indspec->table[itspec_index];
 	bool custom_shape_check = false;
@@ -1558,7 +1559,7 @@
 	if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL;
 
 	if (HasBit(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) {
-		if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index)) return NULL;
+		if (!CheckIfCallBackAllowsCreation(tile, type, itspec_index, seed)) return NULL;
 	} else {
 		if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
 	}
@@ -1588,15 +1589,15 @@
 /** Build/Fund an industry
  * @param tile tile where industry is built
  * @param flags of operations to conduct
- * @param p1 industry type see build_industry.h and see industry.h
- * @param p2 first layout to try
+ * @param p1 various bitstuffed elements
+ * - p1 = (bit  0 - 15) - industry type see build_industry.h and see industry.h
+ * - p1 = (bit 16 - 31) - first layout to try
+ * @param p2 seed to use for variable 8F
  * @return index of the newly create industry, or CMD_ERROR if it failed
  */
 CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
-	const IndustrySpec *indspec;
-
-	indspec = GetIndustrySpec(p1);
+	const IndustrySpec *indspec = GetIndustrySpec(GB(p1, 0, 16));
 
 	/* Check if the to-be built/founded industry is available for this climate. */
 	if (!indspec->enabled) {
@@ -1620,7 +1621,7 @@
 					 * because parameter evaluation order is not guaranteed in the c++ standard
 					 */
 					tile = RandomTile();
-					const Industry *ind = CreateNewIndustryHelper(tile, p1, flags, indspec, RandomRange(indspec->num_table));
+					const Industry *ind = CreateNewIndustryHelper(tile, p1, flags, indspec, RandomRange(indspec->num_table), p2);
 					if (ind != NULL) {
 						SetDParam(0, indspec->name);
 						if (indspec->new_industry_text > STR_LAST_STRINGID) {
@@ -1639,7 +1640,7 @@
 	} else {
 		int count = indspec->num_table;
 		const IndustryTileTable * const *itt = indspec->table;
-		int num = Clamp(p2, 0, count - 1);
+		int num = Clamp(GB(p1, 16, 16), 0, count - 1);
 
 		_error_message = STR_0239_SITE_UNSUITABLE;
 		do {
@@ -1647,7 +1648,7 @@
 			if (--num < 0) num = indspec->num_table - 1;
 		} while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1));
 
-		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num) == NULL) return CMD_ERROR;
+		if (CreateNewIndustryHelper(tile, p1, flags, indspec, num, p2) == NULL) return CMD_ERROR;
 	}
 
 	return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
@@ -1658,7 +1659,8 @@
 {
 	const IndustrySpec *indspec = GetIndustrySpec(type);
 
-	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table));
+	uint32 seed = Random();
+	return CreateNewIndustryHelper(tile, type, DC_EXEC, indspec, RandomRange(indspec->num_table), seed);
 }
 
 enum {
--- a/src/industry_gui.cpp	Tue Jan 29 00:29:28 2008 +0000
+++ b/src/industry_gui.cpp	Tue Jan 29 00:36:55 2008 +0000
@@ -253,7 +253,7 @@
 							_generating_world = false;
 						}
 					} else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(WP(w, fnd_d).select)->IsRawIndustry()) {
-						DoCommandP(0, WP(w, fnd_d).select, 0, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+						DoCommandP(0, WP(w, fnd_d).select, InteractiveRandom(), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
 						w->HandleButtonClick(DPIW_FUND_WIDGET);
 					} else {
 						HandlePlacePushButton(w, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
@@ -272,6 +272,7 @@
 			bool success = true;
 			/* We do not need to protect ourselves against "Random Many Industries" in this mode */
 			const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select);
+			uint32 seed = InteractiveRandom();
 
 			if (_game_mode == GM_EDITOR) {
 				/* Show error if no town exists at all */
@@ -284,7 +285,7 @@
 				_current_player = OWNER_NONE;
 				_generating_world = true;
 				_ignore_restrictions = true;
-				success = DoCommandP(e->we.place.tile, WP(w, fnd_d).select, InteractiveRandomRange(indsp->num_table), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+				success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
 				if (!success) {
 					SetDParam(0, indsp->name);
 					ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
@@ -293,7 +294,7 @@
 				_ignore_restrictions = false;
 				_generating_world = false;
 			} else {
-				success = DoCommandP(e->we.place.tile, WP(w, fnd_d).select, InteractiveRandomRange(indsp->num_table), NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
+				success = DoCommandP(e->we.place.tile, (InteractiveRandomRange(indsp->num_table) << 16) | WP(w, fnd_d).select, seed, NULL, CMD_BUILD_INDUSTRY | CMD_MSG(STR_4830_CAN_T_CONSTRUCT_THIS_INDUSTRY));
 			}
 
 			/* If an industry has been built, just reset the cursor and the system */
--- a/src/newgrf_industries.cpp	Tue Jan 29 00:29:28 2008 +0000
+++ b/src/newgrf_industries.cpp	Tue Jan 29 00:36:55 2008 +0000
@@ -25,6 +25,8 @@
 
 #include "table/strings.h"
 
+static Randomizer _industry_creation_randomizer;
+
 /* Since the industry IDs defined by the GRF file don't necessarily correlate
  * to those used by the game, the IDs used for overriding old industries must be
  * translated when the idustry spec is set. */
@@ -466,15 +468,15 @@
 		/* Square of Euclidian distance from town */
 		case 0x8D: return min(DistanceSquare(industry->town->xy, tile), 65535);
 
-		/* 32 random bits TODO! Wait for a better scheme that will not cause problems, MP desyncs and asserts */
-		// case 0x8F: return Random();
+		/* 32 random bits */
+		case 0x8F: return _industry_creation_randomizer.Next();
 	}
 
 	/* None of the special ones, so try the general ones */
 	return IndustryGetVariable(object, variable, parameter, available);
 }
 
-bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index)
+bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index, uint32 seed)
 {
 	const IndustrySpec *indspec = GetIndustrySpec(type);
 
@@ -492,6 +494,7 @@
 	NewIndustryResolver(&object, tile, &ind, type);
 	object.GetVariable = IndustryLocationGetVariable;
 	object.callback = CBID_INDUSTRY_LOCATION;
+	_industry_creation_randomizer.SetSeed(seed);
 
 	group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object);
 
--- a/src/newgrf_industries.h	Tue Jan 29 00:29:28 2008 +0000
+++ b/src/newgrf_industries.h	Tue Jan 29 00:36:55 2008 +0000
@@ -30,7 +30,7 @@
 uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile);
 uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i);
 void IndustryProductionCallback(Industry *ind, int reason);
-bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index);
+bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspec_index, uint32 seed);
 bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type);
 
 IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id);