00001
00002
00003 #include "stdafx.h"
00004 #include "openttd.h"
00005 #include "bridge_map.h"
00006 #include "heightmap.h"
00007 #include "clear_map.h"
00008 #include "spritecache.h"
00009 #include <stdarg.h>
00010 #include "viewport_func.h"
00011 #include "command_func.h"
00012 #include "landscape.h"
00013 #include "variables.h"
00014 #include "void_map.h"
00015 #include "water_map.h"
00016 #include "tgp.h"
00017 #include "genworld.h"
00018 #include "tile_cmd.h"
00019 #include "core/alloc_func.hpp"
00020 #include "fios.h"
00021 #include "window_func.h"
00022 #include "functions.h"
00023 #include "date_func.h"
00024 #include "vehicle_func.h"
00025 #include "settings_type.h"
00026 #include "water.h"
00027
00028 #include "table/sprites.h"
00029
00030 extern const TileTypeProcs
00031 _tile_type_clear_procs,
00032 _tile_type_rail_procs,
00033 _tile_type_road_procs,
00034 _tile_type_town_procs,
00035 _tile_type_trees_procs,
00036 _tile_type_station_procs,
00037 _tile_type_water_procs,
00038 _tile_type_dummy_procs,
00039 _tile_type_industry_procs,
00040 _tile_type_tunnelbridge_procs,
00041 _tile_type_unmovable_procs;
00042
00043 const TileTypeProcs * const _tile_type_procs[16] = {
00044 &_tile_type_clear_procs,
00045 &_tile_type_rail_procs,
00046 &_tile_type_road_procs,
00047 &_tile_type_town_procs,
00048 &_tile_type_trees_procs,
00049 &_tile_type_station_procs,
00050 &_tile_type_water_procs,
00051 &_tile_type_dummy_procs,
00052 &_tile_type_industry_procs,
00053 &_tile_type_tunnelbridge_procs,
00054 &_tile_type_unmovable_procs,
00055 };
00056
00057
00058 const byte _tileh_to_sprite[32] = {
00059 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
00060 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 17, 0, 15, 18, 0,
00061 };
00062
00063 SnowLine *_snow_line = NULL;
00064
00073 uint ApplyFoundationToSlope(Foundation f, Slope *s)
00074 {
00075
00076 if (!IsFoundation(f)) return 0;
00077
00078 if (IsLeveledFoundation(f)) {
00079 uint dz = TILE_HEIGHT + (IsSteepSlope(*s) ? TILE_HEIGHT : 0);
00080 *s = SLOPE_FLAT;
00081 return dz;
00082 }
00083
00084 if (f != FOUNDATION_STEEP_BOTH && IsNonContinuousFoundation(f)) {
00085 *s = HalftileSlope(*s, GetHalftileFoundationCorner(f));
00086 return 0;
00087 }
00088
00089 if (IsSpecialRailFoundation(f)) {
00090 *s = SlopeWithThreeCornersRaised(OppositeCorner(GetRailFoundationCorner(f)));
00091 return 0;
00092 }
00093
00094 uint dz = IsSteepSlope(*s) ? TILE_HEIGHT : 0;
00095 Corner highest_corner = GetHighestSlopeCorner(*s);
00096
00097 switch (f) {
00098 case FOUNDATION_INCLINED_X:
00099 *s = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? SLOPE_SW : SLOPE_NE);
00100 break;
00101
00102 case FOUNDATION_INCLINED_Y:
00103 *s = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? SLOPE_SE : SLOPE_NW);
00104 break;
00105
00106 case FOUNDATION_STEEP_LOWER:
00107 *s = SlopeWithOneCornerRaised(highest_corner);
00108 break;
00109
00110 case FOUNDATION_STEEP_BOTH:
00111 *s = HalftileSlope(SlopeWithOneCornerRaised(highest_corner), highest_corner);
00112 break;
00113
00114 default: NOT_REACHED();
00115 }
00116 return dz;
00117 }
00118
00119
00120 uint GetPartialZ(int x, int y, Slope corners)
00121 {
00122 if (IsHalftileSlope(corners)) {
00123 switch (GetHalftileSlopeCorner(corners)) {
00124 case CORNER_W:
00125 if (x - y >= 0) return GetSlopeMaxZ(corners);
00126 break;
00127
00128 case CORNER_S:
00129 if (x - (y ^ 0xF) >= 0) return GetSlopeMaxZ(corners);
00130 break;
00131
00132 case CORNER_E:
00133 if (y - x >= 0) return GetSlopeMaxZ(corners);
00134 break;
00135
00136 case CORNER_N:
00137 if ((y ^ 0xF) - x >= 0) return GetSlopeMaxZ(corners);
00138 break;
00139
00140 default: NOT_REACHED();
00141 }
00142 }
00143
00144 int z = 0;
00145
00146 switch (RemoveHalftileSlope(corners)) {
00147 case SLOPE_W:
00148 if (x - y >= 0)
00149 z = (x - y) >> 1;
00150 break;
00151
00152 case SLOPE_S:
00153 y ^= 0xF;
00154 if ( (x - y) >= 0)
00155 z = (x - y) >> 1;
00156 break;
00157
00158 case SLOPE_SW:
00159 z = (x >> 1) + 1;
00160 break;
00161
00162 case SLOPE_E:
00163 if (y - x >= 0)
00164 z = (y - x) >> 1;
00165 break;
00166
00167 case SLOPE_EW:
00168 case SLOPE_NS:
00169 case SLOPE_ELEVATED:
00170 z = 4;
00171 break;
00172
00173 case SLOPE_SE:
00174 z = (y >> 1) + 1;
00175 break;
00176
00177 case SLOPE_WSE:
00178 z = 8;
00179 y ^= 0xF;
00180 if (x - y < 0)
00181 z += (x - y) >> 1;
00182 break;
00183
00184 case SLOPE_N:
00185 y ^= 0xF;
00186 if (y - x >= 0)
00187 z = (y - x) >> 1;
00188 break;
00189
00190 case SLOPE_NW:
00191 z = (y ^ 0xF) >> 1;
00192 break;
00193
00194 case SLOPE_NWS:
00195 z = 8;
00196 if (x - y < 0)
00197 z += (x - y) >> 1;
00198 break;
00199
00200 case SLOPE_NE:
00201 z = (x ^ 0xF) >> 1;
00202 break;
00203
00204 case SLOPE_ENW:
00205 z = 8;
00206 y ^= 0xF;
00207 if (y - x < 0)
00208 z += (y - x) >> 1;
00209 break;
00210
00211 case SLOPE_SEN:
00212 z = 8;
00213 if (y - x < 0)
00214 z += (y - x) >> 1;
00215 break;
00216
00217 case SLOPE_STEEP_S:
00218 z = 1 + ((x + y) >> 1);
00219 break;
00220
00221 case SLOPE_STEEP_W:
00222 z = 1 + ((x + (y ^ 0xF)) >> 1);
00223 break;
00224
00225 case SLOPE_STEEP_N:
00226 z = 1 + (((x ^ 0xF) + (y ^ 0xF)) >> 1);
00227 break;
00228
00229 case SLOPE_STEEP_E:
00230 z = 1 + (((x ^ 0xF) + y) >> 1);
00231 break;
00232
00233 default: break;
00234 }
00235
00236 return z;
00237 }
00238
00239 uint GetSlopeZ(int x, int y)
00240 {
00241 TileIndex tile = TileVirtXY(x, y);
00242
00243 return _tile_type_procs[GetTileType(tile)]->get_slope_z_proc(tile, x, y);
00244 }
00245
00255 int GetSlopeZInCorner(Slope tileh, Corner corner)
00256 {
00257 assert(!IsHalftileSlope(tileh));
00258 return ((tileh & SlopeWithOneCornerRaised(corner)) != 0 ? TILE_HEIGHT : 0) + (tileh == SteepSlope(corner) ? TILE_HEIGHT : 0);
00259 }
00260
00273 void GetSlopeZOnEdge(Slope tileh, DiagDirection edge, int *z1, int *z2)
00274 {
00275 static const Slope corners[4][4] = {
00276
00277
00278 {SLOPE_E, SLOPE_N, SLOPE_STEEP_E, SLOPE_STEEP_N},
00279 {SLOPE_S, SLOPE_E, SLOPE_STEEP_S, SLOPE_STEEP_E},
00280 {SLOPE_S, SLOPE_W, SLOPE_STEEP_S, SLOPE_STEEP_W},
00281 {SLOPE_W, SLOPE_N, SLOPE_STEEP_W, SLOPE_STEEP_N},
00282 };
00283
00284 int halftile_test = (IsHalftileSlope(tileh) ? SlopeWithOneCornerRaised(GetHalftileSlopeCorner(tileh)) : 0);
00285 if (halftile_test == corners[edge][0]) *z2 += TILE_HEIGHT;
00286 if (halftile_test == corners[edge][1]) *z1 += TILE_HEIGHT;
00287
00288 if ((tileh & corners[edge][0]) != 0) *z1 += TILE_HEIGHT;
00289 if ((tileh & corners[edge][1]) != 0) *z2 += TILE_HEIGHT;
00290 if (RemoveHalftileSlope(tileh) == corners[edge][2]) *z1 += TILE_HEIGHT;
00291 if (RemoveHalftileSlope(tileh) == corners[edge][3]) *z2 += TILE_HEIGHT;
00292 }
00293
00302 Slope GetFoundationSlope(TileIndex tile, uint* z)
00303 {
00304 Slope tileh = GetTileSlope(tile, z);
00305 Foundation f = _tile_type_procs[GetTileType(tile)]->get_foundation_proc(tile, tileh);
00306 uint z_inc = ApplyFoundationToSlope(f, &tileh);
00307 if (z != NULL) *z += z_inc;
00308 return tileh;
00309 }
00310
00311
00312 static bool HasFoundationNW(TileIndex tile, Slope slope_here, uint z_here)
00313 {
00314 uint z;
00315
00316 int z_W_here = z_here;
00317 int z_N_here = z_here;
00318 GetSlopeZOnEdge(slope_here, DIAGDIR_NW, &z_W_here, &z_N_here);
00319
00320 Slope slope = GetFoundationSlope(TILE_ADDXY(tile, 0, -1), &z);
00321 int z_W = z;
00322 int z_N = z;
00323 GetSlopeZOnEdge(slope, DIAGDIR_SE, &z_W, &z_N);
00324
00325 return (z_N_here > z_N) || (z_W_here > z_W);
00326 }
00327
00328
00329 static bool HasFoundationNE(TileIndex tile, Slope slope_here, uint z_here)
00330 {
00331 uint z;
00332
00333 int z_E_here = z_here;
00334 int z_N_here = z_here;
00335 GetSlopeZOnEdge(slope_here, DIAGDIR_NE, &z_E_here, &z_N_here);
00336
00337 Slope slope = GetFoundationSlope(TILE_ADDXY(tile, -1, 0), &z);
00338 int z_E = z;
00339 int z_N = z;
00340 GetSlopeZOnEdge(slope, DIAGDIR_SW, &z_E, &z_N);
00341
00342 return (z_N_here > z_N) || (z_E_here > z_E);
00343 }
00344
00345
00346 void DrawFoundation(TileInfo *ti, Foundation f)
00347 {
00348 if (!IsFoundation(f)) return;
00349
00350
00351 assert(f != FOUNDATION_STEEP_BOTH);
00352
00353 uint sprite_block = 0;
00354 uint z;
00355 Slope slope = GetFoundationSlope(ti->tile, &z);
00356
00357
00358
00359
00360
00361
00362
00363 if (!HasFoundationNW(ti->tile, slope, z)) sprite_block += 1;
00364 if (!HasFoundationNE(ti->tile, slope, z)) sprite_block += 2;
00365
00366
00367 SpriteID leveled_base = (sprite_block == 0 ? (int)SPR_FOUNDATION_BASE : (SPR_SLOPES_VIRTUAL_BASE + sprite_block * SPR_TRKFOUND_BLOCK_SIZE));
00368 SpriteID inclined_base = SPR_SLOPES_VIRTUAL_BASE + SPR_SLOPES_INCLINED_OFFSET + sprite_block * SPR_TRKFOUND_BLOCK_SIZE;
00369 SpriteID halftile_base = SPR_HALFTILE_FOUNDATION_BASE + sprite_block * SPR_HALFTILE_BLOCK_SIZE;
00370
00371 if (IsSteepSlope(ti->tileh)) {
00372 if (!IsNonContinuousFoundation(f)) {
00373
00374 AddSortableSpriteToDraw(
00375 leveled_base + (ti->tileh & ~SLOPE_STEEP), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z
00376 );
00377 }
00378
00379 Corner highest_corner = GetHighestSlopeCorner(ti->tileh);
00380 ti->z += ApplyFoundationToSlope(f, &ti->tileh);
00381
00382 if (IsInclinedFoundation(f)) {
00383
00384 byte inclined = highest_corner * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
00385
00386 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y, 16, 16, 1, ti->z);
00387 OffsetGroundSprite(31, 9);
00388 } else if (IsLeveledFoundation(f)) {
00389 AddSortableSpriteToDraw(leveled_base + SlopeWithOneCornerRaised(highest_corner), PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z - TILE_HEIGHT);
00390 OffsetGroundSprite(31, 1);
00391 } else if (f == FOUNDATION_STEEP_LOWER) {
00392
00393 OffsetGroundSprite(31, 1);
00394 } else {
00395
00396 int x_bb = (((highest_corner == CORNER_W) || (highest_corner == CORNER_S)) ? 8 : 0);
00397 int y_bb = (((highest_corner == CORNER_S) || (highest_corner == CORNER_E)) ? 8 : 0);
00398
00399 AddSortableSpriteToDraw(halftile_base + highest_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z + TILE_HEIGHT);
00400 OffsetGroundSprite(31, 9);
00401 }
00402 } else {
00403 if (IsLeveledFoundation(f)) {
00404
00405 AddSortableSpriteToDraw(leveled_base + ti->tileh, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
00406 OffsetGroundSprite(31, 1);
00407 } else if (IsNonContinuousFoundation(f)) {
00408
00409 Corner halftile_corner = GetHalftileFoundationCorner(f);
00410 int x_bb = (((halftile_corner == CORNER_W) || (halftile_corner == CORNER_S)) ? 8 : 0);
00411 int y_bb = (((halftile_corner == CORNER_S) || (halftile_corner == CORNER_E)) ? 8 : 0);
00412
00413 AddSortableSpriteToDraw(halftile_base + halftile_corner, PAL_NONE, ti->x + x_bb, ti->y + y_bb, 8, 8, 7, ti->z);
00414 OffsetGroundSprite(31, 9);
00415 } else if (IsSpecialRailFoundation(f)) {
00416
00417 SpriteID spr;
00418 if (ti->tileh == SLOPE_NS || ti->tileh == SLOPE_EW) {
00419
00420 spr = leveled_base + SlopeWithThreeCornersRaised(GetRailFoundationCorner(f));
00421 } else {
00422
00423 spr = inclined_base + 2 * GetRailFoundationCorner(f) + ((ti->tileh == SLOPE_SW || ti->tileh == SLOPE_NE) ? 1 : 0);
00424 }
00425 AddSortableSpriteToDraw(spr, PAL_NONE, ti->x, ti->y, 16, 16, 7, ti->z);
00426 OffsetGroundSprite(31, 9);
00427 } else {
00428
00429 byte inclined = GetHighestSlopeCorner(ti->tileh) * 2 + (f == FOUNDATION_INCLINED_Y ? 1 : 0);
00430
00431 AddSortableSpriteToDraw(inclined_base + inclined, PAL_NONE, ti->x, ti->y, 16, 16, 1, ti->z);
00432 OffsetGroundSprite(31, 9);
00433 }
00434 ti->z += ApplyFoundationToSlope(f, &ti->tileh);
00435 }
00436 }
00437
00438 void DoClearSquare(TileIndex tile)
00439 {
00440 MakeClear(tile, CLEAR_GRASS, _generating_world ? 3 : 0);
00441 MarkTileDirtyByTile(tile);
00442 }
00443
00453 TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
00454 {
00455 return _tile_type_procs[GetTileType(tile)]->get_tile_track_status_proc(tile, mode, sub_mode, side);
00456 }
00457
00458 void ChangeTileOwner(TileIndex tile, PlayerID old_player, PlayerID new_player)
00459 {
00460 _tile_type_procs[GetTileType(tile)]->change_tile_owner_proc(tile, old_player, new_player);
00461 }
00462
00463 void GetAcceptedCargo(TileIndex tile, AcceptedCargo ac)
00464 {
00465 memset(ac, 0, sizeof(AcceptedCargo));
00466 _tile_type_procs[GetTileType(tile)]->get_accepted_cargo_proc(tile, ac);
00467 }
00468
00469 void AnimateTile(TileIndex tile)
00470 {
00471 _tile_type_procs[GetTileType(tile)]->animate_tile_proc(tile);
00472 }
00473
00474 void ClickTile(TileIndex tile)
00475 {
00476 _tile_type_procs[GetTileType(tile)]->click_tile_proc(tile);
00477 }
00478
00479 void GetTileDesc(TileIndex tile, TileDesc *td)
00480 {
00481 _tile_type_procs[GetTileType(tile)]->get_tile_desc_proc(tile, td);
00482 }
00483
00488 bool IsSnowLineSet(void)
00489 {
00490 return _snow_line != NULL;
00491 }
00492
00497 void SetSnowLine(byte table[SNOW_LINE_MONTHS][SNOW_LINE_DAYS])
00498 {
00499 _snow_line = CallocT<SnowLine>(1);
00500 memcpy(_snow_line->table, table, sizeof(_snow_line->table));
00501
00502 for (uint i = 0; i < SNOW_LINE_MONTHS; i++) {
00503 for (uint j = 0; j < SNOW_LINE_DAYS; j++) {
00504 _snow_line->highest_value = max(_snow_line->highest_value, table[i][j]);
00505 }
00506 }
00507 }
00508
00513 byte GetSnowLine(void)
00514 {
00515 if (_snow_line == NULL) return _opt.snow_line;
00516
00517 YearMonthDay ymd;
00518 ConvertDateToYMD(_date, &ymd);
00519 return _snow_line->table[ymd.month][ymd.day];
00520 }
00521
00526 byte HighestSnowLine(void)
00527 {
00528 return _snow_line == NULL ? _opt.snow_line : _snow_line->highest_value;
00529 }
00530
00534 void ClearSnowLine(void)
00535 {
00536 free(_snow_line);
00537 _snow_line = NULL;
00538 }
00539
00546 CommandCost CmdLandscapeClear(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
00547 {
00548 return _tile_type_procs[GetTileType(tile)]->clear_tile_proc(tile, flags);
00549 }
00550
00557 CommandCost CmdClearArea(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
00558 {
00559 CommandCost ret, money;
00560 CommandCost cost(EXPENSES_CONSTRUCTION);
00561 int ex;
00562 int ey;
00563 int sx, sy;
00564 int x, y;
00565 bool success = false;
00566
00567 if (p1 >= MapSize()) return CMD_ERROR;
00568
00569
00570 ex = TileX(tile);
00571 ey = TileY(tile);
00572 sx = TileX(p1);
00573 sy = TileY(p1);
00574 if (ex < sx) Swap(ex, sx);
00575 if (ey < sy) Swap(ey, sy);
00576
00577 money.AddCost(GetAvailableMoneyForCommand());
00578
00579 for (x = sx; x <= ex; ++x) {
00580 for (y = sy; y <= ey; ++y) {
00581 ret = DoCommand(TileXY(x, y), 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
00582 if (CmdFailed(ret)) continue;
00583 success = true;
00584
00585 if (flags & DC_EXEC) {
00586 money.AddCost(-ret.GetCost());
00587 if (ret.GetCost() > 0 && money.GetCost() < 0) {
00588 _additional_cash_required = ret.GetCost();
00589 return cost;
00590 }
00591 DoCommand(TileXY(x, y), 0, 0, flags, CMD_LANDSCAPE_CLEAR);
00592
00593
00594 if ((x == sx || x == ex) && (y == sy || y == ey)) {
00595
00596 CreateEffectVehicleAbove(x * TILE_SIZE + TILE_SIZE / 2, y * TILE_SIZE + TILE_SIZE / 2, 2,
00597 sy == ey && sx == ex ? EV_EXPLOSION_SMALL : EV_EXPLOSION_LARGE
00598 );
00599 }
00600 }
00601 cost.AddCost(ret);
00602 }
00603 }
00604
00605 return (success) ? cost : CMD_ERROR;
00606 }
00607
00608
00609 #define TILELOOP_BITS 4
00610 #define TILELOOP_SIZE (1 << TILELOOP_BITS)
00611 #define TILELOOP_ASSERTMASK ((TILELOOP_SIZE - 1) + ((TILELOOP_SIZE - 1) << MapLogX()))
00612 #define TILELOOP_CHKMASK (((1 << (MapLogX() - TILELOOP_BITS))-1) << TILELOOP_BITS)
00613
00614 void RunTileLoop()
00615 {
00616 TileIndex tile;
00617 uint count;
00618
00619 tile = _cur_tileloop_tile;
00620
00621 assert( (tile & ~TILELOOP_ASSERTMASK) == 0);
00622 count = (MapSizeX() / TILELOOP_SIZE) * (MapSizeY() / TILELOOP_SIZE);
00623 do {
00624 _tile_type_procs[GetTileType(tile)]->tile_loop_proc(tile);
00625
00626 if (TileX(tile) < MapSizeX() - TILELOOP_SIZE) {
00627 tile += TILELOOP_SIZE;
00628 } else {
00629 tile = TILE_MASK(tile - TILELOOP_SIZE * (MapSizeX() / TILELOOP_SIZE - 1) + TileDiffXY(0, TILELOOP_SIZE));
00630 }
00631 } while (--count);
00632 assert( (tile & ~TILELOOP_ASSERTMASK) == 0);
00633
00634 tile += 9;
00635 if (tile & TILELOOP_CHKMASK)
00636 tile = (tile + MapSizeX()) & TILELOOP_ASSERTMASK;
00637 _cur_tileloop_tile = tile;
00638 }
00639
00640 void InitializeLandscape()
00641 {
00642 uint maxx = MapMaxX();
00643 uint maxy = MapMaxY();
00644 uint sizex = MapSizeX();
00645 uint x;
00646 uint y;
00647
00648 for (y = 0; y < maxy; y++) {
00649 for (x = 0; x < maxx; x++) {
00650 MakeClear(sizex * y + x, CLEAR_GRASS, 3);
00651 SetTileHeight(sizex * y + x, 0);
00652 SetTropicZone(sizex * y + x, TROPICZONE_NORMAL);
00653 ClearBridgeMiddle(sizex * y + x);
00654 }
00655 MakeVoid(sizex * y + x);
00656 }
00657 for (x = 0; x < sizex; x++) MakeVoid(sizex * y + x);
00658 }
00659
00660 static const byte _genterrain_tbl_1[5] = { 10, 22, 33, 37, 4 };
00661 static const byte _genterrain_tbl_2[5] = { 0, 0, 0, 0, 33 };
00662
00663 static void GenerateTerrain(int type, int flag)
00664 {
00665 uint32 r;
00666 uint x;
00667 uint y;
00668 uint w;
00669 uint h;
00670 const Sprite* templ;
00671 const byte *p;
00672 Tile* tile;
00673 byte direction;
00674
00675 r = Random();
00676 templ = GetSprite((((r >> 24) * _genterrain_tbl_1[type]) >> 8) + _genterrain_tbl_2[type] + 4845);
00677
00678 x = r & MapMaxX();
00679 y = (r >> MapLogX()) & MapMaxY();
00680
00681
00682 if (x < 2 || y < 2) return;
00683
00684 direction = GB(r, 22, 2);
00685 if (direction & 1) {
00686 w = templ->height;
00687 h = templ->width;
00688 } else {
00689 w = templ->width;
00690 h = templ->height;
00691 }
00692 p = templ->data;
00693
00694 if (flag & 4) {
00695 uint xw = x * MapSizeY();
00696 uint yw = y * MapSizeX();
00697 uint bias = (MapSizeX() + MapSizeY()) * 16;
00698
00699 switch (flag & 3) {
00700 case 0:
00701 if (xw + yw > MapSize() - bias) return;
00702 break;
00703
00704 case 1:
00705 if (yw < xw + bias) return;
00706 break;
00707
00708 case 2:
00709 if (xw + yw < MapSize() + bias) return;
00710 break;
00711
00712 case 3:
00713 if (xw < yw + bias) return;
00714 break;
00715 }
00716 }
00717
00718 if (x + w >= MapMaxX() - 1) return;
00719 if (y + h >= MapMaxY() - 1) return;
00720
00721 tile = &_m[TileXY(x, y)];
00722
00723 switch (direction) {
00724 case 0:
00725 do {
00726 Tile* tile_cur = tile;
00727 uint w_cur;
00728
00729 for (w_cur = w; w_cur != 0; --w_cur) {
00730 if (*p >= tile_cur->type_height) tile_cur->type_height = *p;
00731 p++;
00732 tile_cur++;
00733 }
00734 tile += TileDiffXY(0, 1);
00735 } while (--h != 0);
00736 break;
00737
00738 case 1:
00739 do {
00740 Tile* tile_cur = tile;
00741 uint h_cur;
00742
00743 for (h_cur = h; h_cur != 0; --h_cur) {
00744 if (*p >= tile_cur->type_height) tile_cur->type_height = *p;
00745 p++;
00746 tile_cur += TileDiffXY(0, 1);
00747 }
00748 tile++;
00749 } while (--w != 0);
00750 break;
00751
00752 case 2:
00753 tile += TileDiffXY(w - 1, 0);
00754 do {
00755 Tile* tile_cur = tile;
00756 uint w_cur;
00757
00758 for (w_cur = w; w_cur != 0; --w_cur) {
00759 if (*p >= tile_cur->type_height) tile_cur->type_height = *p;
00760 p++;
00761 tile_cur--;
00762 }
00763 tile += TileDiffXY(0, 1);
00764 } while (--h != 0);
00765 break;
00766
00767 case 3:
00768 tile += TileDiffXY(0, h - 1);
00769 do {
00770 Tile* tile_cur = tile;
00771 uint h_cur;
00772
00773 for (h_cur = h; h_cur != 0; --h_cur) {
00774 if (*p >= tile_cur->type_height) tile_cur->type_height = *p;
00775 p++;
00776 tile_cur -= TileDiffXY(0, 1);
00777 }
00778 tile++;
00779 } while (--w != 0);
00780 break;
00781 }
00782 }
00783
00784
00785 #include "table/genland.h"
00786
00787 static void CreateDesertOrRainForest()
00788 {
00789 TileIndex tile;
00790 TileIndex update_freq = MapSize() / 4;
00791 const TileIndexDiffC *data;
00792 uint i;
00793
00794 for (tile = 0; tile != MapSize(); ++tile) {
00795 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00796
00797 for (data = _make_desert_or_rainforest_data;
00798 data != endof(_make_desert_or_rainforest_data); ++data) {
00799 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
00800 if (TileHeight(t) >= 4 || IsTileType(t, MP_WATER)) break;
00801 }
00802 if (data == endof(_make_desert_or_rainforest_data))
00803 SetTropicZone(tile, TROPICZONE_DESERT);
00804 }
00805
00806 for (i = 0; i != 256; i++) {
00807 if ((i % 64) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00808
00809 RunTileLoop();
00810 }
00811
00812 for (tile = 0; tile != MapSize(); ++tile) {
00813 if ((tile % update_freq) == 0) IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00814
00815 for (data = _make_desert_or_rainforest_data;
00816 data != endof(_make_desert_or_rainforest_data); ++data) {
00817 TileIndex t = TILE_MASK(tile + ToTileIndexDiff(*data));
00818 if (IsTileType(t, MP_CLEAR) && IsClearGround(t, CLEAR_DESERT)) break;
00819 }
00820 if (data == endof(_make_desert_or_rainforest_data))
00821 SetTropicZone(tile, TROPICZONE_RAINFOREST);
00822 }
00823 }
00824
00825 void GenerateLandscape(byte mode)
00826 {
00827 const int gwp_desert_amount = 4 + 8;
00828 uint i;
00829 uint flag;
00830 uint32 r;
00831
00832 if (mode == GW_HEIGHTMAP) {
00833 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 1 + gwp_desert_amount : 1);
00834 LoadHeightmap(_file_to_saveload.name);
00835 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00836 } else if (_patches.land_generator == LG_TERRAGENESIS) {
00837 SetGeneratingWorldProgress(GWP_LANDSCAPE, (_opt.landscape == LT_TROPIC) ? 3 + gwp_desert_amount : 3);
00838 GenerateTerrainPerlin();
00839 } else {
00840 switch (_opt.landscape) {
00841 case LT_ARCTIC:
00842 SetGeneratingWorldProgress(GWP_LANDSCAPE, 2);
00843
00844 for (i = ScaleByMapSize((Random() & 0x7F) + 950); i != 0; --i) {
00845 GenerateTerrain(2, 0);
00846 }
00847 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00848
00849 r = Random();
00850 flag = GB(r, 0, 2) | 4;
00851 for (i = ScaleByMapSize(GB(r, 16, 7) + 450); i != 0; --i) {
00852 GenerateTerrain(4, flag);
00853 }
00854 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00855 break;
00856
00857 case LT_TROPIC:
00858 SetGeneratingWorldProgress(GWP_LANDSCAPE, 3 + gwp_desert_amount);
00859
00860 for (i = ScaleByMapSize((Random() & 0x7F) + 170); i != 0; --i) {
00861 GenerateTerrain(0, 0);
00862 }
00863 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00864
00865 r = Random();
00866 flag = GB(r, 0, 2) | 4;
00867 for (i = ScaleByMapSize(GB(r, 16, 8) + 1700); i != 0; --i) {
00868 GenerateTerrain(0, flag);
00869 }
00870 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00871
00872 flag ^= 2;
00873
00874 for (i = ScaleByMapSize((Random() & 0x7F) + 410); i != 0; --i) {
00875 GenerateTerrain(3, flag);
00876 }
00877 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00878 break;
00879
00880 default:
00881 SetGeneratingWorldProgress(GWP_LANDSCAPE, 1);
00882
00883 i = ScaleByMapSize((Random() & 0x7F) + (3 - _opt.diff.quantity_sea_lakes) * 256 + 100);
00884 for (; i != 0; --i) {
00885 GenerateTerrain(_opt.diff.terrain_type, 0);
00886 }
00887 IncreaseGeneratingWorldProgress(GWP_LANDSCAPE);
00888 break;
00889 }
00890 }
00891
00892 ConvertGroundTilesIntoWaterTiles();
00893
00894 if (_opt.landscape == LT_TROPIC) CreateDesertOrRainForest();
00895 }
00896
00897 void OnTick_Town();
00898 void OnTick_Trees();
00899 void OnTick_Station();
00900 void OnTick_Industry();
00901
00902 void OnTick_Players();
00903 void OnTick_Train();
00904
00905 void CallLandscapeTick()
00906 {
00907 OnTick_Town();
00908 OnTick_Trees();
00909 OnTick_Station();
00910 OnTick_Industry();
00911
00912 OnTick_Players();
00913 OnTick_Train();
00914 }
00915
00916 TileIndex AdjustTileCoordRandomly(TileIndex a, byte rng)
00917 {
00918 int rn = rng;
00919 uint32 r = Random();
00920
00921 return TILE_MASK(TileXY(
00922 TileX(a) + (GB(r, 0, 8) * rn * 2 >> 8) - rn,
00923 TileY(a) + (GB(r, 8, 8) * rn * 2 >> 8) - rn
00924 ));
00925 }