diff --git a/src/ai/api/ai_industrytype.cpp b/src/ai/api/ai_industrytype.cpp index 121a7756f7e7..bd28df2899b2 100644 --- a/src/ai/api/ai_industrytype.cpp +++ b/src/ai/api/ai_industrytype.cpp @@ -91,7 +91,7 @@ { if (!IsValidIndustryType(industry_type)) return false; - if (!::CheckIfCallBackAllowsAvailability(industry_type, IACT_USERCREATION)) return false; + if (::GetIndustryProbabilityCallback(industry_type, IACT_USERCREATION, 1) == 0) return false; if (!::GetIndustrySpec(industry_type)->IsRawIndustry()) return true; /* raw_industry_construction == 1 means "Build as other industries" */ @@ -103,7 +103,7 @@ if (!IsValidIndustryType(industry_type)) return false; if (!::GetIndustrySpec(industry_type)->IsRawIndustry()) return false; - if (!::CheckIfCallBackAllowsAvailability(industry_type, IACT_USERCREATION)) return false; + if (::GetIndustryProbabilityCallback(industry_type, IACT_USERCREATION, 1) == 0) return false; /* raw_industry_construction == 2 means "prospect" */ return _settings_game.construction.raw_industry_construction == 2; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 5309135f143a..c7ed3f7a65fe 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -1777,7 +1777,7 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin return CMD_ERROR; } - if (_game_mode != GM_EDITOR && !CheckIfCallBackAllowsAvailability(it, IACT_USERCREATION)) { + if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, IACT_USERCREATION, 1) == 0) { return CMD_ERROR; } @@ -1876,9 +1876,9 @@ static uint32 GetScaledIndustryGenerationProbability(IndustryType it, bool *forc { const IndustrySpec *ind_spc = GetIndustrySpec(it); uint32 chance = ind_spc->appear_creation[_settings_game.game_creation.landscape] * 16; // * 16 to increase precision - if (!ind_spc->enabled || chance == 0 || ind_spc->num_table == 0 || - !CheckIfCallBackAllowsAvailability(it, IACT_MAPGENERATION) || - (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY)) { + if (!ind_spc->enabled || ind_spc->num_table == 0 || + (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) || + (chance = GetIndustryProbabilityCallback(it, IACT_MAPGENERATION, chance)) == 0) { *force_at_least_one = false; return 0; } else { @@ -1906,10 +1906,10 @@ static uint16 GetIndustryGamePlayProbability(IndustryType it, byte *min_number) const IndustrySpec *ind_spc = GetIndustrySpec(it); byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape]; - if (!ind_spc->enabled || chance == 0 || ind_spc->num_table == 0 || + if (!ind_spc->enabled || ind_spc->num_table == 0 || ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) || ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) || - !CheckIfCallBackAllowsAvailability(it, IACT_RANDOMCREATION)) { + (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) { *min_number = 0; return 0; } diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 1ea3967fd4e4..9c2e825f6f24 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -209,7 +209,7 @@ class BuildIndustryWindow : public Window { bool timer_enabled; ///< timer can be used uint16 count; ///< How many industries are loaded IndustryType index[NUM_INDUSTRYTYPES + 1]; ///< Type of industry, in the order it was loaded - bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_AVAILABLE (if ever) + bool enabled[NUM_INDUSTRYTYPES + 1]; ///< availability state, coming from CBID_INDUSTRY_PROBABILITY (if ever) Scrollbar *vscroll; /** The offset for the text in the matrix. */ @@ -247,7 +247,7 @@ class BuildIndustryWindow : public Window { continue; } this->index[this->count] = ind; - this->enabled[this->count] = (_game_mode == GM_EDITOR) || CheckIfCallBackAllowsAvailability(ind, IACT_USERCREATION); + this->enabled[this->count] = (_game_mode == GM_EDITOR) || GetIndustryProbabilityCallback(ind, IACT_USERCREATION, 1) > 0; /* Keep the selection to the correct line */ if (this->selected_type == ind) this->selected_index = this->count; this->count++; @@ -582,7 +582,7 @@ class BuildIndustryWindow : public Window { const IndustrySpec *indsp = GetIndustrySpec(this->selected_type); if (indsp->enabled) { - bool call_back_result = CheckIfCallBackAllowsAvailability(this->selected_type, IACT_USERCREATION); + bool call_back_result = GetIndustryProbabilityCallback(this->selected_type, IACT_USERCREATION, 1) > 0; /* Only if result does match the previous state would it require a redraw. */ if (call_back_result != this->enabled[this->selected_index]) { diff --git a/src/newgrf_callbacks.h b/src/newgrf_callbacks.h index cce00151fbe8..1cc608121235 100644 --- a/src/newgrf_callbacks.h +++ b/src/newgrf_callbacks.h @@ -85,8 +85,8 @@ enum CallbackID { /** Called periodically to determine if a house should be destroyed. */ CBID_HOUSE_DESTRUCTION = 0x21, // 8 bit callback - /** Called to determine if the given industry type is available */ - CBID_INDUSTRY_AVAILABLE = 0x22, // 15 bit callback + /** Called to determine if the given industry type is available. For grf version >= 8 also a probability can be returned. */ + CBID_INDUSTRY_PROBABILITY = 0x22, // 15 bit callback /** * This callback is called from vehicle purchase lists. It returns a value to be @@ -341,7 +341,7 @@ enum CargoCallbackMask { * Callback masks for Industries */ enum IndustryCallbackMask { - CBM_IND_AVAILABLE = 0, ///< industry availability callback + CBM_IND_PROBABILITY = 0, ///< industry availability/probability callback CBM_IND_PRODUCTION_CARGO_ARRIVAL = 1, ///< call production callback when cargo arrives at the industry CBM_IND_PRODUCTION_256_TICKS = 2, ///< call production callback every 256 ticks CBM_IND_LOCATION = 3, ///< check industry construction on given area diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 389bcebfb727..2f469dc71a39 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -550,22 +550,32 @@ CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uin } /** - * Check with callback #CBM_IND_AVAILABLE whether the industry can be built. + * Check with callback #CBID_INDUSTRY_PROBABILITY whether the industry can be built. * @param type Industry type to check. * @param creation_type Reason to construct a new industry. * @return If the industry has no callback or allows building, \c true is returned. Otherwise, \c false is returned. */ -bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type) +uint32 GetIndustryProbabilityCallback(IndustryType type, IndustryAvailabilityCallType creation_type, uint32 default_prob) { const IndustrySpec *indspec = GetIndustrySpec(type); - if (HasBit(indspec->callback_mask, CBM_IND_AVAILABLE)) { - uint16 res = GetIndustryCallback(CBID_INDUSTRY_AVAILABLE, 0, creation_type, NULL, type, INVALID_TILE); + if (HasBit(indspec->callback_mask, CBM_IND_PROBABILITY)) { + uint16 res = GetIndustryCallback(CBID_INDUSTRY_PROBABILITY, 0, creation_type, NULL, type, INVALID_TILE); if (res != CALLBACK_FAILED) { - return (res == 0); + if (indspec->grf_prop.grffile->grf_version < 8) { + /* Disallow if result != 0 */ + if (res != 0) default_prob = 0; + } else { + /* Use returned probability. 0x100 to use default */ + if (res < 0x100) { + default_prob = res; + } else if (res > 0x100) { + ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_PROBABILITY, res); + } + } } } - return true; + return default_prob; } static int32 DerefIndProd(int field, bool use_register) diff --git a/src/newgrf_industries.h b/src/newgrf_industries.h index 91a0fe9638f4..4132e51e954a 100644 --- a/src/newgrf_industries.h +++ b/src/newgrf_industries.h @@ -26,7 +26,7 @@ enum IndustryTrigger { INDUSTRY_TRIGGER_CARGO_DELIVERY = 4, }; -/** From where is callback CBID_INDUSTRY_AVAILABLE been called */ +/** From where is callback CBID_INDUSTRY_PROBABILITY been called */ enum IndustryAvailabilityCallType { IACT_MAPGENERATION, ///< during random map generation IACT_RANDOMCREATION, ///< during creation of random ingame industry @@ -40,7 +40,7 @@ uint16 GetIndustryCallback(CallbackID callback, uint32 param1, uint32 param2, In uint32 GetIndustryIDAtOffset(TileIndex new_tile, const Industry *i, uint32 cur_grfid); void IndustryProductionCallback(Industry *ind, int reason); CommandCost CheckIfCallBackAllowsCreation(TileIndex tile, IndustryType type, uint layout, uint32 seed, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type); -bool CheckIfCallBackAllowsAvailability(IndustryType type, IndustryAvailabilityCallType creation_type); +uint32 GetIndustryProbabilityCallback(IndustryType type, IndustryAvailabilityCallType creation_type, uint32 default_prob); bool IndustryTemporarilyRefusesCargo(Industry *ind, CargoID cargo_type); IndustryType MapNewGRFIndustryType(IndustryType grf_type, uint32 grf_id); diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index e24a183c828f..a07ccc006e82 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -253,7 +253,7 @@ static const NIProperty _nip_industries[] = { #define NICI(cb_id, bit) NIC(cb_id, IndustrySpec, callback_mask, bit) static const NICallback _nic_industries[] = { - NICI(CBID_INDUSTRY_AVAILABLE, CBM_IND_AVAILABLE), + NICI(CBID_INDUSTRY_PROBABILITY, CBM_IND_PROBABILITY), NICI(CBID_INDUSTRY_LOCATION, CBM_IND_LOCATION), NICI(CBID_INDUSTRY_PRODUCTION_CHANGE, CBM_IND_PRODUCTION_CHANGE), NICI(CBID_INDUSTRY_MONTHLYPROD_CHANGE, CBM_IND_MONTHLYPROD_CHANGE),