diff options
Diffstat (limited to 'src/terraform_cmd.cpp')
-rw-r--r-- | src/terraform_cmd.cpp | 76 |
1 files changed, 34 insertions, 42 deletions
diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index e1f794412..21df5ccbe 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -38,8 +38,6 @@ struct TerraformerState { TileIndexToHeightMap tile_to_new_height; ///< The tiles for which the height has changed. }; -TileIndex _terraform_err_tile; ///< first tile we couldn't terraform - /** * Gets the TileHeight (height of north corner) of a tile as of current terraforming progress. * @@ -101,20 +99,20 @@ static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile) * @param height Aimed height. * @return Error code or cost. */ -static CommandCost TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height) +static std::tuple<CommandCost, TileIndex> TerraformTileHeight(TerraformerState *ts, TileIndex tile, int height) { assert(tile < MapSize()); /* Check range of destination height */ - if (height < 0) return_cmd_error(STR_ERROR_ALREADY_AT_SEA_LEVEL); - if (height > _settings_game.construction.map_height_limit) return_cmd_error(STR_ERROR_TOO_HIGH); + if (height < 0) return { CommandCost(STR_ERROR_ALREADY_AT_SEA_LEVEL), INVALID_TILE }; + if (height > _settings_game.construction.map_height_limit) return { CommandCost(STR_ERROR_TOO_HIGH), INVALID_TILE }; /* * Check if the terraforming has any effect. * This can only be true, if multiple corners of the start-tile are terraformed (i.e. the terraforming is done by towns/industries etc.). * In this case the terraforming should fail. (Don't know why.) */ - if (height == TerraformGetHeightOfTile(ts, tile)) return CMD_ERROR; + if (height == TerraformGetHeightOfTile(ts, tile)) return { CMD_ERROR, INVALID_TILE }; /* Check "too close to edge of map". Only possible when freeform-edges is off. */ uint x = TileX(tile); @@ -125,8 +123,7 @@ static CommandCost TerraformTileHeight(TerraformerState *ts, TileIndex tile, int */ if (x == 1) x = 0; if (y == 1) y = 0; - _terraform_err_tile = TileXY(x, y); - return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP); + return { CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP), TileXY(x, y) }; } /* Mark incident tiles that are involved in the terraforming. */ @@ -168,14 +165,14 @@ static CommandCost TerraformTileHeight(TerraformerState *ts, TileIndex tile, int if (abs(height_diff) > 1) { /* Terraform the neighboured corner. The resulting height difference should be 1. */ height_diff += (height_diff < 0 ? 1 : -1); - CommandCost cost = TerraformTileHeight(ts, tile, r + height_diff); - if (cost.Failed()) return cost; + auto [cost, err_tile] = TerraformTileHeight(ts, tile, r + height_diff); + if (cost.Failed()) return { cost, err_tile }; total_cost.AddCost(cost); } } } - return total_cost; + return { total_cost, INVALID_TILE }; } /** @@ -186,10 +183,8 @@ static CommandCost TerraformTileHeight(TerraformerState *ts, TileIndex tile, int * @param dir_up direction; eg up (true) or down (false) * @return the cost of this operation or an error */ -CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, bool dir_up) +std::tuple<CommandCost, Money, TileIndex> CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, bool dir_up) { - _terraform_err_tile = INVALID_TILE; - CommandCost total_cost(EXPENSES_CONSTRUCTION); int direction = (dir_up ? 1 : -1); TerraformerState ts; @@ -197,29 +192,29 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b /* Compute the costs and the terraforming result in a model of the landscape */ if ((slope & SLOPE_W) != 0 && tile + TileDiffXY(1, 0) < MapSize()) { TileIndex t = tile + TileDiffXY(1, 0); - CommandCost cost = TerraformTileHeight(&ts, t, TileHeight(t) + direction); - if (cost.Failed()) return cost; + auto [cost, err_tile] = TerraformTileHeight(&ts, t, TileHeight(t) + direction); + if (cost.Failed()) return { cost, 0, err_tile }; total_cost.AddCost(cost); } if ((slope & SLOPE_S) != 0 && tile + TileDiffXY(1, 1) < MapSize()) { TileIndex t = tile + TileDiffXY(1, 1); - CommandCost cost = TerraformTileHeight(&ts, t, TileHeight(t) + direction); - if (cost.Failed()) return cost; + auto [cost, err_tile] = TerraformTileHeight(&ts, t, TileHeight(t) + direction); + if (cost.Failed()) return { cost, 0, err_tile }; total_cost.AddCost(cost); } if ((slope & SLOPE_E) != 0 && tile + TileDiffXY(0, 1) < MapSize()) { TileIndex t = tile + TileDiffXY(0, 1); - CommandCost cost = TerraformTileHeight(&ts, t, TileHeight(t) + direction); - if (cost.Failed()) return cost; + auto [cost, err_tile] = TerraformTileHeight(&ts, t, TileHeight(t) + direction); + if (cost.Failed()) return { cost, 0, err_tile }; total_cost.AddCost(cost); } if ((slope & SLOPE_N) != 0) { TileIndex t = tile + TileDiffXY(0, 0); - CommandCost cost = TerraformTileHeight(&ts, t, TileHeight(t) + direction); - if (cost.Failed()) return cost; + auto [cost, err_tile] = TerraformTileHeight(&ts, t, TileHeight(t) + direction); + if (cost.Failed()) return { cost, 0, err_tile }; total_cost.AddCost(cost); } @@ -259,20 +254,17 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b /* Check if bridge would take damage. */ if (direction == 1 && bridge_height <= z_max) { - _terraform_err_tile = t; // highlight the tile under the bridge - return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); + return { CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST), 0, t }; // highlight the tile under the bridge } /* Is the bridge above not too high afterwards? */ if (direction == -1 && bridge_height > (z_min + _settings_game.construction.max_bridge_height)) { - _terraform_err_tile = t; - return_cmd_error(STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND); + return { CommandCost(STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND), 0, t }; } } /* Check if tunnel would take damage */ if (direction == -1 && IsTunnelInWay(t, z_min)) { - _terraform_err_tile = t; // highlight the tile above the tunnel - return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE); + return { CommandCost(STR_ERROR_EXCAVATION_WOULD_DAMAGE), 0, t }; // highlight the tile above the tunnel } } @@ -296,8 +288,7 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b } old_generating_world.Restore(); if (cost.Failed()) { - _terraform_err_tile = t; - return cost; + return { cost, 0, t }; } if (pass == 1) total_cost.AddCost(cost); } @@ -305,7 +296,7 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b Company *c = Company::GetIfValid(_current_company); if (c != nullptr && GB(c->terraform_limit, 16, 16) < ts.tile_to_new_height.size()) { - return_cmd_error(STR_ERROR_TERRAFORM_LIMIT_REACHED); + return { CommandCost(STR_ERROR_TERRAFORM_LIMIT_REACHED), 0, INVALID_TILE }; } if (flags & DC_EXEC) { @@ -328,7 +319,7 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b if (c != nullptr) c->terraform_limit -= (uint32)ts.tile_to_new_height.size() << 16; } - return total_cost; + return { total_cost, 0, total_cost.Succeeded() ? tile : INVALID_TILE }; } @@ -341,11 +332,9 @@ CommandCost CmdTerraformLand(DoCommandFlag flags, TileIndex tile, Slope slope, b * @param LevelMode Mode of leveling \c LevelMode. * @return the cost of this operation or an error */ -std::tuple<CommandCost, Money> CmdLevelLand(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal, LevelMode lm) +std::tuple<CommandCost, Money, TileIndex> CmdLevelLand(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, bool diagonal, LevelMode lm) { - if (start_tile >= MapSize()) return { CMD_ERROR, 0 }; - - _terraform_err_tile = INVALID_TILE; + if (start_tile >= MapSize()) return { CMD_ERROR, 0, INVALID_TILE }; /* remember level height */ uint oldh = TileHeight(start_tile); @@ -356,11 +345,11 @@ std::tuple<CommandCost, Money> CmdLevelLand(DoCommandFlag flags, TileIndex tile, case LM_LEVEL: break; case LM_RAISE: h++; break; case LM_LOWER: h--; break; - default: return { CMD_ERROR, 0 }; + default: return { CMD_ERROR, 0, INVALID_TILE }; } /* Check range of destination height */ - if (h > _settings_game.construction.map_height_limit) return { CommandCost(oldh == 0 ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH), 0 }; + if (h > _settings_game.construction.map_height_limit) return { CommandCost(oldh == 0 ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH), 0, INVALID_TILE }; Money money = GetAvailableMoneyForCommand(); CommandCost cost(EXPENSES_CONSTRUCTION); @@ -369,14 +358,16 @@ std::tuple<CommandCost, Money> CmdLevelLand(DoCommandFlag flags, TileIndex tile, const Company *c = Company::GetIfValid(_current_company); int limit = (c == nullptr ? INT32_MAX : GB(c->terraform_limit, 16, 16)); - if (limit == 0) return { CommandCost(STR_ERROR_TERRAFORM_LIMIT_REACHED), 0 }; + if (limit == 0) return { CommandCost(STR_ERROR_TERRAFORM_LIMIT_REACHED), 0, INVALID_TILE }; + TileIndex error_tile = INVALID_TILE; TileIterator *iter = diagonal ? (TileIterator *)new DiagonalTileIterator(tile, start_tile) : new OrthogonalTileIterator(tile, start_tile); for (; *iter != INVALID_TILE; ++(*iter)) { TileIndex t = *iter; uint curh = TileHeight(t); while (curh != h) { - CommandCost ret = Command<CMD_TERRAFORM_LAND>::Do(flags & ~DC_EXEC, t, SLOPE_N, curh <= h); + CommandCost ret; + std::tie(ret, std::ignore, error_tile) = Command<CMD_TERRAFORM_LAND>::Do(flags & ~DC_EXEC, t, SLOPE_N, curh <= h); if (ret.Failed()) { last_error = ret; @@ -389,7 +380,7 @@ std::tuple<CommandCost, Money> CmdLevelLand(DoCommandFlag flags, TileIndex tile, money -= ret.GetCost(); if (money < 0) { delete iter; - return { cost, ret.GetCost() }; + return { cost, ret.GetCost(), error_tile }; } Command<CMD_TERRAFORM_LAND>::Do(flags, t, SLOPE_N, curh <= h); } else { @@ -413,5 +404,6 @@ std::tuple<CommandCost, Money> CmdLevelLand(DoCommandFlag flags, TileIndex tile, } delete iter; - return { had_success ? cost : last_error, 0 }; + CommandCost cc_ret = had_success ? cost : last_error; + return { cc_ret, 0, cc_ret.Succeeded() ? tile : error_tile }; } |