# clear_cmd.cpp

Go to the documentation of this file.

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