clear_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: clear_cmd.cpp 20192 2010-07-19 17:28:27Z 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 "openttd.h"
00014 #include "clear_map.h"
00015 #include "command_func.h"
00016 #include "landscape.h"
00017 #include "genworld.h"
00018 #include "landscape_type.h"
00019 #include "functions.h"
00020 #include "economy_func.h"
00021 #include "viewport_func.h"
00022 #include "water.h"
00023 #include "core/random_func.hpp"
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_FIELDS,
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 + SlopeToSpriteOffset(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 + SlopeToSpriteOffset(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   bool fence_sw = GetFenceSW(ti->tile) != 0;
00067   bool fence_se = GetFenceSE(ti->tile) != 0;
00068 
00069   if (!fence_sw && !fence_se) return;
00070 
00071   int z = GetSlopeZInCorner(ti->tileh, CORNER_S);
00072 
00073   if (fence_sw) {
00074     DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh], PAL_NONE, 0, 0, z);
00075   }
00076 
00077   if (fence_se) {
00078     DrawGroundSpriteAt(_clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh], PAL_NONE, 0, 0, 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 + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
00095       break;
00096 
00097     case CLEAR_FIELDS:
00098       DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + SlopeToSpriteOffset(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)] + SlopeToSpriteOffset(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 
00160 static void TileLoopClearAlps(TileIndex tile)
00161 {
00162   int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT;
00163 
00164   if (k < 0) {
00165     /* Below the snow line, do nothing if no snow. */
00166     if (!IsSnowTile(tile)) return;
00167   } else {
00168     /* At or above the snow line, make snow tile if needed. */
00169     if (!IsSnowTile(tile)) {
00170       MakeSnow(tile);
00171       MarkTileDirtyByTile(tile);
00172       return;
00173     }
00174   }
00175   /* Update snow density. */
00176   uint curent_density = GetClearDensity(tile);
00177   uint req_density = (k < 0) ? 0u : min((uint)k / TILE_HEIGHT, 3);
00178 
00179   if (curent_density < req_density) {
00180     AddClearDensity(tile, 1);
00181   } else if (curent_density > req_density) {
00182     AddClearDensity(tile, -1);
00183   } else {
00184     /* Density at the required level. */
00185     if (k >= 0) return;
00186     ClearSnow(tile);
00187   }
00188   MarkTileDirtyByTile(tile);
00189 }
00190 
00196 static inline bool NeighbourIsDesert(TileIndex tile)
00197 {
00198   return GetTropicZone(tile + TileDiffXY(  1,  0)) == TROPICZONE_DESERT ||
00199       GetTropicZone(tile + TileDiffXY( -1,  0)) == TROPICZONE_DESERT ||
00200       GetTropicZone(tile + TileDiffXY(  0,  1)) == TROPICZONE_DESERT ||
00201       GetTropicZone(tile + TileDiffXY(  0, -1)) == TROPICZONE_DESERT;
00202 }
00203 
00204 static void TileLoopClearDesert(TileIndex tile)
00205 {
00206   /* Current desert level - 0 if it is not desert */
00207   uint current = 0;
00208   if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
00209 
00210   /* Expected desert level - 0 if it shouldn't be desert */
00211   uint expected = 0;
00212   if (GetTropicZone(tile) == TROPICZONE_DESERT) {
00213     expected = 3;
00214   } else if (NeighbourIsDesert(tile)) {
00215     expected = 1;
00216   }
00217 
00218   if (current == expected) return;
00219 
00220   if (expected == 0) {
00221     SetClearGroundDensity(tile, CLEAR_GRASS, 3);
00222   } else {
00223     /* Transition from clear to desert is not smooth (after clearing desert tile) */
00224     SetClearGroundDensity(tile, CLEAR_DESERT, expected);
00225   }
00226 
00227   MarkTileDirtyByTile(tile);
00228 }
00229 
00230 static void TileLoop_Clear(TileIndex tile)
00231 {
00232   /* If the tile is at any edge flood it to prevent maps without water. */
00233   if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) {
00234     uint z;
00235     Slope slope = GetTileSlope(tile, &z);
00236     if (z == 0 && slope == SLOPE_FLAT) {
00237       DoFloodTile(tile);
00238       MarkTileDirtyByTile(tile);
00239       return;
00240     }
00241   }
00242   TileLoopClearHelper(tile);
00243 
00244   switch (_settings_game.game_creation.landscape) {
00245     case LT_TROPIC: TileLoopClearDesert(tile); break;
00246     case LT_ARCTIC: TileLoopClearAlps(tile);   break;
00247   }
00248 
00249   switch (GetClearGround(tile)) {
00250     case CLEAR_GRASS:
00251       if (GetClearDensity(tile) == 3) return;
00252 
00253       if (_game_mode != GM_EDITOR) {
00254         if (GetClearCounter(tile) < 7) {
00255           AddClearCounter(tile, 1);
00256           return;
00257         } else {
00258           SetClearCounter(tile, 0);
00259           AddClearDensity(tile, 1);
00260         }
00261       } else {
00262         SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
00263       }
00264       break;
00265 
00266     case CLEAR_FIELDS: {
00267       uint field_type;
00268 
00269       if (_game_mode == GM_EDITOR) return;
00270 
00271       if (GetClearCounter(tile) < 7) {
00272         AddClearCounter(tile, 1);
00273         return;
00274       } else {
00275         SetClearCounter(tile, 0);
00276       }
00277 
00278       if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
00279         /* This farmfield is no longer farmfield, so make it grass again */
00280         MakeClear(tile, CLEAR_GRASS, 2);
00281       } else {
00282         field_type = GetFieldType(tile);
00283         field_type = (field_type < 8) ? field_type + 1 : 0;
00284         SetFieldType(tile, field_type);
00285       }
00286       break;
00287     }
00288 
00289     default:
00290       return;
00291   }
00292 
00293   MarkTileDirtyByTile(tile);
00294 }
00295 
00296 void GenerateClearTile()
00297 {
00298   uint i, gi;
00299   TileIndex tile;
00300 
00301   /* add rough tiles */
00302   i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
00303   gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
00304 
00305   SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
00306   do {
00307     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00308     tile = RandomTile();
00309     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
00310   } while (--i);
00311 
00312   /* add rocky tiles */
00313   i = gi;
00314   do {
00315     uint32 r = Random();
00316     tile = RandomTileSeed(r);
00317 
00318     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00319     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
00320       uint j = GB(r, 16, 4) + 5;
00321       for (;;) {
00322         TileIndex tile_new;
00323 
00324         SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
00325         do {
00326           if (--j == 0) goto get_out;
00327           tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
00328         } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
00329         tile = tile_new;
00330       }
00331 get_out:;
00332     }
00333   } while (--i);
00334 }
00335 
00336 static TrackStatus GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00337 {
00338   return 0;
00339 }
00340 
00341 static const StringID _clear_land_str[] = {
00342   STR_LAI_CLEAR_DESCRIPTION_GRASS,
00343   STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND,
00344   STR_LAI_CLEAR_DESCRIPTION_ROCKS,
00345   STR_LAI_CLEAR_DESCRIPTION_FIELDS,
00346   STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND,
00347   STR_LAI_CLEAR_DESCRIPTION_DESERT
00348 };
00349 
00350 static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
00351 {
00352   if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
00353     td->str = STR_LAI_CLEAR_DESCRIPTION_BARE_LAND;
00354   } else {
00355     td->str = _clear_land_str[GetClearGround(tile)];
00356   }
00357   td->owner[0] = GetTileOwner(tile);
00358 }
00359 
00360 static void ChangeTileOwner_Clear(TileIndex tile, Owner old_owner, Owner new_owner)
00361 {
00362   return;
00363 }
00364 
00365 void InitializeClearLand()
00366 {
00367   _settings_game.game_creation.snow_line = _settings_game.game_creation.snow_line_height * TILE_HEIGHT;
00368 }
00369 
00370 static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
00371 {
00372   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00373 }
00374 
00375 extern const TileTypeProcs _tile_type_clear_procs = {
00376   DrawTile_Clear,           
00377   GetSlopeZ_Clear,          
00378   ClearTile_Clear,          
00379   NULL,                     
00380   GetTileDesc_Clear,        
00381   GetTileTrackStatus_Clear, 
00382   NULL,                     
00383   NULL,                     
00384   TileLoop_Clear,           
00385   ChangeTileOwner_Clear,    
00386   NULL,                     
00387   NULL,                     
00388   GetFoundation_Clear,      
00389   TerraformTile_Clear,      
00390 };

Generated on Sun Jan 9 16:01:53 2011 for OpenTTD by  doxygen 1.6.1