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 #include "newgrf_generic.h"
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 static void DrawClearLandFence(const TileInfo *ti)
00065 {
00066
00067 StartSpriteCombine();
00068
00069 int maxz = GetSlopeMaxPixelZ(ti->tileh);
00070
00071 bool fence_nw = GetFenceNW(ti->tile) != 0;
00072 if (fence_nw) {
00073 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_W);
00074 SpriteID sprite = _clear_land_fence_sprites[GetFenceNW(ti->tile) - 1] + _fence_mod_by_tileh_nw[ti->tileh];
00075 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y - 15, 16, 31, maxz - z + 4, ti->z + z, false, 0, 15, -z);
00076 }
00077
00078 bool fence_ne = GetFenceNE(ti->tile) != 0;
00079 if (fence_ne) {
00080 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_E);
00081 SpriteID sprite = _clear_land_fence_sprites[GetFenceNE(ti->tile) - 1] + _fence_mod_by_tileh_ne[ti->tileh];
00082 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x - 15, ti->y, 31, 16, maxz - z + 4, ti->z + z, false, 15, 0, -z);
00083 }
00084
00085 bool fence_sw = GetFenceSW(ti->tile) != 0;
00086 bool fence_se = GetFenceSE(ti->tile) != 0;
00087
00088 if (fence_sw || fence_se) {
00089 int z = GetSlopePixelZInCorner(ti->tileh, CORNER_S);
00090
00091 if (fence_sw) {
00092 SpriteID sprite = _clear_land_fence_sprites[GetFenceSW(ti->tile) - 1] + _fence_mod_by_tileh_sw[ti->tileh];
00093 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
00094 }
00095
00096 if (fence_se) {
00097 SpriteID sprite = _clear_land_fence_sprites[GetFenceSE(ti->tile) - 1] + _fence_mod_by_tileh_se[ti->tileh];
00098 AddSortableSpriteToDraw(sprite, PAL_NONE, ti->x, ti->y, 16, 16, maxz - z + 4, ti->z + z, false, 0, 0, -z);
00099 }
00100 }
00101 EndSpriteCombine();
00102 }
00103
00104 static void DrawTile_Clear(TileInfo *ti)
00105 {
00106 switch (GetClearGround(ti->tile)) {
00107 case CLEAR_GRASS:
00108 DrawClearLandTile(ti, GetClearDensity(ti->tile));
00109 break;
00110
00111 case CLEAR_ROUGH:
00112 DrawHillyLandTile(ti);
00113 break;
00114
00115 case CLEAR_ROCKS:
00116 DrawGroundSprite(SPR_FLAT_ROCKY_LAND_1 + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
00117 break;
00118
00119 case CLEAR_FIELDS:
00120 DrawGroundSprite(_clear_land_sprites_farmland[GetFieldType(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
00121 DrawClearLandFence(ti);
00122 break;
00123
00124 case CLEAR_SNOW:
00125 case CLEAR_DESERT:
00126 DrawGroundSprite(_clear_land_sprites_snow_desert[GetClearDensity(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE);
00127 break;
00128 }
00129
00130 DrawBridgeMiddle(ti);
00131 }
00132
00133 static int GetSlopePixelZ_Clear(TileIndex tile, uint x, uint y)
00134 {
00135 int z;
00136 Slope tileh = GetTilePixelSlope(tile, &z);
00137
00138 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
00139 }
00140
00141 static Foundation GetFoundation_Clear(TileIndex tile, Slope tileh)
00142 {
00143 return FOUNDATION_NONE;
00144 }
00145
00146 static void UpdateFences(TileIndex tile)
00147 {
00148 assert(IsTileType(tile, MP_CLEAR) && IsClearGround(tile, CLEAR_FIELDS));
00149 bool dirty = false;
00150
00151 bool neighbour = (IsTileType(TILE_ADDXY(tile, 1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 1, 0), CLEAR_FIELDS));
00152 if (!neighbour && GetFenceSW(tile) == 0) {
00153 SetFenceSW(tile, 3);
00154 dirty = true;
00155 }
00156
00157 neighbour = (IsTileType(TILE_ADDXY(tile, 0, 1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, 1), CLEAR_FIELDS));
00158 if (!neighbour && GetFenceSE(tile) == 0) {
00159 SetFenceSE(tile, 3);
00160 dirty = true;
00161 }
00162
00163 neighbour = (IsTileType(TILE_ADDXY(tile, -1, 0), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, -1, 0), CLEAR_FIELDS));
00164 if (!neighbour && GetFenceNE(tile) == 0) {
00165 SetFenceNE(tile, 3);
00166 dirty = true;
00167 }
00168
00169 neighbour = (IsTileType(TILE_ADDXY(tile, 0, -1), MP_CLEAR) && IsClearGround(TILE_ADDXY(tile, 0, -1), CLEAR_FIELDS));
00170 if (!neighbour && GetFenceNW(tile) == 0) {
00171 SetFenceNW(tile, 3);
00172 dirty = true;
00173 }
00174
00175 if (dirty) MarkTileDirtyByTile(tile);
00176 }
00177
00178
00180 static void TileLoopClearAlps(TileIndex tile)
00181 {
00182 int k = GetTileZ(tile) - GetSnowLine() + 1;
00183
00184 if (k < 0) {
00185
00186 if (!IsSnowTile(tile)) return;
00187 } else {
00188
00189 if (!IsSnowTile(tile)) {
00190 MakeSnow(tile);
00191 MarkTileDirtyByTile(tile);
00192 return;
00193 }
00194 }
00195
00196 uint curent_density = GetClearDensity(tile);
00197 uint req_density = (k < 0) ? 0u : min((uint)k, 3);
00198
00199 if (curent_density < req_density) {
00200 AddClearDensity(tile, 1);
00201 } else if (curent_density > req_density) {
00202 AddClearDensity(tile, -1);
00203 } else {
00204
00205 if (k >= 0) return;
00206 ClearSnow(tile);
00207 }
00208 MarkTileDirtyByTile(tile);
00209 }
00210
00216 static inline bool NeighbourIsDesert(TileIndex tile)
00217 {
00218 return GetTropicZone(tile + TileDiffXY( 1, 0)) == TROPICZONE_DESERT ||
00219 GetTropicZone(tile + TileDiffXY( -1, 0)) == TROPICZONE_DESERT ||
00220 GetTropicZone(tile + TileDiffXY( 0, 1)) == TROPICZONE_DESERT ||
00221 GetTropicZone(tile + TileDiffXY( 0, -1)) == TROPICZONE_DESERT;
00222 }
00223
00224 static void TileLoopClearDesert(TileIndex tile)
00225 {
00226
00227 uint current = 0;
00228 if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
00229
00230
00231 uint expected = 0;
00232 if (GetTropicZone(tile) == TROPICZONE_DESERT) {
00233 expected = 3;
00234 } else if (NeighbourIsDesert(tile)) {
00235 expected = 1;
00236 }
00237
00238 if (current == expected) return;
00239
00240 if (expected == 0) {
00241 SetClearGroundDensity(tile, CLEAR_GRASS, 3);
00242 } else {
00243
00244 SetClearGroundDensity(tile, CLEAR_DESERT, expected);
00245 }
00246
00247 MarkTileDirtyByTile(tile);
00248 }
00249
00250 static void TileLoop_Clear(TileIndex tile)
00251 {
00252
00253 if (_settings_game.construction.freeform_edges && DistanceFromEdge(tile) == 1) {
00254 int z;
00255 Slope slope = GetTileSlope(tile, &z);
00256 if (z == 0 && slope == SLOPE_FLAT) {
00257 DoFloodTile(tile);
00258 MarkTileDirtyByTile(tile);
00259 return;
00260 }
00261 }
00262 AmbientSoundEffectCallback(tile);
00263
00264 switch (_settings_game.game_creation.landscape) {
00265 case LT_TROPIC: TileLoopClearDesert(tile); break;
00266 case LT_ARCTIC: TileLoopClearAlps(tile); break;
00267 }
00268
00269 switch (GetClearGround(tile)) {
00270 case CLEAR_GRASS:
00271 if (GetClearDensity(tile) == 3) return;
00272
00273 if (_game_mode != GM_EDITOR) {
00274 if (GetClearCounter(tile) < 7) {
00275 AddClearCounter(tile, 1);
00276 return;
00277 } else {
00278 SetClearCounter(tile, 0);
00279 AddClearDensity(tile, 1);
00280 }
00281 } else {
00282 SetClearGroundDensity(tile, GB(Random(), 0, 8) > 21 ? CLEAR_GRASS : CLEAR_ROUGH, 3);
00283 }
00284 break;
00285
00286 case CLEAR_FIELDS:
00287 UpdateFences(tile);
00288
00289 if (_game_mode == GM_EDITOR) return;
00290
00291 if (GetClearCounter(tile) < 7) {
00292 AddClearCounter(tile, 1);
00293 return;
00294 } else {
00295 SetClearCounter(tile, 0);
00296 }
00297
00298 if (GetIndustryIndexOfField(tile) == INVALID_INDUSTRY && GetFieldType(tile) >= 7) {
00299
00300 MakeClear(tile, CLEAR_GRASS, 2);
00301 } else {
00302 uint field_type = GetFieldType(tile);
00303 field_type = (field_type < 8) ? field_type + 1 : 0;
00304 SetFieldType(tile, field_type);
00305 }
00306 break;
00307
00308 default:
00309 return;
00310 }
00311
00312 MarkTileDirtyByTile(tile);
00313 }
00314
00315 void GenerateClearTile()
00316 {
00317 uint i, gi;
00318 TileIndex tile;
00319
00320
00321 i = ScaleByMapSize(GB(Random(), 0, 10) + 0x400);
00322 gi = ScaleByMapSize(GB(Random(), 0, 7) + 0x80);
00323
00324 SetGeneratingWorldProgress(GWP_ROUGH_ROCKY, gi + i);
00325 do {
00326 IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00327 tile = RandomTile();
00328 if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) SetClearGroundDensity(tile, CLEAR_ROUGH, 3);
00329 } while (--i);
00330
00331
00332 i = gi;
00333 do {
00334 uint32 r = Random();
00335 tile = RandomTileSeed(r);
00336
00337 IncreaseGeneratingWorldProgress(GWP_ROUGH_ROCKY);
00338 if (IsTileType(tile, MP_CLEAR) && !IsClearGround(tile, CLEAR_DESERT)) {
00339 uint j = GB(r, 16, 4) + 5;
00340 for (;;) {
00341 TileIndex tile_new;
00342
00343 SetClearGroundDensity(tile, CLEAR_ROCKS, 3);
00344 do {
00345 if (--j == 0) goto get_out;
00346 tile_new = tile + TileOffsByDiagDir((DiagDirection)GB(Random(), 0, 2));
00347 } while (!IsTileType(tile_new, MP_CLEAR) || IsClearGround(tile_new, CLEAR_DESERT));
00348 tile = tile_new;
00349 }
00350 get_out:;
00351 }
00352 } while (--i);
00353 }
00354
00355 static TrackStatus GetTileTrackStatus_Clear(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00356 {
00357 return 0;
00358 }
00359
00360 static const StringID _clear_land_str[] = {
00361 STR_LAI_CLEAR_DESCRIPTION_GRASS,
00362 STR_LAI_CLEAR_DESCRIPTION_ROUGH_LAND,
00363 STR_LAI_CLEAR_DESCRIPTION_ROCKS,
00364 STR_LAI_CLEAR_DESCRIPTION_FIELDS,
00365 STR_LAI_CLEAR_DESCRIPTION_SNOW_COVERED_LAND,
00366 STR_LAI_CLEAR_DESCRIPTION_DESERT
00367 };
00368
00369 static void GetTileDesc_Clear(TileIndex tile, TileDesc *td)
00370 {
00371 if (IsClearGround(tile, CLEAR_GRASS) && GetClearDensity(tile) == 0) {
00372 td->str = STR_LAI_CLEAR_DESCRIPTION_BARE_LAND;
00373 } else {
00374 td->str = _clear_land_str[GetClearGround(tile)];
00375 }
00376 td->owner[0] = GetTileOwner(tile);
00377 }
00378
00379 static void ChangeTileOwner_Clear(TileIndex tile, Owner old_owner, Owner new_owner)
00380 {
00381 return;
00382 }
00383
00384 static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
00385 {
00386 return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00387 }
00388
00389 extern const TileTypeProcs _tile_type_clear_procs = {
00390 DrawTile_Clear,
00391 GetSlopePixelZ_Clear,
00392 ClearTile_Clear,
00393 NULL,
00394 GetTileDesc_Clear,
00395 GetTileTrackStatus_Clear,
00396 NULL,
00397 NULL,
00398 TileLoop_Clear,
00399 ChangeTileOwner_Clear,
00400 NULL,
00401 NULL,
00402 GetFoundation_Clear,
00403 TerraformTile_Clear,
00404 };