From 1629699094b6dd708c7c379f3bb03000fad549e3 Mon Sep 17 00:00:00 2001 From: rubidium Date: Tue, 29 Jan 2008 00:36:55 +0000 Subject: [PATCH] (svn r12006) -Fix: implement FS#1697 without the nasty side effects as specified in FS#1712. --- src/industry_cmd.cpp | 24 +++++++++++++----------- src/industry_gui.cpp | 7 ++++--- src/newgrf_industries.cpp | 9 ++++++--- src/newgrf_industries.h | 2 +- 4 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 0532a16040..6b46b7be0b 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1548,9 +1548,10 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind * @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 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint 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 @@ static Industry *CreateNewIndustryHelper(TileIndex tile, IndustryType type, uint /** 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 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) * 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 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) } 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 @@ CommandCost CmdBuildIndustry(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) 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 @@ Industry *CreateNewIndustry(TileIndex tile, IndustryType 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 { diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 0d06451510..23cef6229b 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -253,7 +253,7 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e) _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 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e) 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 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e) _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 @@ static void BuildDynamicIndustryWndProc(Window *w, WindowEvent *e) _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 */ diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index dd995263f7..8eb6eb951d 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -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 @@ uint32 IndustryLocationGetVariable(const ResolverObject *object, byte variable, /* 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 @@ bool CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint itspe 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); diff --git a/src/newgrf_industries.h b/src/newgrf_industries.h index e98c037b43..9d532fa583 100644 --- a/src/newgrf_industries.h +++ b/src/newgrf_industries.h @@ -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); 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);