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