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