(svn r12006) -Fix: implement FS#1697 without the nasty side effects as specified in FS#1712.

This commit is contained in:
rubidium 2008-01-29 00:36:55 +00:00
parent c9a9103566
commit 1629699094
4 changed files with 24 additions and 18 deletions

View File

@ -1548,9 +1548,10 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind
* @param flags of operations to conduct * @param flags of operations to conduct
* @param indspec pointer to industry specifications * @param indspec pointer to industry specifications
* @param itspec_index the index of the itsepc to build/fund * @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 * @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]; const IndustryTileTable *it = indspec->table[itspec_index];
bool custom_shape_check = false; bool custom_shape_check = false;
@ -1558,7 +1559,7 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint
if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL; if (!CheckIfIndustryTilesAreFree(tile, it, itspec_index, type, &custom_shape_check)) return NULL;
if (HasBit(GetIndustrySpec(type)->callback_flags, CBM_IND_LOCATION)) { 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 { } else {
if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL; if (!_check_new_industry_procs[indspec->check_proc](tile)) return NULL;
} }
@ -1588,15 +1589,15 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint
/** Build/Fund an industry /** Build/Fund an industry
* @param tile tile where industry is built * @param tile tile where industry is built
* @param flags of operations to conduct * @param flags of operations to conduct
* @param p1 industry type see build_industry.h and see industry.h * @param p1 various bitstuffed elements
* @param p2 first layout to try * - 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 * @return index of the newly create industry, or CMD_ERROR if it failed
*/ */
CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
{ {
const IndustrySpec *indspec; const IndustrySpec *indspec = GetIndustrySpec(GB(p1, 0, 16));
indspec = GetIndustrySpec(p1);
/* Check if the to-be built/founded industry is available for this climate. */ /* Check if the to-be built/founded industry is available for this climate. */
if (!indspec->enabled) { if (!indspec->enabled) {
@ -1620,7 +1621,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
* because parameter evaluation order is not guaranteed in the c++ standard * because parameter evaluation order is not guaranteed in the c++ standard
*/ */
tile = RandomTile(); 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) { if (ind != NULL) {
SetDParam(0, indspec->name); SetDParam(0, indspec->name);
if (indspec->new_industry_text > STR_LAST_STRINGID) { if (indspec->new_industry_text > STR_LAST_STRINGID) {
@ -1639,7 +1640,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
} else { } else {
int count = indspec->num_table; int count = indspec->num_table;
const IndustryTileTable * const *itt = indspec->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; _error_message = STR_0239_SITE_UNSUITABLE;
do { do {
@ -1647,7 +1648,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (--num < 0) num = indspec->num_table - 1; if (--num < 0) num = indspec->num_table - 1;
} while (!CheckIfIndustryTilesAreFree(tile, itt[num], num, p1)); } 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()); return CommandCost(EXPENSES_OTHER, indspec->GetConstructionCost());
@ -1658,7 +1659,8 @@ Industry *CreateNewIndustry(TileIndex tile, IndustryType type)
{ {
const IndustrySpec *indspec = GetIndustrySpec(type); 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 { enum {

View File

@ -253,7 +253,7 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
_generating_world = false; _generating_world = false;
} }
} else if (_game_mode != GM_EDITOR && _patches.raw_industry_construction == 2 && GetIndustrySpec(WP(w, fnd_d).select)->IsRawIndustry()) { } 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); w->HandleButtonClick(DPIW_FUND_WIDGET);
} else { } else {
HandlePlacePushButton(w, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL); HandlePlacePushButton(w, DPIW_FUND_WIDGET, SPR_CURSOR_INDUSTRY, VHM_RECT, NULL);
@ -272,6 +272,7 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
bool success = true; bool success = true;
/* We do not need to protect ourselves against "Random Many Industries" in this mode */ /* We do not need to protect ourselves against "Random Many Industries" in this mode */
const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select); const IndustrySpec *indsp = GetIndustrySpec(WP(w, fnd_d).select);
uint32 seed = InteractiveRandom();
if (_game_mode == GM_EDITOR) { if (_game_mode == GM_EDITOR) {
/* Show error if no town exists at all */ /* Show error if no town exists at all */
@ -284,7 +285,7 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
_current_player = OWNER_NONE; _current_player = OWNER_NONE;
_generating_world = true; _generating_world = true;
_ignore_restrictions = 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) { if (!success) {
SetDParam(0, indsp->name); SetDParam(0, indsp->name);
ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y); ShowErrorMessage(_error_message, STR_0285_CAN_T_BUILD_HERE, e->we.place.pt.x, e->we.place.pt.y);
@ -293,7 +294,7 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e)
_ignore_restrictions = false; _ignore_restrictions = false;
_generating_world = false; _generating_world = false;
} else { } 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 */ /* If an industry has been built, just reset the cursor and the system */

View File

@ -25,6 +25,8 @@
#include "table/strings.h" #include "table/strings.h"
static Randomizer _industry_creation_randomizer;
/* Since the industry IDs defined by the GRF file don't necessarily correlate /* 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 * to those used by the game, the IDs used for overriding old industries must be
* translated when the idustry spec is set. */ * translated when the idustry spec is set. */
@ -466,15 +468,15 @@ uint32 IndustryLocationGetVariable(const ResolverObject *object, byte variable,
/* Square of Euclidian distance from town */ /* Square of Euclidian distance from town */
case 0x8D: return min(DistanceSquare(industry->town->xy, tile), 65535); 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 */ /* 32 random bits */
// case 0x8F: return Random(); case 0x8F: return _industry_creation_randomizer.Next();
} }
/* None of the special ones, so try the general ones */ /* None of the special ones, so try the general ones */
return IndustryGetVariable(object, variable, parameter, available); 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); const IndustrySpec *indspec = GetIndustrySpec(type);
@ -492,6 +494,7 @@ bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspe
NewIndustryResolver(&object, tile, &ind, type); NewIndustryResolver(&object, tile, &ind, type);
object.GetVariable = IndustryLocationGetVariable; object.GetVariable = IndustryLocationGetVariable;
object.callback = CBID_INDUSTRY_LOCATION; object.callback = CBID_INDUSTRY_LOCATION;
_industry_creation_randomizer.SetSeed(seed);
group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object); group = Resolve(GetIndustrySpec(type)->grf_prop.spritegroup, &object);

View File

@ -30,7 +30,7 @@ uint32 IndustryGetVariable(const ResolverObject *object, byte variable, byte par
uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile); uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, Industry *industry, IndustryType type, TileIndex tile);
uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i); uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i);
void IndustryProductionCallback(Industry *ind, int reason); 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); bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type);
IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id); IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id);