00001
00002
00003
00004
00005
00006
00007
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 "clear_func.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
00165 if (!IsSnowTile(tile)) return;
00166 } else {
00167
00168 if (!IsSnowTile(tile)) {
00169 MakeSnow(tile);
00170 MarkTileDirtyByTile(tile);
00171 return;
00172 }
00173 }
00174
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
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
00206 uint current = 0;
00207 if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
00208
00209
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
00223 SetClearGroundDensity(tile, CLEAR_DESERT, expected);
00224 }
00225
00226 MarkTileDirtyByTile(tile);
00227 }
00228
00229 static void TileLoop_Clear(TileIndex tile)
00230 {
00231
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
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
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
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 };