# clear_cmd.cpp

Go to the documentation of this file.

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