# HG changeset patch # User frosch # Date 2010-11-21 17:42:18 # Node ID 27c24a3260350f94ee75d3680de17cdfdf94bd24 # Parent b9e4f67cdda1c3bef7f67f4e7f76d12b0e61565a (svn r21289) -Fix [FS#4133]: Make terraforming and tunnel-excavation handle DC_AUTO-clearable multitile objects. diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -17,6 +17,7 @@ #include "functions.h" #include "economy_func.h" #include "genworld.h" +#include "object_base.h" #include "table/strings.h" @@ -275,8 +276,10 @@ CommandCost CmdTerraformLand(TileIndex t total_cost.AddCost(cost); } - /* Check if the terraforming is valid wrt. tunnels, bridges and objects on the surface */ - { + /* Check if the terraforming is valid wrt. tunnels, bridges and objects on the surface + * Pass == 0: Collect tileareas which are caused to be auto-cleared. + * Pass == 1: Collect the actual cost. */ + for (int pass = 0; pass < 2; pass++) { TileIndex *ti = ts.tile_table; for (int count = ts.tile_table_count; count != 0; count--, ti++) { @@ -315,16 +318,31 @@ CommandCost CmdTerraformLand(TileIndex t _terraform_err_tile = tile; // highlight the tile above the tunnel return_cmd_error(STR_ERROR_EXCAVATION_WOULD_DAMAGE); } + + /* Is the tile already cleared? */ + const ClearedObjectArea *coa = FindClearedObject(tile); + bool indirectly_cleared = coa != NULL && coa->first_tile != tile; + /* Check tiletype-specific things, and add extra-cost */ const bool curr_gen = _generating_world; if (_game_mode == GM_EDITOR) _generating_world = true; // used to create green terraformed land - CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags | DC_AUTO | DC_FORCE_CLEAR_TILE, z_min * TILE_HEIGHT, tileh); + DoCommandFlag tile_flags = flags | DC_AUTO | DC_FORCE_CLEAR_TILE; + if (pass == 0) { + tile_flags &= ~DC_EXEC; + tile_flags |= DC_NO_MODIFY_TOWN_RATING; + } + CommandCost cost; + if (indirectly_cleared) { + cost = DoCommand(tile, 0, 0, tile_flags, CMD_LANDSCAPE_CLEAR); + } else { + cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, tile_flags, z_min * TILE_HEIGHT, tileh); + } _generating_world = curr_gen; if (cost.Failed()) { _terraform_err_tile = tile; return cost; } - total_cost.AddCost(cost); + if (pass == 1) total_cost.AddCost(cost); } } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -38,6 +38,7 @@ #include "pbs.h" #include "company_base.h" #include "newgrf_railtype.h" +#include "object_base.h" #include "table/sprites.h" #include "table/strings.h" @@ -583,23 +584,31 @@ CommandCost CmdBuildTunnel(TileIndex sta if (IsWaterTile(end_tile)) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER); + /* Clear the tile in any case */ + ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND); + cost.AddCost(ret); + /* slope of end tile must be complementary to the slope of the start tile */ if (end_tileh != ComplementSlope(start_tileh)) { - /* Check if there is a structure on the terraformed tile. Do not add the cost, that will be done by the terraforming - * Note: Currently the town rating is also affected by this clearing-test. So effectivly the player is punished twice for clearing - * the tree on end_tile. - */ - ret = DoCommand(end_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR); + /* Mark the tile as already cleared for the terraform command. + * Do this for all tiles (like trees), not only objects. */ + ClearedObjectArea *coa = FindClearedObject(end_tile); + if (coa == NULL) { + coa = _cleared_object_areas.Append(); + coa->first_tile = end_tile; + coa->area = TileArea(end_tile, 1, 1); + } + + /* Hide the tile from the terraforming command */ + TileIndex old_first_tile = coa->first_tile; + coa->first_tile = INVALID_TILE; + ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); + coa->first_tile = old_first_tile; if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND); - - ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); - if (ret.Failed()) return_cmd_error(STR_ERROR_UNABLE_TO_EXCAVATE_LAND); - } else { - ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); - if (ret.Failed()) return ret; + cost.AddCost(ret); } cost.AddCost(_price[PR_BUILD_TUNNEL]); - cost.AddCost(ret); /* Pay for the rail/road in the tunnel including entrances */ switch (transport_type) {