clear_cmd.cpp

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

Generated on Fri Feb 4 20:53:38 2011 for OpenTTD by  doxygen 1.6.1