* Build/Fund an industry * @param flags of operations to conduct * @param tile tile where industry is built * @param it industry type see build_industry.h and see industry.h * @param first_layout first layout to try * @param fund false = prospect, true = fund (only valid if current company is DEITY) * @param seed seed to use for desyncfree randomisations * @return the cost of this operation
| 2062 | * @return the cost of this operation or an error |
| 2063 | */ |
| 2064 | CommandCost CmdBuildIndustry(DoCommandFlags flags, TileIndex tile, IndustryType it, uint32_t first_layout, bool fund, uint32_t seed) |
| 2065 | { |
| 2066 | if (it >= NUM_INDUSTRYTYPES) return CMD_ERROR; |
| 2067 | |
| 2068 | const IndustrySpec *indspec = GetIndustrySpec(it); |
| 2069 | |
| 2070 | /* Check if the to-be built/founded industry is available for this climate. */ |
| 2071 | if (!indspec->enabled || indspec->layouts.empty()) return CMD_ERROR; |
| 2072 | |
| 2073 | /* If the setting for raw-material industries is not on, you cannot build raw-material industries. |
| 2074 | * Raw material industries are industries that do not accept cargo (at least for now) */ |
| 2075 | if (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 0 && indspec->IsRawIndustry()) { |
| 2076 | return CMD_ERROR; |
| 2077 | } |
| 2078 | |
| 2079 | if (_game_mode != GM_EDITOR && GetIndustryProbabilityCallback(it, _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_USERCREATION, 1) == 0) { |
| 2080 | return CMD_ERROR; |
| 2081 | } |
| 2082 | |
| 2083 | Randomizer randomizer; |
| 2084 | randomizer.SetSeed(seed); |
| 2085 | uint16_t random_initial_bits = GB(seed, 0, 16); |
| 2086 | uint32_t random_var8f = randomizer.Next(); |
| 2087 | size_t num_layouts = indspec->layouts.size(); |
| 2088 | CommandCost ret = CommandCost(STR_ERROR_SITE_UNSUITABLE); |
| 2089 | const bool deity_prospect = _current_company == OWNER_DEITY && !fund; |
| 2090 | |
| 2091 | Industry *ind = nullptr; |
| 2092 | if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) { |
| 2093 | if (flags.Test(DoCommandFlag::Execute)) { |
| 2094 | /* Prospecting has a chance to fail, however we cannot guarantee that something can |
| 2095 | * be built on the map, so the chance gets lower when the map is fuller, but there |
| 2096 | * is nothing we can really do about that. */ |
| 2097 | bool prospect_success = deity_prospect || Random() <= indspec->prospecting_chance; |
| 2098 | if (prospect_success) { |
| 2099 | /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */ |
| 2100 | IndustryAvailabilityCallType calltype = _current_company == OWNER_DEITY ? IACT_RANDOMCREATION : IACT_PROSPECTCREATION; |
| 2101 | Backup<CompanyID> cur_company(_current_company, OWNER_TOWN); |
| 2102 | for (int i = 0; i < 5000; i++) { |
| 2103 | /* We should not have more than one Random() in a function call |
| 2104 | * because parameter evaluation order is not guaranteed in the c++ standard |
| 2105 | */ |
| 2106 | tile = RandomTile(); |
| 2107 | /* Start with a random layout */ |
| 2108 | size_t layout = RandomRange((uint32_t)num_layouts); |
| 2109 | /* Check now each layout, starting with the random one */ |
| 2110 | for (size_t j = 0; j < num_layouts; j++) { |
| 2111 | layout = (layout + 1) % num_layouts; |
| 2112 | ret = CreateNewIndustryHelper(tile, it, flags, indspec, layout, random_var8f, random_initial_bits, cur_company.GetOriginalValue(), calltype, &ind); |
| 2113 | if (ret.Succeeded()) break; |
| 2114 | } |
| 2115 | if (ret.Succeeded()) break; |
| 2116 | } |
| 2117 | cur_company.Restore(); |
| 2118 | } |
| 2119 | if (ret.Failed() && IsLocalCompany()) { |
| 2120 | if (prospect_success) { |
| 2121 | ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_PROSPECT_INDUSTRY), GetEncodedString(STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING), WL_INFO); |
nothing calls this directly
no test coverage detected