00001
00002
00003
00004
00005
00006
00007
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
00167 if (!IsSnowTile(tile)) return;
00168 } else {
00169
00170 if (!IsSnowTile(tile)) {
00171 MakeSnow(tile);
00172 MarkTileDirtyByTile(tile);
00173 return;
00174 }
00175 }
00176
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
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
00208 uint current = 0;
00209 if (IsClearGround(tile, CLEAR_DESERT)) current = GetClearDensity(tile);
00210
00211
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
00225 SetClearGroundDensity(tile, CLEAR_DESERT, expected);
00226 }
00227
00228 MarkTileDirtyByTile(tile);
00229 }
00230
00231 static void TileLoop_Clear(TileIndex tile)
00232 {
00233
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
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
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
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 };