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