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 }; |