# clear_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: clear_cmd.cpp 18945 2010-01-29 00:11:30Z yexo $ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
    00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
    00008  */
    00009
    00012 #include "stdafx.h"
    00013 #include "openttd.h"
    00014 #include "clear_map.h"
    00015 #include "command_func.h"
    00016 #include "landscape.h"
    00017 #include "variables.h"
    00018 #include "genworld.h"
    00019 #include "landscape_type.h"
    00020 #include "functions.h"
    00021 #include "economy_func.h"
    00022 #include "viewport_func.h"
    00023 #include "water.h"
    00024 #include "core/random_func.hpp"
    00025
    00026 #include "table/strings.h"
    00027 #include "table/sprites.h"
    00028 #include "table/clear_land.h"
    00029
    00030 static CommandCost ClearTile_Clear(TileIndex tile, DoCommandFlag flags)
    00031 {
    00032   static const Price clear_price_table[] = {
    00033     PR_CLEAR_GRASS,
    00034     PR_CLEAR_ROUGH,
    00035     PR_CLEAR_ROCKS,
    00036     PR_CLEAR_FIELDS,
    00037     PR_CLEAR_ROUGH,
    00038     PR_CLEAR_ROUGH,
    00039   };
    00040   CommandCost price(EXPENSES_CONSTRUCTION);
    00041
    00042   if (!IsClearGround(tile, CLEAR_GRASS) || GetClearDensity(tile) != 0) {
    00043     price.AddCost(_price[clear_price_table[GetClearGround(tile)]]);
    00044   }
    00045
    00046   if (flags & DC_EXEC) DoClearSquare(tile);
    00047
    00048   return price;
    00049 }
    00050
    00051 void DrawClearLandTile(const TileInfo *ti, byte set)
    00052 {
    00053   DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19, PAL_NONE);
    00054 }
    00055
    00056 void DrawHillyLandTile(const TileInfo *ti)
    00057 {
    00058   if (ti->tileh != SLOPE_FLAT) {
    00059     DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00060   } else {
    00061     DrawGroundSprite(_landscape_clear_sprites_rough[GB(ti->x ^ ti->y, 4, 3)], PAL_NONE);
    00062   }
    00063 }
    00064
    00065 void DrawClearLandFence(const TileInfo *ti)
    00066 {
    00067   bool fence_sw = GetFenceSW(ti->tile) != 0;
    00068   bool fence_se = GetFenceSE(ti->tile) != 0;
    00069
    00070   if (!fence_sw && !fence_se) return;
    00071
    00072   int z = GetSlopeZInCorner(ti->tileh, CORNER_S);
    00073
    00074   if (fence_sw) {
    00075     DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh], PAL_NONE, 0, 0, z);
    00076   }
    00077
    00078   if (fence_se) {
    00079     DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh], PAL_NONE, 0, 0, z);
    00080   }
    00081 }
    00082
    00083 static void DrawTile_Clear(TileInfo *ti)
    00084 {
    00085   switch (GetClearGround(ti->tile)) {
    00086     case CLEAR_GRASS:
    00087       DrawClearLandTile(ti, GetClearDensity(ti->tile));
    00088       break;
    00089
    00090     case CLEAR_ROUGH:
    00091       DrawHillyLandTile(ti);
    00092       break;
    00093
    00094     case CLEAR_ROCKS:
    00095       DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00096       break;
    00097
    00098     case CLEAR_FIELDS:
    00099       DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00100       break;
    00101
    00102     case CLEAR_SNOW:
    00103     case CLEAR_DESERT:
    00104       DrawGroundSprite(_clear_land_sprites_snow_desert[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00105       break;
    00106   }
    00107
    00108   DrawClearLandFence(ti);
    00109   DrawBridgeMiddle(ti);
    00110 }
    00111
    00112 static uint GetSlopeZ_Clear(TileIndex tile, uint x, uint y)
    00113 {
    00114   uint z;
    00115   Slope tileh = GetTileSlope(tile, &z);
    00116
    00117   return z + GetPartialZ(x & 0xF, y & 0xF, tileh);
    00118 }
    00119
    00120 static Foundation GetFoundation_Clear(TileIndex tile, Slope tileh)
    00121 {
    00122   return FOUNDATION_NONE;
    00123 }
    00124
    00125 void TileLoopClearHelper(TileIndex tile)
    00126 {
    00127   bool self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
    00128   bool dirty = false;
    00129
    00130   bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
    00131   if (GetFenceSW(tile) == 0) {
    00132     if (self != neighbour) {
    00133       SetFenceSW(tile, 3);
    00134       dirty = true;
    00135     }
    00136   } else {
    00137     if (self == 0 && neighbour == 0) {
    00138       SetFenceSW(tile, 0);
    00139       dirty = true;
    00140     }
    00141   }
    00142
    00143   neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
    00144   if (GetFenceSE(tile) == 0) {
    00145     if (self != neighbour) {
    00146       SetFenceSE(tile, 3);
    00147       dirty = true;
    00148     }
    00149   } else {
    00150     if (self == 0 && neighbour == 0) {
    00151       SetFenceSE(tile, 0);
    00152       dirty = true;
    00153     }
    00154   }
    00155
    00156   if (dirty) MarkTileDirtyByTile(tile);
    00157 }
    00158
    00159
    00161 static void TileLoopClearAlps(TileIndex tile)
    00162 {
    00163   int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT;
    00164
    00165   if (k < 0) {
    00166     /* Below the snow line, do nothing if no snow. */
    00167     if (!IsSnowTile(tile)) return;
    00168   } else {
    00169     /* At or above the snow line, make snow tile if needed. */
    00170     if (!IsSnowTile(tile)) {
    00171       MakeSnow(tile);
    00172       MarkTileDirtyByTile(tile);
    00173       return;
    00174     }
    00175   }
    00176   /* Update snow density. */
    00177   uint curent_density = GetClearDensity(tile);
    00178   uint req_density = (k < 0) ? 0u : min((uint)k / TILE_HEIGHT, 3);
    00179
    00180   if (curent_density < req_density) {
    00181     AddClearDensity(tile, 1);
    00182   } else if (curent_density > req_density) {
    00183     AddClearDensity(tile, -1);
    00184   } else {
    00185     /* Density at the required level. */
    00186     if (k >= 0) return;
    00187     ClearSnow(tile);
    00188   }
    00189   MarkTileDirtyByTile(tile);
    00190 }
    00191
    00192 static void TileLoopClearDesert(TileIndex tile)
    00193 {
    00194   if (IsClearGround(tile, CLEAR_DESERT)) return;
    00195
    00196   if (GetTropicZone(tile) == TROPICZONE_DESERT) {
    00197     SetClearGroundDensity(tile, CLEAR_DESERT, 3);
    00198   } else {
    00199     if (GetTropicZone(tile + TileDiffXY( 1,  0)) != TROPICZONE_DESERT &&
    00200         GetTropicZone(tile + TileDiffXY(-1,  0)) != TROPICZONE_DESERT &&
    00201         GetTropicZone(tile + TileDiffXY( 0,  1)) != TROPICZONE_DESERT &&
    00202         GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
    00203       return;
    00204     SetClearGroundDensity(tile, CLEAR_DESERT, 1);
    00205   }
    00206
    00207   MarkTileDirtyByTile(tile);
    00208 }
    00209
    00210 static void TileLoop_Clear(TileIndex tile)
    00211 {
    00212   /* If the tile is at any edge flood it to prevent maps without water. */
    00213   if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) {
    00214     uint z;
    00215     Slope slope = GetTileSlope(tile, &z);
    00216     if (z == 0 && slope == SLOPE_FLAT) {
    00217       DoFloodTile(tile);
    00218       MarkTileDirtyByTile(tile);
    00219       return;
    00220     }
    00221   }
    00222   TileLoopClearHelper(tile);
    00223
    00224   switch (_settings_game.game_creation.landscape) {
    00225     case LT_TROPIC: TileLoopClearDesert(tile); break;
    00226     case LT_ARCTIC: TileLoopClearAlps(tile);   break;
    00227   }
    00228
    00229   switch (GetClearGround(tile)) {
    00230     case CLEAR_GRASS:
    00231       if (GetClearDensity(tile) == 3) return;
    00232
    00233       if (_game_mode != GM_EDITOR) {
    00234         if (GetClearCounter(tile) < 7) {
    00235           AddClearCounter(tile, 1);
    00236           return;
    00237         } else {
    00238           SetClearCounter(tile, 0);
    00239           AddClearDensity(tile, 1);
    00240         }
    00241       } else {
    00242         SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
    00243       }
    00244       break;
    00245
    00246     case CLEAR_FIELDS: {
    00247       uint field_type;
    00248
    00249       if (_game_mode == GM_EDITOR) return;
    00250
    00251       if (GetClearCounter(tile) < 7) {
    00252         AddClearCounter(tile, 1);
    00253         return;
    00254       } else {
    00255         SetClearCounter(tile, 0);
    00256       }
    00257
    00258       if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
    00259         /* This farmfield is no longer farmfield, so make it grass again */
    00260         MakeClear(tile, CLEAR_GRASS, 2);
    00261       } else {
    00262         field_type = GetFieldType(tile);
    00263         field_type = (field_type < 8) ? field_type + 1 : 0;
    00264         SetFieldType(tile, field_type);
    00265       }
    00266       break;
    00267     }
    00268
    00269     default:
    00270       return;
    00271   }
    00272
    00273   MarkTileDirtyByTile(tile);
    00274 }
    00275
    00276 void GenerateClearTile()
    00277 {
    00278   uint i, gi;
    00279   TileIndex tile;
    00280
    00281   /* add rough tiles */
    00282   i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
    00283   gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
    00284
    00285   SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
    00286   do {
    00287     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
    00288     tile = RandomTile();
    00289     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
    00290   } while (--i);
    00291
    00292   /* add rocky tiles */
    00293   i = gi;
    00294   do {
    00295     uint32 r = Random();
    00296     tile = RandomTileSeed(r);
    00297
    00298     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
    00299     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
    00300       uint j = GB(r, 16, 4) + 5;
    00301       for (;;) {
    00302         TileIndex tile_new;
    00303
    00304         SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
    00305         do {
    00306           if (--j == 0) goto get_out;
    00307           tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
    00308         } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
    00309         tile = tile_new;
    00310       }
    00311 get_out:;
    00312     }
    00313   } while (--i);
    00314 }
    00315
    00316 static TrackStatus GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
    00317 {
    00318   return 0;
    00319 }
    00320
    00321 static const StringID _clear_land_str[] = {
    00322   STR_LAI_CLEAR_DESCRIPTION_GRASS,
    00323   STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND,
    00324   STR_LAI_CLEAR_DESCRIPTION_ROCKS,
    00325   STR_LAI_CLEAR_DESCRIPTION_FIELDS,
    00326   STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND,
    00327   STR_LAI_CLEAR_DESCRIPTION_DESERT
    00328 };
    00329
    00330 static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
    00331 {
    00332   if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
    00333     td->str = STR_LAI_CLEAR_DESCRIPTION_BARE_LAND;
    00334   } else {
    00335     td->str = _clear_land_str[GetClearGround(tile)];
    00336   }
    00337   td->owner[0] = GetTileOwner(tile);
    00338 }
    00339
    00340 static void ChangeTileOwner_Clear(TileIndex tile, Owner old_owner, Owner new_owner)
    00341 {
    00342   return;
    00343 }
    00344
    00345 void InitializeClearLand()
    00346 {
    00347   _settings_game.game_creation.snow_line = _settings_game.game_creation.snow_line_height * TILE_HEIGHT;
    00348 }
    00349
    00350 static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
    00351 {
    00352   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
    00353 }
    00354
    00355 extern const TileTypeProcs _tile_type_clear_procs = {
    00356   DrawTile_Clear,
    00357   GetSlopeZ_Clear,
    00358   ClearTile_Clear,
    00359   NULL,
    00360   GetTileDesc_Clear,
    00361   GetTileTrackStatus_Clear,
    00362   NULL,
    00363   NULL,
    00364   TileLoop_Clear,
    00365   ChangeTileOwner_Clear,
    00366   NULL,
    00367   NULL,
    00368   GetFoundation_Clear,
    00369   TerraformTile_Clear,
    00370 };