# clear_cmd.cpp

Go to the documentation of this file.

    00001 /* $Id: clear_cmd.cpp 12199 2008-02-20 17:49:50Z frosch $ */
    00002
    00005 #include "stdafx.h"
    00006 #include "openttd.h"
    00007 #include "clear_map.h"
    00008 #include "command_func.h"
    00009 #include "bridge.h"
    00010 #include "landscape.h"
    00011 #include "variables.h"
    00012 #include "unmovable_map.h"
    00013 #include "genworld.h"
    00014 #include "industry.h"
    00015 #include "water_map.h"
    00016 #include "tile_cmd.h"
    00017 #include "functions.h"
    00018 #include "economy_func.h"
    00019 #include "viewport_func.h"
    00020 #include "settings_type.h"
    00021
    00022 #include "table/strings.h"
    00023 #include "table/sprites.h"
    00024 #include "table/clear_land.h"
    00025
    00026 static CommandCost ClearTile_Clear(TileIndex tile, byte flags)
    00027 {
    00028   static const Money* clear_price_table[] = {
    00029     &_price.clear_grass,
    00030     &_price.clear_roughland,
    00031     &_price.clear_rocks,
    00032     &_price.clear_fields,
    00033     &_price.clear_roughland,
    00034     &_price.clear_roughland,
    00035   };
    00036   CommandCost price(EXPENSES_CONSTRUCTION);
    00037
    00038   if (!IsClearGround(tile, CLEAR_GRASS) || GetClearDensity(tile) != 0) {
    00039     price.AddCost(*clear_price_table[GetClearGround(tile)]);
    00040   }
    00041
    00042   if (flags & DC_EXEC) DoClearSquare(tile);
    00043
    00044   return price;
    00045 }
    00046
    00047 void DrawClearLandTile(const TileInfo *ti, byte set)
    00048 {
    00049   DrawGroundSprite(SPR_FLAT_BARE_LAND + _tileh_to_sprite[ti->tileh] + set * 19, PAL_NONE);
    00050 }
    00051
    00052 void DrawHillyLandTile(const TileInfo *ti)
    00053 {
    00054   if (ti->tileh != SLOPE_FLAT) {
    00055     DrawGroundSprite(SPR_FLAT_ROUGH_LAND + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00056   } else {
    00057     DrawGroundSprite(_landscape_clear_sprites[GB(ti->x ^ ti->y, 4, 3)], PAL_NONE);
    00058   }
    00059 }
    00060
    00061 void DrawClearLandFence(const TileInfo *ti)
    00062 {
    00063   byte z = ti->z;
    00064
    00065   if (ti->tileh & SLOPE_S) {
    00066     z += TILE_HEIGHT;
    00067     if (ti->tileh == SLOPE_STEEP_S) z += TILE_HEIGHT;
    00068   }
    00069
    00070   if (GetFenceSW(ti->tile) != 0) {
    00071     DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh[ti->tileh], PAL_NONE, ti->x, ti->y, z);
    00072   }
    00073
    00074   if (GetFenceSE(ti->tile) != 0) {
    00075     DrawGroundSpriteAt(_clear_land_fence_sprites_1[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_2[ti->tileh], PAL_NONE, ti->x, ti->y, z);
    00076   }
    00077 }
    00078
    00079 static void DrawTile_Clear(TileInfo *ti)
    00080 {
    00081   switch (GetClearGround(ti->tile)) {
    00082     case CLEAR_GRASS:
    00083       DrawClearLandTile(ti, GetClearDensity(ti->tile));
    00084       break;
    00085
    00086     case CLEAR_ROUGH:
    00087       DrawHillyLandTile(ti);
    00088       break;
    00089
    00090     case CLEAR_ROCKS:
    00091       DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00092       break;
    00093
    00094     case CLEAR_FIELDS:
    00095       DrawGroundSprite(_clear_land_sprites_1[GetFieldType(ti->tile)] + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00096       break;
    00097
    00098     case CLEAR_SNOW:
    00099       DrawGroundSprite(_clear_land_sprites_2[GetClearDensity(ti->tile)] + _tileh_to_sprite[ti->tileh], PAL_NONE);
    00100       break;
    00101
    00102     case CLEAR_DESERT:
    00103       DrawGroundSprite(_clear_land_sprites_3[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 static void GetAcceptedCargo_Clear(TileIndex tile, AcceptedCargo ac)
    00125 {
    00126   /* unused */
    00127 }
    00128
    00129 static void AnimateTile_Clear(TileIndex tile)
    00130 {
    00131   /* unused */
    00132 }
    00133
    00134 void TileLoopClearHelper(TileIndex tile)
    00135 {
    00136   byte self;
    00137   byte neighbour;
    00138   TileIndex dirty = INVALID_TILE;
    00139
    00140   self = (IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
    00141
    00142   neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
    00143   if (GetFenceSW(tile) == 0) {
    00144     if (self != neighbour) {
    00145       SetFenceSW(tile, 3);
    00146       dirty = tile;
    00147     }
    00148   } else {
    00149     if (self == 0 && neighbour == 0) {
    00150       SetFenceSW(tile, 0);
    00151       dirty = tile;
    00152     }
    00153   }
    00154
    00155   neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
    00156   if (GetFenceSE(tile) == 0) {
    00157     if (self != neighbour) {
    00158       SetFenceSE(tile, 3);
    00159       dirty = tile;
    00160     }
    00161   } else {
    00162     if (self == 0 && neighbour == 0) {
    00163       SetFenceSE(tile, 0);
    00164       dirty = tile;
    00165     }
    00166   }
    00167
    00168   if (dirty != INVALID_TILE) MarkTileDirtyByTile(dirty);
    00169 }
    00170
    00171
    00172 /* convert into snowy tiles */
    00173 static void TileLoopClearAlps(TileIndex tile)
    00174 {
    00175   int k = GetTileZ(tile) - GetSnowLine() + TILE_HEIGHT;
    00176
    00177   if (k < 0) { // well below the snow line
    00178     if (!IsClearGround(tile, CLEAR_SNOW)) return;
    00179     if (GetClearDensity(tile) == 0) SetClearGroundDensity(tile, CLEAR_GRASS, 3);
    00180   } else {
    00181     if (!IsClearGround(tile, CLEAR_SNOW)) {
    00182       SetClearGroundDensity(tile, CLEAR_SNOW, 0);
    00183     } else {
    00184       uint density = min((uint)k / TILE_HEIGHT, 3);
    00185
    00186       if (GetClearDensity(tile) < density) {
    00187         AddClearDensity(tile, 1);
    00188       } else if (GetClearDensity(tile) > density) {
    00189         AddClearDensity(tile, -1);
    00190       } else {
    00191         return;
    00192       }
    00193     }
    00194   }
    00195
    00196   MarkTileDirtyByTile(tile);
    00197 }
    00198
    00199 static void TileLoopClearDesert(TileIndex tile)
    00200 {
    00201   if (IsClearGround(tile, CLEAR_DESERT)) return;
    00202
    00203   if (GetTropicZone(tile) == TROPICZONE_DESERT) {
    00204     SetClearGroundDensity(tile, CLEAR_DESERT, 3);
    00205   } else {
    00206     if (GetTropicZone(tile + TileDiffXY( 1,  0)) != TROPICZONE_DESERT &&
    00207         GetTropicZone(tile + TileDiffXY(-1,  0)) != TROPICZONE_DESERT &&
    00208         GetTropicZone(tile + TileDiffXY( 0,  1)) != TROPICZONE_DESERT &&
    00209         GetTropicZone(tile + TileDiffXY( 0, -1)) != TROPICZONE_DESERT)
    00210       return;
    00211     SetClearGroundDensity(tile, CLEAR_DESERT, 1);
    00212   }
    00213
    00214   MarkTileDirtyByTile(tile);
    00215 }
    00216
    00217 static void TileLoop_Clear(TileIndex tile)
    00218 {
    00219   TileLoopClearHelper(tile);
    00220
    00221   switch (_opt.landscape) {
    00222     case LT_TROPIC: TileLoopClearDesert(tile); break;
    00223     case LT_ARCTIC: TileLoopClearAlps(tile);   break;
    00224   }
    00225
    00226   switch (GetClearGround(tile)) {
    00227     case CLEAR_GRASS:
    00228       if (GetClearDensity(tile) == 3) return;
    00229
    00230       if (_game_mode != GM_EDITOR) {
    00231         if (GetClearCounter(tile) < 7) {
    00232           AddClearCounter(tile, 1);
    00233           return;
    00234         } else {
    00235           SetClearCounter(tile, 0);
    00236           AddClearDensity(tile, 1);
    00237         }
    00238       } else {
    00239         SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
    00240       }
    00241       break;
    00242
    00243     case CLEAR_FIELDS: {
    00244       uint field_type;
    00245
    00246       if (_game_mode == GM_EDITOR) return;
    00247
    00248       if (GetClearCounter(tile) < 7) {
    00249         AddClearCounter(tile, 1);
    00250         return;
    00251       } else {
    00252         SetClearCounter(tile, 0);
    00253       }
    00254
    00255       if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
    00256         /* This farmfield is no longer farmfield, so make it grass again */
    00257         MakeClear(tile, CLEAR_GRASS, 2);
    00258       } else {
    00259         field_type = GetFieldType(tile);
    00260         field_type = (field_type < 8) ? field_type + 1 : 0;
    00261         SetFieldType(tile, field_type);
    00262       }
    00263       break;
    00264     }
    00265
    00266     default:
    00267       return;
    00268   }
    00269
    00270   MarkTileDirtyByTile(tile);
    00271 }
    00272
    00273 void GenerateClearTile()
    00274 {
    00275   uint i, gi;
    00276   TileIndex tile;
    00277
    00278   /* add rough tiles */
    00279   i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
    00280   gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
    00281
    00282   SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
    00283   do {
    00284     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
    00285     tile = RandomTile();
    00286     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
    00287   } while (--i);
    00288
    00289   /* add rocky tiles */
    00290   i = gi;
    00291   do {
    00292     uint32 r = Random();
    00293     tile = RandomTileSeed(r);
    00294
    00295     IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
    00296     if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
    00297       uint j = GB(r, 16, 4) + 5;
    00298       for (;;) {
    00299         TileIndex tile_new;
    00300
    00301         SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
    00302         do {
    00303           if (--j == 0) goto get_out;
    00304           tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
    00305         } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
    00306         tile = tile_new;
    00307       }
    00308 get_out:;
    00309     }
    00310   } while (--i);
    00311 }
    00312
    00313 static void ClickTile_Clear(TileIndex tile)
    00314 {
    00315   /* not used */
    00316 }
    00317
    00318 static TrackStatus GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
    00319 {
    00320   return 0;
    00321 }
    00322
    00323 static const StringID _clear_land_str[] = {
    00324   STR_080D_GRASS,
    00325   STR_080B_ROUGH_LAND,
    00326   STR_080A_ROCKS,
    00327   STR_080E_FIELDS,
    00328   STR_080F_SNOW_COVERED_LAND,
    00329   STR_0810_DESERT
    00330 };
    00331
    00332 static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
    00333 {
    00334   if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
    00335     td->str = STR_080C_BARE_LAND;
    00336   } else {
    00337     td->str = _clear_land_str[GetClearGround(tile)];
    00338   }
    00339   td->owner = GetTileOwner(tile);
    00340 }
    00341
    00342 static void ChangeTileOwner_Clear(TileIndex tile, PlayerID old_player, PlayerID new_player)
    00343 {
    00344   return;
    00345 }
    00346
    00347 void InitializeClearLand()
    00348 {
    00349   _opt.snow_line = _patches.snow_line_height * TILE_HEIGHT;
    00350 }
    00351
    00352 static CommandCost TerraformTile_Clear(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new)
    00353 {
    00354   return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
    00355 }
    00356
    00357 extern const TileTypeProcs _tile_type_clear_procs = {
    00358   DrawTile_Clear,
    00359   GetSlopeZ_Clear,
    00360   ClearTile_Clear,
    00361   GetAcceptedCargo_Clear,
    00362   GetTileDesc_Clear,
    00363   GetTileTrackStatus_Clear,
    00364   ClickTile_Clear,
    00365   AnimateTile_Clear,
    00366   TileLoop_Clear,
    00367   ChangeTileOwner_Clear,
    00368   NULL,
    00369   NULL,
    00370   GetFoundation_Clear,
    00371   TerraformTile_Clear,
    00372 };