clear_cmd.cpp

Go to the documentation of this file.
00001 /* $Id: clear_cmd.cpp 19857 2010-05-18 21:44:47Z 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 "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 
00197 static inline bool NeighbourIsDesert(TileIndex tile)
00198 {
00199   return 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 }
00204 
00205 static void TileLoopClearDesert(TileIndex tile)
00206 {
00207   /* Current desert level - 0 if it is not desert */
00208   uint current = 0;
00209   if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
00210 
00211   /* Expected desert level - 0 if it shouldn't be desert */
00212   uint expected = 0;
00213   if (GetTropicZone(tile) == TROPICZONE_DESERT) {
00214     expected = 3;
00215   } else if (NeighbourIsDesert(tile)) {
00216     expected = 1;
00217   }
00218 
00219   if (current == expected) return;
00220 
00221   if (expected == 0) {
00222     SetClearGroundDensity(tile, CLEAR_GRASS, 3);
00223   } else {
00224     /* Transition from clear to desert is not smooth (after clearing desert tile) */
00225     SetClearGroundDensity(tile, CLEAR_DESERT, expected);
00226   }
00227 
00228   MarkTileDirtyByTile(tile);
00229 }
00230 
00231 static void TileLoop_Clear(TileIndex tile)
00232 {
00233   /* If the tile is at any edge flood it to prevent maps without water. */
00234   if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) {
00235     uint z;
00236     Slope slope = GetTileSlope(tile, &z);
00237     if (z == 0 && slope == SLOPE_FLAT) {
00238       DoFloodTile(tile);
00239       MarkTileDirtyByTile(tile);
00240       return;
00241     }
00242   }
00243   TileLoopClearHelper(tile);
00244 
00245   switch (_settings_game.game_creation.landscape) {
00246     case LT_TROPIC: TileLoopClearDesert(tile); break;
00247     case LT_ARCTIC: TileLoopClearAlps(tile);   break;
00248   }
00249 
00250   switch (GetClearGround(tile)) {
00251     case CLEAR_GRASS:
00252       if (GetClearDensity(tile) == 3) return;
00253 
00254       if (_game_mode != GM_EDITOR) {
00255         if (GetClearCounter(tile) < 7) {
00256           AddClearCounter(tile, 1);
00257           return;
00258         } else {
00259           SetClearCounter(tile, 0);
00260           AddClearDensity(tile, 1);
00261         }
00262       } else {
00263         SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
00264       }
00265       break;
00266 
00267     case CLEAR_FIELDS: {
00268       uint field_type;
00269 
00270       if (_game_mode == GM_EDITOR) return;
00271 
00272       if (GetClearCounter(tile) < 7) {
00273         AddClearCounter(tile, 1);
00274         return;
00275       } else {
00276         SetClearCounter(tile, 0);
00277       }
00278 
00279       if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
00280         /* This farmfield is no longer farmfield, so make it grass again */
00281         MakeClear(tile, CLEAR_GRASS, 2);
00282       } else {
00283         field_type = GetFieldType(tile);
00284         field_type = (field_type < 8) ? field_type + 1 : 0;
00285         SetFieldType(tile, field_type);
00286       }
00287       break;
00288     }
00289 
00290     default:
00291       return;
00292   }
00293 
00294   MarkTileDirtyByTile(tile);
00295 }
00296 
00297 void GenerateClearTile()
00298 {
00299   uint i, gi;
00300   TileIndex tile;
00301 
00302   /* add rough tiles */
00303   i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
00304   gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
00305 
00306   SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
00307   do {
00308     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00309     tile = RandomTile();
00310     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
00311   } while (--i);
00312 
00313   /* add rocky tiles */
00314   i = gi;
00315   do {
00316     uint32 r = Random();
00317     tile = RandomTileSeed(r);
00318 
00319     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00320     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
00321       uint j = GB(r, 16, 4) + 5;
00322       for (;;) {
00323         TileIndex tile_new;
00324 
00325         SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
00326         do {
00327           if (--j == 0) goto get_out;
00328           tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
00329         } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
00330         tile = tile_new;
00331       }
00332 get_out:;
00333     }
00334   } while (--i);
00335 }
00336 
00337 static TrackStatus GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00338 {
00339   return 0;
00340 }
00341 
00342 static const StringID _clear_land_str[] = {
00343   STR_LAI_CLEAR_DESCRIPTION_GRASS,
00344   STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND,
00345   STR_LAI_CLEAR_DESCRIPTION_ROCKS,
00346   STR_LAI_CLEAR_DESCRIPTION_FIELDS,
00347   STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND,
00348   STR_LAI_CLEAR_DESCRIPTION_DESERT
00349 };
00350 
00351 static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
00352 {
00353   if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
00354     td->str = STR_LAI_CLEAR_DESCRIPTION_BARE_LAND;
00355   } else {
00356     td->str = _clear_land_str[GetClearGround(tile)];
00357   }
00358   td->owner[0] = GetTileOwner(tile);
00359 }
00360 
00361 static void ChangeTileOwner_Clear(TileIndex tile, Owner old_owner, Owner new_owner)
00362 {
00363   return;
00364 }
00365 
00366 void InitializeClearLand()
00367 {
00368   _settings_game.game_creation.snow_line = _settings_game.game_creation.snow_line_height * TILE_HEIGHT;
00369 }
00370 
00371 static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, uint z_new, Slope tileh_new)
00372 {
00373   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00374 }
00375 
00376 extern const TileTypeProcs _tile_type_clear_procs = {
00377   DrawTile_Clear,           
00378   GetSlopeZ_Clear,          
00379   ClearTile_Clear,          
00380   NULL,                     
00381   GetTileDesc_Clear,        
00382   GetTileTrackStatus_Clear, 
00383   NULL,                     
00384   NULL,                     
00385   TileLoop_Clear,           
00386   ChangeTileOwner_Clear,    
00387   NULL,                     
00388   NULL,                     
00389   GetFoundation_Clear,      
00390   TerraformTile_Clear,      
00391 };

Generated on Sat Jun 19 17:14:47 2010 for OpenTTD by  doxygen 1.6.1