OpenTTD Source 20250205-master-gfd85ab1e2c
tree_cmd.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "clear_map.h"
12#include "landscape.h"
13#include "tree_map.h"
14#include "viewport_func.h"
15#include "command_func.h"
16#include "town.h"
17#include "genworld.h"
18#include "clear_func.h"
19#include "company_func.h"
20#include "sound_func.h"
21#include "water.h"
22#include "company_base.h"
23#include "core/random_func.hpp"
24#include "newgrf_generic.h"
26#include "tree_cmd.h"
27#include "landscape_cmd.h"
28
29#include "table/strings.h"
30#include "table/tree_land.h"
31#include "table/clear_land.h"
32
33#include "safeguards.h"
34
45
53
56
57static const uint16_t DEFAULT_TREE_STEPS = 1000;
58static const uint16_t DEFAULT_RAINFOREST_TREE_STEPS = 15000;
59static const uint16_t EDITOR_TREE_DIV = 5;
60
69static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
70{
71 switch (GetTileType(tile)) {
72 case MP_WATER:
73 return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile));
74
75 case MP_CLEAR:
76 return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && GetRawClearGround(tile) != CLEAR_ROCKS &&
77 (allow_desert || !IsClearGround(tile, CLEAR_DESERT));
78
79 default: return false;
80 }
81}
82
94static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, TreeGrowthStage growth)
95{
96 assert(treetype != TREE_INVALID);
97 assert(CanPlantTreesOnTile(tile, true));
98
99 TreeGround ground;
100 uint density = 3;
101
102 switch (GetTileType(tile)) {
103 case MP_WATER:
104 ground = TREE_GROUND_SHORE;
106 break;
107
108 case MP_CLEAR:
109 switch (GetClearGround(tile)) {
110 case CLEAR_GRASS: ground = TREE_GROUND_GRASS; break;
111 case CLEAR_ROUGH: ground = TREE_GROUND_ROUGH; break;
113 default: ground = TREE_GROUND_SNOW_DESERT; break;
114 }
115 if (GetClearGround(tile) != CLEAR_ROUGH) density = GetClearDensity(tile);
116 break;
117
118 default: NOT_REACHED();
119 }
120
121 MakeTree(tile, treetype, count, growth, ground, density);
122}
123
135static TreeType GetRandomTreeType(TileIndex tile, uint seed)
136{
138 case LandscapeType::Temperate:
139 return static_cast<TreeType>(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE);
140
141 case LandscapeType::Arctic:
142 return static_cast<TreeType>(seed * TREE_COUNT_SUB_ARCTIC / 256 + TREE_SUB_ARCTIC);
143
144 case LandscapeType::Tropic:
145 switch (GetTropicZone(tile)) {
146 case TROPICZONE_NORMAL: return static_cast<TreeType>(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL);
147 case TROPICZONE_DESERT: return static_cast<TreeType>((seed > 12) ? TREE_INVALID : TREE_CACTUS);
148 default: return static_cast<TreeType>(seed * TREE_COUNT_RAINFOREST / 256 + TREE_RAINFOREST);
149 }
150
151 default:
152 return static_cast<TreeType>(seed * TREE_COUNT_TOYLAND / 256 + TREE_TOYLAND);
153 }
154}
155
165static void PlaceTree(TileIndex tile, uint32_t r)
166{
167 TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8));
168
169 if (tree != TREE_INVALID) {
170 PlantTreesOnTile(tile, tree, GB(r, 22, 2), static_cast<TreeGrowthStage>(std::min<uint8_t>(GB(r, 16, 3), 6)));
172
173 /* Rerandomize ground, if neither snow nor shore */
174 TreeGround ground = GetTreeGround(tile);
175 if (ground != TREE_GROUND_SNOW_DESERT && ground != TREE_GROUND_ROUGH_SNOW && ground != TREE_GROUND_SHORE) {
176 SetTreeGroundDensity(tile, (TreeGround)GB(r, 28, 1), 3);
177 }
178 }
179}
180
187static void PlaceTreeGroups(uint num_groups)
188{
189 do {
190 TileIndex center_tile = RandomTile();
191
192 for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) {
193 uint32_t r = Random();
194 int x = GB(r, 0, 5) - 16;
195 int y = GB(r, 8, 5) - 16;
196 uint dist = abs(x) + abs(y);
197 TileIndex cur_tile = TileAddWrap(center_tile, x, y);
198
200
201 if (cur_tile != INVALID_TILE && dist <= 13 && CanPlantTreesOnTile(cur_tile, true)) {
202 PlaceTree(cur_tile, r);
203 }
204 }
205
206 } while (--num_groups);
207}
208
218static void PlaceTreeAtSameHeight(TileIndex tile, int height)
219{
220 for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) {
221 uint32_t r = Random();
222 int x = GB(r, 0, 5) - 16;
223 int y = GB(r, 8, 5) - 16;
224 TileIndex cur_tile = TileAddWrap(tile, x, y);
225 if (cur_tile == INVALID_TILE) continue;
226
227 /* Keep in range of the existing tree */
228 if (abs(x) + abs(y) > 16) continue;
229
230 /* Clear tile, no farm-tiles or rocks */
231 if (!CanPlantTreesOnTile(cur_tile, true)) continue;
232
233 /* Not too much height difference */
234 if (Delta(GetTileZ(cur_tile), height) > 2) continue;
235
236 /* Place one tree and quit */
237 PlaceTree(cur_tile, r);
238 break;
239 }
240}
241
248{
249 int i, j, ht;
250 uint8_t max_height = _settings_game.construction.map_height_limit;
251
253 if (_game_mode == GM_EDITOR) i /= EDITOR_TREE_DIV;
254 do {
255 uint32_t r = Random();
256 TileIndex tile = RandomTileSeed(r);
257
259
260 if (CanPlantTreesOnTile(tile, true)) {
261 PlaceTree(tile, r);
263
264 /* Place a number of trees based on the tile height.
265 * This gives a cool effect of multiple trees close together.
266 * It is almost real life ;) */
267 ht = GetTileZ(tile);
268 /* The higher we get, the more trees we plant */
269 j = GetTileZ(tile) * 2;
270 /* Above snowline more trees! */
271 if (_settings_game.game_creation.landscape == LandscapeType::Arctic && ht > GetSnowLine()) j *= 3;
272 /* Scale generation by maximum map height. */
273 if (max_height > MAP_HEIGHT_LIMIT_ORIGINAL) j = j * MAP_HEIGHT_LIMIT_ORIGINAL / max_height;
274 while (j--) {
275 PlaceTreeAtSameHeight(tile, ht);
276 }
277 }
278 } while (--i);
279
280 /* place extra trees at rainforest area */
281 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
283 if (_game_mode == GM_EDITOR) i /= EDITOR_TREE_DIV;
284
285 do {
286 uint32_t r = Random();
287 TileIndex tile = RandomTileSeed(r);
288
290
291 if (GetTropicZone(tile) == TROPICZONE_RAINFOREST && CanPlantTreesOnTile(tile, false)) {
292 PlaceTree(tile, r);
293 }
294 } while (--i);
295 }
296}
297
310uint PlaceTreeGroupAroundTile(TileIndex tile, TreeType treetype, uint radius, uint count, bool set_zone)
311{
312 assert(_game_mode == GM_EDITOR); // Due to InteractiveRandom being used in this function
313 assert(treetype < TREE_TOYLAND + TREE_COUNT_TOYLAND);
314 const bool allow_desert = treetype == TREE_CACTUS;
315 uint planted = 0;
316
317 for (; count > 0; count--) {
318 /* Simple quasi-normal distribution with range [-radius; radius) */
319 auto mkcoord = [&]() -> int32_t {
320 const uint32_t rand = InteractiveRandom();
321 const int32_t dist = GB<int32_t>(rand, 0, 8) + GB<int32_t>(rand, 8, 8) + GB<int32_t>(rand, 16, 8) + GB<int32_t>(rand, 24, 8);
322 const int32_t scu = dist * radius / 512;
323 return scu - radius;
324 };
325 const int32_t xofs = mkcoord();
326 const int32_t yofs = mkcoord();
327 const TileIndex tile_to_plant = TileAddWrap(tile, xofs, yofs);
328 if (tile_to_plant != INVALID_TILE) {
329 if (IsTileType(tile_to_plant, MP_TREES) && GetTreeCount(tile_to_plant) < 4) {
330 AddTreeCount(tile_to_plant, 1);
332 MarkTileDirtyByTile(tile_to_plant, 0);
333 planted++;
334 } else if (CanPlantTreesOnTile(tile_to_plant, allow_desert)) {
335 PlantTreesOnTile(tile_to_plant, treetype, 0, TreeGrowthStage::Grown);
336 MarkTileDirtyByTile(tile_to_plant, 0);
337 planted++;
338 }
339 }
340 }
341
342 if (set_zone && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) {
343 for (TileIndex t : TileArea(tile).Expand(radius)) {
344 if (GetTileType(t) != MP_VOID && DistanceSquare(tile, t) < radius * radius) SetTropicZone(t, TROPICZONE_RAINFOREST);
345 }
346 }
347
348 return planted;
349}
350
358{
359 uint i, total;
360
362
364 case TP_ORIGINAL: i = _settings_game.game_creation.landscape == LandscapeType::Arctic ? 15 : 6; break;
365 case TP_IMPROVED: i = _settings_game.game_creation.landscape == LandscapeType::Arctic ? 4 : 2; break;
366 default: NOT_REACHED();
367 }
368
371 total *= i;
372 uint num_groups = (_settings_game.game_creation.landscape != LandscapeType::Toyland) ? Map::ScaleBySize(GB(Random(), 0, 5) + 25) : 0;
373 total += num_groups * DEFAULT_TREE_STEPS;
375
376 if (num_groups != 0) PlaceTreeGroups(num_groups);
377
378 for (; i != 0; i--) {
380 }
381}
382
392CommandCost CmdPlantTree(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, uint8_t tree_to_plant, bool diagonal)
393{
396
397 if (start_tile >= Map::Size()) return CMD_ERROR;
398 /* Check the tree type within the current climate */
399 if (tree_to_plant != TREE_INVALID && !IsInsideBS(tree_to_plant, _tree_base_by_landscape[to_underlying(_settings_game.game_creation.landscape)], _tree_count_by_landscape[to_underlying(_settings_game.game_creation.landscape)])) return CMD_ERROR;
400
401 Company *c = (_game_mode != GM_EDITOR) ? Company::GetIfValid(_current_company) : nullptr;
402 int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16));
403
404 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
405 for (; *iter != INVALID_TILE; ++(*iter)) {
406 TileIndex current_tile = *iter;
407 switch (GetTileType(current_tile)) {
408 case MP_TREES:
409 /* no more space for trees? */
410 if (GetTreeCount(current_tile) == 4) {
411 msg = STR_ERROR_TREE_ALREADY_HERE;
412 continue;
413 }
414
415 /* Test tree limit. */
416 if (--limit < 1) {
417 msg = STR_ERROR_TREE_PLANT_LIMIT_REACHED;
418 break;
419 }
420
421 if (flags & DC_EXEC) {
422 AddTreeCount(current_tile, 1);
423 MarkTileDirtyByTile(current_tile);
424 if (c != nullptr) c->tree_limit -= 1 << 16;
425 }
426 /* 2x as expensive to add more trees to an existing tile */
427 cost.AddCost(_price[PR_BUILD_TREES] * 2);
428 break;
429
430 case MP_WATER:
431 if (!IsCoast(current_tile) || IsSlopeWithOneCornerRaised(GetTileSlope(current_tile))) {
432 msg = STR_ERROR_CAN_T_BUILD_ON_WATER;
433 continue;
434 }
435 [[fallthrough]];
436
437 case MP_CLEAR: {
438 if (IsBridgeAbove(current_tile)) {
439 msg = STR_ERROR_SITE_UNSUITABLE;
440 continue;
441 }
442
443 TreeType treetype = (TreeType)tree_to_plant;
444 /* Be a bit picky about which trees go where. */
445 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && treetype != TREE_INVALID && (
446 /* No cacti outside the desert */
447 (treetype == TREE_CACTUS && GetTropicZone(current_tile) != TROPICZONE_DESERT) ||
448 /* No rainforest trees outside the rainforest, except in the editor mode where it makes those tiles rainforest tile */
449 (IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(current_tile) != TROPICZONE_RAINFOREST && _game_mode != GM_EDITOR) ||
450 /* And no subtropical trees in the desert/rainforest */
451 (IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(current_tile) != TROPICZONE_NORMAL))) {
452 msg = STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE;
453 continue;
454 }
455
456 /* Test tree limit. */
457 if (--limit < 1) {
458 msg = STR_ERROR_TREE_PLANT_LIMIT_REACHED;
459 break;
460 }
461
462 if (IsTileType(current_tile, MP_CLEAR)) {
463 /* Remove fields or rocks. Note that the ground will get barrened */
464 switch (GetRawClearGround(current_tile)) {
465 case CLEAR_FIELDS:
466 case CLEAR_ROCKS: {
467 CommandCost ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, current_tile);
468 if (ret.Failed()) return ret;
469 cost.AddCost(ret);
470 break;
471 }
472
473 default: break;
474 }
475 }
476
477 if (_game_mode != GM_EDITOR && Company::IsValidID(_current_company)) {
479 if (t != nullptr) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM, flags);
480 }
481
482 if (flags & DC_EXEC) {
483 if (treetype == TREE_INVALID) {
484 treetype = GetRandomTreeType(current_tile, GB(Random(), 24, 8));
485 if (treetype == TREE_INVALID) treetype = TREE_CACTUS;
486 }
487
488 /* Plant full grown trees in scenario editor */
489 PlantTreesOnTile(current_tile, treetype, 0, _game_mode == GM_EDITOR ? TreeGrowthStage::Grown : TreeGrowthStage::Growing1);
490 MarkTileDirtyByTile(current_tile);
491 if (c != nullptr) c->tree_limit -= 1 << 16;
492
493 /* When planting rainforest-trees, set tropiczone to rainforest in editor. */
494 if (_game_mode == GM_EDITOR && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) {
496 }
497 }
498 cost.AddCost(_price[PR_BUILD_TREES]);
499 break;
500 }
501
502 default:
503 msg = STR_ERROR_SITE_UNSUITABLE;
504 break;
505 }
506
507 /* Tree limit used up? No need to check more. */
508 if (limit < 0) break;
509 }
510
511 if (cost.GetCost() == 0) {
512 return CommandCost(msg);
513 } else {
514 return cost;
515 }
516}
517
519 uint8_t x, y;
520};
521
522static void DrawTile_Trees(TileInfo *ti)
523{
524 switch (GetTreeGround(ti->tile)) {
525 case TREE_GROUND_SHORE: DrawShoreTile(ti->tileh); break;
526 case TREE_GROUND_GRASS: DrawClearLandTile(ti, GetTreeDensity(ti->tile)); break;
527 case TREE_GROUND_ROUGH: DrawHillyLandTile(ti); break;
528 default: DrawGroundSprite(_clear_land_sprites_snow_desert[GetTreeDensity(ti->tile)] + SlopeToSpriteOffset(ti->tileh), PAL_NONE); break;
529 }
530
531 /* Do not draw trees when the invisible trees setting is set */
532 if (IsInvisibilitySet(TO_TREES)) return;
533
534 uint tmp = CountBits(ti->tile.base() + ti->x + ti->y);
535 uint index = GB(tmp, 0, 2) + (GetTreeType(ti->tile) << 2);
536
537 /* different tree styles above one of the grounds */
539 GetTreeDensity(ti->tile) >= 2 &&
540 IsInsideMM(index, TREE_SUB_ARCTIC << 2, TREE_RAINFOREST << 2)) {
541 index += 164 - (TREE_SUB_ARCTIC << 2);
542 }
543
544 assert(index < lengthof(_tree_layout_sprite));
545
546 const PalSpriteID *s = _tree_layout_sprite[index];
547 const TreePos *d = _tree_layout_xy[GB(tmp, 2, 2)];
548
549 /* combine trees into one sprite object */
551
552 TreeListEnt te[4];
553
554 /* put the trees to draw in a list */
555 uint trees = GetTreeCount(ti->tile);
556
557 for (uint i = 0; i < trees; i++) {
558 SpriteID sprite = s[0].sprite + (i == trees - 1 ? static_cast<uint>(GetTreeGrowth(ti->tile)) : 3);
559 PaletteID pal = s[0].pal;
560
561 te[i].sprite = sprite;
562 te[i].pal = pal;
563 te[i].x = d->x;
564 te[i].y = d->y;
565 s++;
566 d++;
567 }
568
569 /* draw them in a sorted way */
570 int z = ti->z + GetSlopeMaxPixelZ(ti->tileh) / 2;
571
572 for (; trees > 0; trees--) {
573 uint min = te[0].x + te[0].y;
574 uint mi = 0;
575
576 for (uint i = 1; i < trees; i++) {
577 if ((uint)(te[i].x + te[i].y) < min) {
578 min = te[i].x + te[i].y;
579 mi = i;
580 }
581 }
582
583 AddSortableSpriteToDraw(te[mi].sprite, te[mi].pal, ti->x + te[mi].x, ti->y + te[mi].y, 16 - te[mi].x, 16 - te[mi].y, 0x30, z, IsTransparencySet(TO_TREES), -te[mi].x, -te[mi].y);
584
585 /* replace the removed one with the last one */
586 te[mi] = te[trees - 1];
587 }
588
590}
591
592
593static int GetSlopePixelZ_Trees(TileIndex tile, uint x, uint y, bool)
594{
595 auto [tileh, z] = GetTilePixelSlope(tile);
596
597 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
598}
599
600static Foundation GetFoundation_Trees(TileIndex, Slope)
601{
602 return FOUNDATION_NONE;
603}
604
605static CommandCost ClearTile_Trees(TileIndex tile, DoCommandFlag flags)
606{
607 uint num;
608
611 if (t != nullptr) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM, flags);
612 }
613
614 num = GetTreeCount(tile);
615 if (IsInsideMM(GetTreeType(tile), TREE_RAINFOREST, TREE_CACTUS)) num *= 4;
616
617 if (flags & DC_EXEC) DoClearSquare(tile);
618
619 return CommandCost(EXPENSES_CONSTRUCTION, num * _price[PR_CLEAR_TREES]);
620}
621
622static void GetTileDesc_Trees(TileIndex tile, TileDesc *td)
623{
624 TreeType tt = GetTreeType(tile);
625
627 td->str = STR_LAI_TREE_NAME_RAINFOREST;
628 } else {
629 td->str = tt == TREE_CACTUS ? STR_LAI_TREE_NAME_CACTUS_PLANTS : STR_LAI_TREE_NAME_TREES;
630 }
631
632 td->owner[0] = GetTileOwner(tile);
633}
634
635static void TileLoopTreesDesert(TileIndex tile)
636{
637 switch (GetTropicZone(tile)) {
642 }
643 break;
644
646 static const SoundFx forest_sounds[] = {
651 };
652 uint32_t r = Random();
653
654 if (Chance16I(1, 200, r) && _settings_client.sound.ambient) SndPlayTileFx(forest_sounds[GB(r, 16, 2)], tile);
655 break;
656 }
657
658 default: break;
659 }
660}
661
662static void TileLoopTreesAlps(TileIndex tile)
663{
664 int k = GetTileZ(tile) - GetSnowLine() + 1;
665
666 if (k < 0) {
667 switch (GetTreeGround(tile)) {
670 default: return;
671 }
672 } else {
673 uint density = std::min<uint>(k, 3);
674
677 SetTreeGroundDensity(tile, tg, density);
678 } else if (GetTreeDensity(tile) != density) {
679 SetTreeGroundDensity(tile, GetTreeGround(tile), density);
680 } else {
681 if (GetTreeDensity(tile) == 3) {
682 uint32_t r = Random();
683 if (Chance16I(1, 200, r) && _settings_client.sound.ambient) {
684 SndPlayTileFx((r & 0x80000000) ? SND_39_ARCTIC_SNOW_2 : SND_34_ARCTIC_SNOW_1, tile);
685 }
686 }
687 return;
688 }
689 }
691}
692
693static bool CanPlantExtraTrees(TileIndex tile)
694{
695 return ((_settings_game.game_creation.landscape == LandscapeType::Tropic && GetTropicZone(tile) == TROPICZONE_RAINFOREST) ?
697 _settings_game.construction.extra_tree_placement == ETP_SPREAD_ALL);
698}
699
700static void TileLoop_Trees(TileIndex tile)
701{
702 if (GetTreeGround(tile) == TREE_GROUND_SHORE) {
703 TileLoop_Water(tile);
704 } else {
706 case LandscapeType::Tropic: TileLoopTreesDesert(tile); break;
707 case LandscapeType::Arctic: TileLoopTreesAlps(tile); break;
708 default: break;
709 }
710 }
711
712 AmbientSoundEffect(tile);
713
714 /* TimerGameTick::counter is incremented by 256 between each call, so ignore lower 8 bits.
715 * Also, we use a simple hash to spread the updates evenly over the map.
716 * 11 and 9 are just some co-prime numbers for better spread.
717 */
718 uint32_t cycle = 11 * TileX(tile) + 9 * TileY(tile) + (TimerGameTick::counter >> 8);
719
720 /* Handle growth of grass (under trees/on MP_TREES tiles) at every 8th processings, like it's done for grass on MP_CLEAR tiles. */
721 if ((cycle & 7) == 7 && GetTreeGround(tile) == TREE_GROUND_GRASS) {
722 uint density = GetTreeDensity(tile);
723 if (density < 3) {
724 SetTreeGroundDensity(tile, TREE_GROUND_GRASS, density + 1);
726 }
727 }
728
730
731 static const uint32_t TREE_UPDATE_FREQUENCY = 16; // How many tile updates happen for one tree update
732 if (cycle % TREE_UPDATE_FREQUENCY != TREE_UPDATE_FREQUENCY - 1) return;
733
734 switch (GetTreeGrowth(tile)) {
735 case TreeGrowthStage::Grown: // regular sized tree
736 if (_settings_game.game_creation.landscape == LandscapeType::Tropic &&
737 GetTreeType(tile) != TREE_CACTUS &&
739 AddTreeGrowth(tile, 1);
740 } else {
741 switch (GB(Random(), 0, 3)) {
742 case 0: // start destructing
743 AddTreeGrowth(tile, 1);
744 break;
745
746 case 1: // add a tree
747 if (GetTreeCount(tile) < 4 && CanPlantExtraTrees(tile)) {
748 AddTreeCount(tile, 1);
750 break;
751 }
752 [[fallthrough]];
753
754 case 2: { // add a neighbouring tree
755 if (!CanPlantExtraTrees(tile)) break;
756
757 TreeType treetype = GetTreeType(tile);
758
759 tile += TileOffsByDir(static_cast<Direction>(Random() % DIR_END));
760
761 /* Cacti don't spread */
762 if (!CanPlantTreesOnTile(tile, false)) return;
763
764 /* Don't plant trees, if ground was freshly cleared */
765 if (IsTileType(tile, MP_CLEAR) && GetClearGround(tile) == CLEAR_GRASS && GetClearDensity(tile) != 3) return;
766
768
769 break;
770 }
771
772 default:
773 return;
774 }
775 }
776 break;
777
778 case TreeGrowthStage::Dead: // final stage of tree destruction
779 if (!CanPlantExtraTrees(tile)) {
780 /* if trees can't spread just plant a new one to prevent deforestation */
782 } else if (GetTreeCount(tile) > 1) {
783 /* more than one tree, delete it */
784 AddTreeCount(tile, -1);
786 } else {
787 /* just one tree, change type into MP_CLEAR */
788 switch (GetTreeGround(tile)) {
789 case TREE_GROUND_SHORE: MakeShore(tile); break;
790 case TREE_GROUND_GRASS: MakeClear(tile, CLEAR_GRASS, GetTreeDensity(tile)); break;
791 case TREE_GROUND_ROUGH: MakeClear(tile, CLEAR_ROUGH, 3); break;
793 uint density = GetTreeDensity(tile);
794 MakeClear(tile, CLEAR_ROUGH, 3);
795 MakeSnow(tile, density);
796 break;
797 }
798 default: // snow or desert
799 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
801 } else {
802 uint density = GetTreeDensity(tile);
803 MakeClear(tile, CLEAR_GRASS, 3);
804 MakeSnow(tile, density);
805 }
806 break;
807 }
808 }
809 break;
810
811 default:
812 AddTreeGrowth(tile, 1);
813 break;
814 }
815
817}
818
826{
827 /* Ensure _trees_tick_ctr can be decremented past zero only once for the largest map size. */
828 static_assert(2 * (MAX_MAP_SIZE_BITS - MIN_MAP_SIZE_BITS) - 4 <= std::numeric_limits<uint8_t>::digits);
829
830 /* byte underflow */
831 uint8_t old_trees_tick_ctr = _trees_tick_ctr;
833 return old_trees_tick_ctr <= _trees_tick_ctr;
834}
835
840static void PlantRandomTree(bool rainforest)
841{
842 uint32_t r = Random();
843 TileIndex tile = RandomTileSeed(r);
844
845 if (rainforest && GetTropicZone(tile) != TROPICZONE_RAINFOREST) return;
846 if (!CanPlantTreesOnTile(tile, false)) return;
847
848 TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8));
849 if (tree == TREE_INVALID) return;
850
852}
853
854void OnTick_Trees()
855{
856 /* Don't spread trees if that's not allowed */
858
859 /* Skip some tree ticks for map sizes below 256 * 256. 64 * 64 is 16 times smaller, so
860 * this is the maximum number of ticks that are skipped. Number of ticks to skip is
861 * inversely proportional to map size, so that is handled to create a mask. */
862 int skip = Map::ScaleBySize(16);
863 if (skip < 16 && (TimerGameTick::counter & (16 / skip - 1)) != 0) return;
864
865 /* place a tree at a random rainforest spot */
866 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
867 for (uint c = Map::ScaleBySize(1); c > 0; c--) {
868 PlantRandomTree(true);
869 }
870 }
871
873
874 /* place a tree at a random spot */
875 PlantRandomTree(false);
876}
877
878static TrackStatus GetTileTrackStatus_Trees(TileIndex, TransportType, uint, DiagDirection)
879{
880 return 0;
881}
882
883static void ChangeTileOwner_Trees(TileIndex, Owner, Owner)
884{
885 /* not used */
886}
887
888void InitializeTrees()
889{
890 _trees_tick_ctr = 0;
891}
892
893static CommandCost TerraformTile_Trees(TileIndex tile, DoCommandFlag flags, int, Slope)
894{
895 return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
896}
897
898
899extern const TileTypeProcs _tile_type_trees_procs = {
900 DrawTile_Trees, // draw_tile_proc
901 GetSlopePixelZ_Trees, // get_slope_z_proc
902 ClearTile_Trees, // clear_tile_proc
903 nullptr, // add_accepted_cargo_proc
904 GetTileDesc_Trees, // get_tile_desc_proc
905 GetTileTrackStatus_Trees, // get_tile_track_status_proc
906 nullptr, // click_tile_proc
907 nullptr, // animate_tile_proc
908 TileLoop_Trees, // tile_loop_proc
909 ChangeTileOwner_Trees, // change_tile_owner_proc
910 nullptr, // add_produced_cargo_proc
911 nullptr, // vehicle_enter_tile_proc
912 GetFoundation_Trees, // get_foundation_proc
913 TerraformTile_Trees, // terraform_tile_proc
914};
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
Common return value for all commands.
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition tilearea.cpp:291
static TickCounter counter
Monotonic counter, in ticks, since start of game.
Functions related to clear (MP_CLEAR) land.
Tables with sprites for clear land and fences.
Map accessors for 'clear' tiles.
ClearGround GetRawClearGround(Tile t)
Get the type of clear tile but never return CLEAR_SNOW.
Definition clear_map.h:47
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:71
void MakeSnow(Tile t, uint density=0)
Make a snow tile.
Definition clear_map.h:300
@ CLEAR_GRASS
0-3
Definition clear_map.h:20
@ CLEAR_FIELDS
3
Definition clear_map.h:23
@ CLEAR_DESERT
1,3
Definition clear_map.h:25
@ CLEAR_SNOW
0-3
Definition clear_map.h:24
@ CLEAR_ROUGH
3
Definition clear_map.h:21
@ CLEAR_ROCKS
3
Definition clear_map.h:22
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:259
ClearGround GetClearGround(Tile t)
Get the type of clear tile.
Definition clear_map.h:59
uint GetClearDensity(Tile t)
Get the density of a non-field clear tile.
Definition clear_map.h:83
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
DoCommandFlag
List of flags for a command.
@ DC_EXEC
execute the given command
Definition of stuff that is very close to a company, like the company struct itself.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
Owner
Enum for all companies/owners.
Direction
Defines the 8 directions on the map.
@ DIR_END
Used to iterate.
DiagDirection
Enumeration for diagonal directions.
@ EXPENSES_CONSTRUCTION
Construction costs.
@ EXPENSES_OTHER
Other expenses.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23)
Definition enum_type.hpp:15
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ GWP_TREE
Generate trees.
Definition genworld.h:80
void SetGeneratingWorldProgress(GenWorldProgress cls, uint total)
Set the total of a stage of the world generation.
static constexpr uint MAP_HEIGHT_LIMIT_ORIGINAL
Original map height limit.
Definition genworld.h:52
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
uint8_t GetSnowLine()
Get the current snow line, either variable or static.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Functions related to OTTD's landscape.
Command definitions related to landscape (slopes etc.).
@ Random
Randomise borders.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:160
TileIndex TileAddWrap(TileIndex tile, int addx, int addy)
This function checks if we add addx/addy to tile, if we do wrap around the edges.
Definition map.cpp:94
TileIndex RandomTileSeed(uint32_t r)
Get a random tile out of a given seed.
Definition map_func.h:653
#define RandomTile()
Get a valid random tile.
Definition map_func.h:664
TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition map_func.h:584
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:415
static const uint MIN_MAP_SIZE_BITS
Minimal and maximal map width and height.
Definition map_type.h:37
static const uint MAX_MAP_SIZE_BITS
Maximal size of map is equal to 2 ^ MAX_MAP_SIZE_BITS.
Definition map_type.h:38
constexpr bool IsInsideBS(const T x, const size_t base, const size_t size)
Checks if a value is between a window started at some base point.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
constexpr T Delta(const T a, const T b)
Returns the (absolute) difference between two (scalar) variables.
Functions related to generic callbacks.
void AmbientSoundEffect(TileIndex tile)
Play an ambient sound effect for an empty tile.
Pseudo random number generator.
bool Chance16I(const uint32_t a, const uint32_t b, const uint32_t r)
Checks if a given randomize-number is below a given probability.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:57
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:56
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:415
static constexpr int GetSlopeMaxPixelZ(Slope s)
Returns the height of the highest corner of a slope relative to TileZ (= minimal height)
Definition slope_func.h:173
Slope
Enumeration for the slope-type.
Definition slope_type.h:48
Foundation
Enumeration for Foundations.
Definition slope_type.h:93
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition slope_type.h:94
Functions related to sound.
SoundFx
Sound effects from baseset.
Definition sound_type.h:45
@ SND_39_ARCTIC_SNOW_2
57 == 0x39 Tree ambient: arctic snow (2): heavy wind
Definition sound_type.h:104
@ SND_44_RAINFOREST_3
68 == 0x44 Tree ambient: rainforest ambient (3): monkeys
Definition sound_type.h:115
@ SND_34_ARCTIC_SNOW_1
52 == 0x34 Tree ambient: arctic snow (1): wind
Definition sound_type.h:99
@ SND_43_RAINFOREST_2
67 == 0x43 Tree ambient: rainforest ambient (2): lion
Definition sound_type.h:114
@ SND_42_RAINFOREST_1
66 == 0x42 Tree ambient: rainforest ambient (1): bird (1)
Definition sound_type.h:113
@ SND_48_RAINFOREST_4
72 == 0x48 Tree ambient: rainforest ambient (4): bird (2)
Definition sound_type.h:119
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:277
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
SoundSettings sound
sound effect settings
uint32_t tree_limit
Amount of trees we can (still) plant (times 65536).
uint8_t extra_tree_placement
(dis)allow building extra trees in-game
uint8_t map_height_limit
the maximum allowed heightlevel
uint8_t dist_local_authority
distance for town local authority, default 20
uint8_t tree_placer
the tree placer algorithm
LandscapeType landscape
the landscape we're currently in
EconomySettings economy
settings to change the economy
ConstructionSettings construction
construction of things in-game
GameCreationSettings game_creation
settings used during the creation of a game (map)
static uint ScaleBySize(uint n)
Scales the given value by the map size, where the given value is for a 256 by 256 map.
Definition map_func.h:328
static debug_inline uint Size()
Get the size of the map.
Definition map_func.h:288
OrthogonalTileArea & Expand(int rad)
Expand a tile area by rad tiles in each direction, keeping within map bounds.
Definition tilearea.cpp:123
Combination of a palette sprite and a 'real' sprite.
Definition gfx_type.h:22
SpriteID sprite
The 'real' sprite.
Definition gfx_type.h:23
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition gfx_type.h:24
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
bool ambient
Play ambient, industry and town sounds.
Tile description for the 'land area information' tool.
Definition tile_cmd.h:52
StringID str
Description of the tile.
Definition tile_cmd.h:53
Owner owner[4]
Name of the owner(s)
Definition tile_cmd.h:55
Tile information, used while rendering the tile.
Definition tile_cmd.h:43
int z
Height.
Definition tile_cmd.h:48
int x
X position of the tile in unit coordinates.
Definition tile_cmd.h:44
Slope tileh
Slope of the tile.
Definition tile_cmd.h:46
TileIndex tile
Tile index.
Definition tile_cmd.h:47
int y
Y position of the tile in unit coordinates.
Definition tile_cmd.h:45
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:158
Town data structure.
Definition town.h:52
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:116
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
TropicZone GetTropicZone(Tile tile)
Get the tropic zone.
Definition tile_map.h:238
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.h:279
void SetTropicZone(Tile tile, TropicZone type)
Set the tropic zone.
Definition tile_map.h:225
@ TROPICZONE_RAINFOREST
Rainforest tile.
Definition tile_type.h:79
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:78
@ TROPICZONE_NORMAL
Normal tropiczone.
Definition tile_type.h:77
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_TREES
Tile got trees.
Definition tile_type.h:52
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:48
@ MP_WATER
Water tile.
Definition tile_type.h:54
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition tile_type.h:55
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition of the tick-based game-timer.
Base of the town class.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
void ChangeTownRating(Town *t, int add, int max, DoCommandFlag flags)
Changes town rating of the current company.
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
@ TO_TREES
trees
TransportType
Available types of transport.
uint PlaceTreeGroupAroundTile(TileIndex tile, TreeType treetype, uint radius, uint count, bool set_zone)
Place some trees in a radius around a tile.
Definition tree_cmd.cpp:310
static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, TreeGrowthStage growth)
Creates a tree tile Ground type and density is preserved.
Definition tree_cmd.cpp:94
static TreeType GetRandomTreeType(TileIndex tile, uint seed)
Get a random TreeType for the given tile based on a given seed.
Definition tree_cmd.cpp:135
void GenerateTrees()
Place new trees.
Definition tree_cmd.cpp:357
static const uint16_t EDITOR_TREE_DIV
Game editor tree generation divisor factor.
Definition tree_cmd.cpp:59
static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
Tests if a tile can be converted to MP_TREES This is true for clear ground without farms or rocks.
Definition tree_cmd.cpp:69
void PlaceTreesRandomly()
Place some trees randomly.
Definition tree_cmd.cpp:247
static const uint16_t DEFAULT_TREE_STEPS
Default number of attempts for placing trees.
Definition tree_cmd.cpp:57
static const uint16_t DEFAULT_RAINFOREST_TREE_STEPS
Default number of attempts for placing extra trees at rainforest in tropic.
Definition tree_cmd.cpp:58
static void PlantRandomTree(bool rainforest)
Place a random tree on a random tile.
Definition tree_cmd.cpp:840
static void PlaceTreeAtSameHeight(TileIndex tile, int height)
Place a tree at the same height as an existing tree.
Definition tree_cmd.cpp:218
CommandCost CmdPlantTree(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, uint8_t tree_to_plant, bool diagonal)
Plant a tree.
Definition tree_cmd.cpp:392
uint8_t _trees_tick_ctr
Determines when to consider building more trees.
Definition tree_cmd.cpp:55
TreePlacer
List of tree placer algorithm.
Definition tree_cmd.cpp:40
@ TP_IMPROVED
A 'improved' algorithm.
Definition tree_cmd.cpp:43
@ TP_NONE
No tree placer algorithm.
Definition tree_cmd.cpp:41
@ TP_ORIGINAL
The original algorithm.
Definition tree_cmd.cpp:42
static void PlaceTree(TileIndex tile, uint32_t r)
Make a random tree tile of the given tile.
Definition tree_cmd.cpp:165
static void PlaceTreeGroups(uint num_groups)
Creates a number of tree groups.
Definition tree_cmd.cpp:187
ExtraTreePlacement
Where to place trees while in-game?
Definition tree_cmd.cpp:47
@ ETP_SPREAD_RAINFOREST
Grow trees on tiles that have them, only spread to new ones in rainforests.
Definition tree_cmd.cpp:49
@ ETP_NO_SPREAD
Grow trees on tiles that have them but don't spread to new ones.
Definition tree_cmd.cpp:48
@ ETP_NO_GROWTH_NO_SPREAD
Don't grow trees and don't spread them at all.
Definition tree_cmd.cpp:51
@ ETP_SPREAD_ALL
Grow trees and spread them without restrictions.
Definition tree_cmd.cpp:50
bool DecrementTreeCounter()
Decrement the tree tick counter.
Definition tree_cmd.cpp:825
Command definitions related to tree tiles.
Sprites to use and how to display them for tree tiles.
Map accessors for tree tiles.
static const uint TREE_COUNT_RAINFOREST
number of tree types for the 'rainforest part' of a sub-tropic map.
Definition tree_map.h:43
uint GetTreeCount(Tile t)
Returns the number of trees on a tile.
Definition tree_map.h:163
TreeGrowthStage GetTreeGrowth(Tile t)
Returns the tree growth stage.
Definition tree_map.h:195
static const uint TREE_COUNT_SUB_TROPICAL
number of tree types for the 'sub-tropic part' of a sub-tropic map.
Definition tree_map.h:44
static const uint TREE_COUNT_TOYLAND
number of tree types on a toyland map.
Definition tree_map.h:45
void MakeTree(Tile t, TreeType type, uint count, TreeGrowthStage growth, TreeGround ground, uint density)
Make a tree-tile.
Definition tree_map.h:244
void SetTreeGrowth(Tile t, TreeGrowthStage g)
Sets the tree growth stage of a tile.
Definition tree_map.h:226
TreeGround GetTreeGround(Tile t)
Returns the groundtype for tree tiles.
Definition tree_map.h:102
TreeType
List of tree types along all landscape types.
Definition tree_map.h:25
@ TREE_RAINFOREST
tree on the 'green part' on a sub-tropical map
Definition tree_map.h:28
@ TREE_TOYLAND
tree on a toyland map
Definition tree_map.h:31
@ TREE_SUB_ARCTIC
tree on a sub_arctic landscape
Definition tree_map.h:27
@ TREE_SUB_TROPICAL
tree on a sub-tropical map, non-rainforest, non-desert
Definition tree_map.h:30
@ TREE_TEMPERATE
temperate tree
Definition tree_map.h:26
@ TREE_CACTUS
a cactus for the 'desert part' on a sub-tropical map
Definition tree_map.h:29
@ TREE_INVALID
An invalid tree.
Definition tree_map.h:32
void AddTreeCount(Tile t, int c)
Add a amount to the tree-count value of a tile with trees.
Definition tree_map.h:180
TreeGround
Enumeration for ground types of tiles with trees.
Definition tree_map.h:52
@ TREE_GROUND_GRASS
normal grass
Definition tree_map.h:53
@ TREE_GROUND_SHORE
shore
Definition tree_map.h:56
@ TREE_GROUND_ROUGH_SNOW
A snow tile that is rough underneath.
Definition tree_map.h:57
@ TREE_GROUND_SNOW_DESERT
a desert or snow tile, depend on landscape
Definition tree_map.h:55
@ TREE_GROUND_ROUGH
some rough tile
Definition tree_map.h:54
static const uint TREE_COUNT_SUB_ARCTIC
number of tree types on a sub arctic map.
Definition tree_map.h:42
TreeType GetTreeType(Tile t)
Returns the treetype of a tile.
Definition tree_map.h:87
void SetTreeGroundDensity(Tile t, TreeGround g, uint d)
Set the density and ground type of a tile with trees.
Definition tree_map.h:144
void AddTreeGrowth(Tile t, int a)
Add a value to the tree growth stage.
Definition tree_map.h:210
uint GetTreeDensity(Tile t)
Returns the 'density' of a tile with trees.
Definition tree_map.h:127
TreeGrowthStage
Enumeration for tree growth stages.
Definition tree_map.h:65
@ Grown
Fully grown tree.
@ Dead
Dead tree.
@ Growing1
First stage of growth.
static const uint TREE_COUNT_TEMPERATE
number of tree types on a temperate map.
Definition tree_map.h:41
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition viewport.cpp:767
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:671
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition viewport.cpp:777
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition viewport.cpp:587
Functions related to (drawing on) viewports.
Functions related to water (management)
void TileLoop_Water(TileIndex tile)
Let a water tile floods its diagonal adjoining tiles called from tunnelbridge_cmd,...
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:97
void MakeShore(Tile t)
Helper function to make a coast tile.
Definition water_map.h:381
bool IsCoast(Tile t)
Is it a coast tile?
Definition water_map.h:201