Codechange: When checking industry placement conditions, perform cheap checks first. (#9987)

1. Built-in checks on industry level.
2. Built-in checks on industry tiles.
3. NewGRF-defined checks on industry level.
4. NewGRF-defined checks on industry tiles.
pull/428/head
frosch 2 years ago committed by GitHub
parent 2fe8a257ac
commit 9529703cab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1429,18 +1429,12 @@ bool IsSlopeRefused(Slope current, Slope refused)
* Are the tiles of the industry free?
* @param tile Position to check.
* @param layout Industry tiles table.
* @param layout_index The index of the layout to build/fund
* @param type Type of the industry.
* @param initial_random_bits The random bits the industry is going to have after construction.
* @param founder Industry founder
* @param creation_type The circumstances the industry is created under.
* @param[out] custom_shape_check Perform custom check for the site.
* @return Failed or succeeded command.
*/
static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTileLayout &layout, IndustryType type)
{
bool refused_slope = false;
bool custom_shape = false;
IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
for (const IndustryTileLayoutTile &it : layout) {
IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
@ -1462,20 +1456,9 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
/* Perform land/water check if not disabled */
if (!HasBit(its->slopes_refused, 5) && ((HasTileWaterClass(cur_tile) && IsTileOnWater(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
custom_shape = true;
CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
if (ret.Failed()) return ret;
} else {
Slope tileh = GetTileSlope(cur_tile);
refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
}
if ((ind_behav & (INDUSTRYBEH_ONLY_INTOWN | INDUSTRYBEH_TOWN1200_MORE)) || // Tile must be a house
((ind_behav & INDUSTRYBEH_ONLY_NEARTOWN) && IsTileType(cur_tile, MP_HOUSE))) { // Tile is allowed to be a house (and it is a house)
if (!IsTileType(cur_tile, MP_HOUSE)) {
@ -1491,8 +1474,46 @@ static CommandCost CheckIfIndustryTilesAreFree(TileIndex tile, const IndustryTil
} else {
/* Clear the tiles, but do not affect town ratings */
CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_TEST_TOWN_RATING | DC_NO_MODIFY_TOWN_RATING, cur_tile);
if (ret.Failed()) return ret;
}
}
}
return CommandCost();
}
/**
* Check slope requirements for industry tiles.
* @param tile Position to check.
* @param layout Industry tiles table.
* @param layout_index The index of the layout to build/fund
* @param type Type of the industry.
* @param initial_random_bits The random bits the industry is going to have after construction.
* @param founder Industry founder
* @param creation_type The circumstances the industry is created under.
* @param[out] custom_shape_check Perform custom check for the site.
* @return Failed or succeeded command.
*/
static CommandCost CheckIfIndustryTileSlopes(TileIndex tile, const IndustryTileLayout &layout, size_t layout_index, int type, uint16 initial_random_bits, Owner founder, IndustryAvailabilityCallType creation_type, bool *custom_shape_check = nullptr)
{
bool refused_slope = false;
bool custom_shape = false;
for (const IndustryTileLayoutTile &it : layout) {
IndustryGfx gfx = GetTranslatedIndustryTileID(it.gfx);
TileIndex cur_tile = TileAddWrap(tile, it.ti.x, it.ti.y);
assert(IsValidTile(cur_tile)); // checked before in CheckIfIndustryTilesAreFree
if (gfx != GFX_WATERTILE_SPECIALCHECK) {
const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
if (HasBit(its->callback_mask, CBM_INDT_SHAPE_CHECK)) {
custom_shape = true;
CommandCost ret = PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, layout_index, initial_random_bits, founder, creation_type);
if (ret.Failed()) return ret;
} else {
Slope tileh = GetTileSlope(cur_tile);
refused_slope |= IsSlopeRefused(tileh, its->slopes_refused);
}
}
}
@ -1929,15 +1950,28 @@ static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, Do
{
assert(layout_index < indspec->layouts.size());
const IndustryTileLayout &layout = indspec->layouts[layout_index];
bool custom_shape_check = false;
*ip = nullptr;
/* 1. Cheap: Built-in checks on industry level. */
CommandCost ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
if (ret.Failed()) return ret;
Town *t = nullptr;
ret = FindTownForIndustry(tile, type, &t);
if (ret.Failed()) return ret;
assert(t != nullptr);
ret = CheckIfIndustryIsAllowed(tile, type, t);
if (ret.Failed()) return ret;
/* 2. Built-in checks on industry tiles. */
std::vector<ClearedObjectArea> object_areas(_cleared_object_areas);
CommandCost ret = CheckIfIndustryTilesAreFree(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
ret = CheckIfIndustryTilesAreFree(tile, layout, type);
_cleared_object_areas = object_areas;
if (ret.Failed()) return ret;
/* 3. NewGRF-defined checks on industry level. */
if (HasBit(GetIndustrySpec(type)->callback_mask, CBM_IND_LOCATION)) {
ret = CheckIfCallBackAllowsCreation(tile, type, layout_index, random_var8f, random_initial_bits, founder, creation_type);
} else {
@ -1945,22 +1979,16 @@ static CommandCost CreateNewIndustryHelper(TileIndex tile, IndustryType type, Do
}
if (ret.Failed()) return ret;
/* 4. Expensive: NewGRF-defined checks on industry tiles. */
bool custom_shape_check = false;
ret = CheckIfIndustryTileSlopes(tile, layout, layout_index, type, random_initial_bits, founder, creation_type, &custom_shape_check);
if (ret.Failed()) return ret;
if (!custom_shape_check && _settings_game.game_creation.land_generator == LG_TERRAGENESIS && _generating_world &&
!_ignore_restrictions && !CheckIfCanLevelIndustryPlatform(tile, DC_NO_WATER, layout, type)) {
return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
}
ret = CheckIfFarEnoughFromConflictingIndustry(tile, type);
if (ret.Failed()) return ret;
Town *t = nullptr;
ret = FindTownForIndustry(tile, type, &t);
if (ret.Failed()) return ret;
assert(t != nullptr);
ret = CheckIfIndustryIsAllowed(tile, type, t);
if (ret.Failed()) return ret;
if (!Industry::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_INDUSTRIES);
if (flags & DC_EXEC) {

Loading…
Cancel
Save