src/clear_cmd.cpp
changeset 7494 ab05bad37410
parent 7487 0a3ff8c6ed75
child 7509 23372ed624e8
equal deleted inserted replaced
7493:07944c9e005f 7494:ab05bad37410
    31 	TileIndex tile;   ///< Referenced tile.
    31 	TileIndex tile;   ///< Referenced tile.
    32 	byte height;      ///< New TileHeight (height of north corner) of the tile.
    32 	byte height;      ///< New TileHeight (height of north corner) of the tile.
    33 };
    33 };
    34 
    34 
    35 struct TerraformerState {
    35 struct TerraformerState {
    36 	uint32 flags;
       
    37 
       
    38 	int direction;
       
    39 	int modheight_count;                                         ///< amount of entries in "modheight".
    36 	int modheight_count;                                         ///< amount of entries in "modheight".
    40 	int tile_table_count;                                        ///< amount of entries in "tile_table".
    37 	int tile_table_count;                                        ///< amount of entries in "tile_table".
    41 
    38 
    42 	CommandCost cost;
    39 	CommandCost cost;
    43 
    40 
    97 {
    94 {
    98 	TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
    95 	TerraformAddDirtyTile(ts, tile + TileDiffXY( 0, -1));
    99 	TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
    96 	TerraformAddDirtyTile(ts, tile + TileDiffXY(-1, -1));
   100 	TerraformAddDirtyTile(ts, tile + TileDiffXY(-1,  0));
    97 	TerraformAddDirtyTile(ts, tile + TileDiffXY(-1,  0));
   101 	TerraformAddDirtyTile(ts, tile);
    98 	TerraformAddDirtyTile(ts, tile);
   102 }
       
   103 
       
   104 /**
       
   105  * Checks if a tile can be terraformed, perform tiletype specific things (like clearing the tile) and compute their extra-cost.
       
   106  *
       
   107  * @param ts TerraformerState.
       
   108  * @param tile Tile.
       
   109  * @param mode Affected corner: 0 = north, 1 = east, 2 = south, 3 = west.
       
   110  * @return Error message or extra-cost.
       
   111  */
       
   112 static CommandCost TerraformProc(TerraformerState *ts, TileIndex tile, int mode)
       
   113 {
       
   114 	/* Check if a tile can be terraformed. */
       
   115 	if (IsTileType(tile, MP_RAILWAY)) {
       
   116 		static const TrackBits safe_track[] = { TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER, TRACK_BIT_RIGHT };
       
   117 		static const Slope unsafe_slope[] = { SLOPE_S, SLOPE_W, SLOPE_N, SLOPE_E };
       
   118 
       
   119 		Slope tileh;
       
   120 		uint z;
       
   121 
       
   122 		/* Nothing could be built at the steep slope - this avoids a bug
       
   123 		 * when you have a single diagonal track in one corner on a
       
   124 		 * basement and then you raise/lower the other corner. */
       
   125 		tileh = GetTileSlope(tile, &z);
       
   126 		if (tileh == unsafe_slope[mode] ||
       
   127 				tileh == (SLOPE_STEEP | ComplementSlope(unsafe_slope[mode]))) {
       
   128 			_terraform_err_tile = tile;
       
   129 			_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
       
   130 			return CMD_ERROR;
       
   131 		}
       
   132 
       
   133 		/* If we have a single diagonal track there, the other side of
       
   134 		 * tile can be terraformed. */
       
   135 		if (IsPlainRailTile(tile) && GetTrackBits(tile) == safe_track[mode]) {
       
   136 			/* Allow terraforming. */
       
   137 			return CommandCost();
       
   138 		}
       
   139 	}
       
   140 
       
   141 	/* Canals can't be terraformed */
       
   142 	if (IsClearWaterTile(tile) && IsCanal(tile)) {
       
   143 		_terraform_err_tile = tile;
       
   144 		_error_message = STR_MUST_DEMOLISH_CANAL_FIRST;
       
   145 		return CMD_ERROR;
       
   146 	}
       
   147 
       
   148 	/* Try to clear the tile. If the tile can be cleared, add the cost to the terraforming cost, else the terraforming fails. */
       
   149 	return DoCommand(tile, 0, 0, ts->flags, CMD_LANDSCAPE_CLEAR);
       
   150 }
    99 }
   151 
   100 
   152 /**
   101 /**
   153  * Terraform the north corner of a tile to a specific height.
   102  * Terraform the north corner of a tile to a specific height.
   154  *
   103  *
   267 
   216 
   268 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   217 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   269 
   218 
   270 	_terraform_err_tile = 0;
   219 	_terraform_err_tile = 0;
   271 
   220 
   272 	ts.direction = direction = p2 ? 1 : -1;
   221 	direction = p2 ? 1 : -1;
   273 	ts.flags = flags;
       
   274 	ts.modheight_count = ts.tile_table_count = 0;
   222 	ts.modheight_count = ts.tile_table_count = 0;
   275 	ts.cost = CommandCost();
   223 	ts.cost = CommandCost();
   276 
   224 
   277 	/* Make an extra check for map-bounds cause we add tiles to the originating tile */
   225 	/* Make an extra check for map-bounds cause we add tiles to the originating tile */
   278 	if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
   226 	if (tile + TileDiffXY(1, 1) >= MapSize()) return CMD_ERROR;
   322 
   270 
   323 			/* Find min and max height of tile */
   271 			/* Find min and max height of tile */
   324 			uint z_min = min(min(z_N, z_W), min(z_S, z_E));
   272 			uint z_min = min(min(z_N, z_W), min(z_S, z_E));
   325 			uint z_max = max(max(z_N, z_W), max(z_S, z_E));
   273 			uint z_max = max(max(z_N, z_W), max(z_S, z_E));
   326 
   274 
       
   275 			/* Compute tile slope */
       
   276 			uint tileh = (z_max > z_min + 1 ? SLOPE_STEEP : SLOPE_FLAT);
       
   277 			if (z_W > z_min) tileh += SLOPE_W;
       
   278 			if (z_S > z_min) tileh += SLOPE_S;
       
   279 			if (z_E > z_min) tileh += SLOPE_E;
       
   280 			if (z_N > z_min) tileh += SLOPE_N;
       
   281 
   327 			/* Check if bridge would take damage */
   282 			/* Check if bridge would take damage */
   328 			if (direction == 1 && MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) &&
   283 			if (direction == 1 && MayHaveBridgeAbove(tile) && IsBridgeAbove(tile) &&
   329 					GetBridgeHeight(GetSouthernBridgeEnd(tile)) <= z_max * TILE_HEIGHT) {
   284 					GetBridgeHeight(GetSouthernBridgeEnd(tile)) <= z_max * TILE_HEIGHT) {
   330 				_terraform_err_tile = *ti; // highlight the tile under the bridge
   285 				_terraform_err_tile = *ti; // highlight the tile under the bridge
   331 				return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   286 				return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
   334 			if (direction == -1 && IsTunnelInWay(tile, z_min * TILE_HEIGHT)) {
   289 			if (direction == -1 && IsTunnelInWay(tile, z_min * TILE_HEIGHT)) {
   335 				_terraform_err_tile = *ti; // highlight the tile above the tunnel
   290 				_terraform_err_tile = *ti; // highlight the tile above the tunnel
   336 				return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
   291 				return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
   337 			}
   292 			}
   338 			/* Check tiletype-specific things, and add extra-cost */
   293 			/* Check tiletype-specific things, and add extra-cost */
   339 			/* Start of temporary solution until TerraformProc() gets replaced with a TileTypeProc */
   294 			CommandCost cost = _tile_type_procs[GetTileType(tile)]->terraform_tile_proc(tile, flags, z_min * TILE_HEIGHT, (Slope) tileh);
   340 			_terraform_err_tile = tile;
   295 			if (CmdFailed(cost)) {
   341 			CommandCost cost_N = CommandCost();
   296 				_terraform_err_tile = tile;
   342 			CommandCost cost_W = CommandCost();
   297 				return cost;
   343 			CommandCost cost_S = CommandCost();
   298 			}
   344 			CommandCost cost_E = CommandCost();
       
   345 
       
   346 			if (z_N != TileHeight(tile)) cost_N = TerraformProc(&ts, tile, 0);
       
   347 			if (CmdFailed(cost_N)) return cost_N;
       
   348 
       
   349 			if (z_E != TileHeight(tile + TileDiffXY(0, 1))) cost_E = TerraformProc(&ts, tile, 1);
       
   350 			if (CmdFailed(cost_E)) return cost_E;
       
   351 
       
   352 			if (z_S != TileHeight(tile + TileDiffXY(1, 1))) cost_S = TerraformProc(&ts, tile, 2);
       
   353 			if (CmdFailed(cost_S)) return cost_S;
       
   354 
       
   355 			if (z_W != TileHeight(tile + TileDiffXY(1, 0))) cost_W = TerraformProc(&ts, tile, 3);
       
   356 			if (CmdFailed(cost_W)) return cost_W;
       
   357 
       
   358 			_terraform_err_tile = 0; // no error, reset error tile.
       
   359 			/* Add extra cost. Currently this may only be for clearing the tile. And we only want to clear it once. */
       
   360 			CommandCost cost = CommandCost();
       
   361 			cost.AddCost(cost_N);
       
   362 			if (cost.GetCost() == 0) cost.AddCost(cost_W);
       
   363 			if (cost.GetCost() == 0) cost.AddCost(cost_S);
       
   364 			if (cost.GetCost() == 0) cost.AddCost(cost_E);
       
   365 			ts.cost.AddCost(cost);
   299 			ts.cost.AddCost(cost);
   366 			/* End of temporary solution */
       
   367 		}
   300 		}
   368 	}
   301 	}
   369 
   302 
   370 	if (flags & DC_EXEC) {
   303 	if (flags & DC_EXEC) {
   371 		/* change the height */
   304 		/* change the height */
   838 }
   771 }
   839 
   772 
   840 void InitializeClearLand()
   773 void InitializeClearLand()
   841 {
   774 {
   842 	_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
   775 	_opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
       
   776 }
       
   777 
       
   778 static CommandCost TerraformTile_Clear(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
       
   779 {
       
   780 	return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
   843 }
   781 }
   844 
   782 
   845 extern const TileTypeProcs _tile_type_clear_procs = {
   783 extern const TileTypeProcs _tile_type_clear_procs = {
   846 	DrawTile_Clear,           ///< draw_tile_proc
   784 	DrawTile_Clear,           ///< draw_tile_proc
   847 	GetSlopeZ_Clear,          ///< get_slope_z_proc
   785 	GetSlopeZ_Clear,          ///< get_slope_z_proc
   854 	TileLoop_Clear,           ///< tile_loop_clear
   792 	TileLoop_Clear,           ///< tile_loop_clear
   855 	ChangeTileOwner_Clear,    ///< change_tile_owner_clear
   793 	ChangeTileOwner_Clear,    ///< change_tile_owner_clear
   856 	NULL,                     ///< get_produced_cargo_proc
   794 	NULL,                     ///< get_produced_cargo_proc
   857 	NULL,                     ///< vehicle_enter_tile_proc
   795 	NULL,                     ///< vehicle_enter_tile_proc
   858 	GetFoundation_Clear,      ///< get_foundation_proc
   796 	GetFoundation_Clear,      ///< get_foundation_proc
       
   797 	TerraformTile_Clear,      ///< terraform_tile_proc
   859 };
   798 };