OpenTTD Source 20260911-master-gee2b2ac12a
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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"
24#include "core/random_func.hpp"
25#include "newgrf_generic.h"
27#include "tree_cmd.h"
28#include "landscape_cmd.h"
29
30#include "table/strings.h"
31#include "table/tree_land.h"
32#include "table/clear_land.h"
33
34#include "safeguards.h"
35
43
46
47static const uint16_t DEFAULT_TREE_STEPS = 1000;
48static const uint16_t DEFAULT_RAINFOREST_TREE_STEPS = 15000;
49static const uint16_t EDITOR_TREE_DIV = 5;
50
59static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
60{
61 switch (GetTileType(tile)) {
62 case TileType::Water:
63 /* Consistency with normal rocky tiles, coast with rocks is not eligible for trees. */
65
66 case TileType::Clear:
68 (allow_desert || !IsClearGround(tile, ClearGround::Desert));
69
70 default: return false;
71 }
72}
73
80{
81 switch (clearground) {
84 default: return TreeGround::SnowOrDesert;
85 }
86}
87
99static void PlantTreesOnTile(TileIndex tile, TreeType treetype, uint count, TreeGrowthStage growth)
100{
101 assert(treetype != TREE_INVALID);
102 assert(CanPlantTreesOnTile(tile, true));
103
104 TreeGround ground;
105 uint density = 3;
106
107 switch (GetTileType(tile)) {
108 case TileType::Water:
109 ground = TreeGround::Shore;
111 break;
112
113 case TileType::Clear: {
114 ClearGround clearground = GetClearGround(tile);
115 if (IsSnowTile(tile)) {
117 } else {
118 ground = TreeGroundFromClearGround(clearground);
119 }
120 if (clearground != ClearGround::Rough) density = GetClearDensity(tile);
121 break;
122 }
123
124 default: NOT_REACHED();
125 }
126
127 MakeTree(tile, treetype, count, growth, ground, density);
128}
129
141static TreeType GetRandomTreeType(TileIndex tile, uint seed)
142{
143 switch (_settings_game.game_creation.landscape) {
145 return static_cast<TreeType>(seed * TREE_COUNT_TEMPERATE / 256 + TREE_TEMPERATE);
146
148 return static_cast<TreeType>(seed * TREE_COUNT_SUB_ARCTIC / 256 + TREE_SUB_ARCTIC);
149
151 switch (GetTropicZone(tile)) {
152 case TropicZone::Normal: return static_cast<TreeType>(seed * TREE_COUNT_SUB_TROPICAL / 256 + TREE_SUB_TROPICAL);
153 case TropicZone::Desert: return static_cast<TreeType>((seed > 12) ? TREE_INVALID : TREE_CACTUS);
154 default: return static_cast<TreeType>(seed * TREE_COUNT_RAINFOREST / 256 + TREE_RAINFOREST);
155 }
156
157 default:
158 return static_cast<TreeType>(seed * TREE_COUNT_TOYLAND / 256 + TREE_TOYLAND);
159 }
160}
161
172void PlaceTree(TileIndex tile, uint32_t r, bool keep_density)
173{
174 TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8));
175
176 if (tree != TREE_INVALID) {
177 PlantTreesOnTile(tile, tree, GB(r, 22, 2), static_cast<TreeGrowthStage>(std::min<uint8_t>(GB(r, 16, 3), to_underlying(TreeGrowthStage::Dead))));
179
180 /* Maybe keep the existing ground density.*/
181 if (keep_density) return;
182
183 /* Rerandomize ground, if neither snow nor shore */
184 TreeGround ground = GetTreeGround(tile);
185 if (ground != TreeGround::SnowOrDesert && ground != TreeGround::RoughSnow && ground != TreeGround::Shore) {
186 SetTreeGroundDensity(tile, (TreeGround)GB(r, 28, 1), 3);
187 }
188 }
189}
190
192 int amplitude;
193 float phase;
194 int frequency;
195};
196
204static void CreateStarShapedPolygon(int radius, std::span<const BlobHarmonic> harmonics, std::span<Point> shape)
205{
206 float theta = 0;
207 float step = (M_PI * 2) / std::size(shape);
208
209 /* Divide a circle into a number of equally spaced divisions. */
210 for (Point &vertex : shape) {
211
212 /* Add up the values of each harmonic at this segment.*/
213 float deviation = std::accumulate(std::begin(harmonics), std::end(harmonics), 0.f, [theta](float d, const BlobHarmonic &harmonic) -> float {
214 return d + sinf((theta + harmonic.phase) * harmonic.frequency) * harmonic.amplitude;
215 });
216
217 /* Smooth out changes. */
218 float adjusted_radius = (radius / 2.f) + (deviation / 2);
219
220 /* Add to the final polygon. */
221 vertex.x = cosf(theta) * adjusted_radius;
222 vertex.y = sinf(theta) * adjusted_radius;
223
224 /* Proceed to the next segment. */
225 theta += step;
226 }
227}
228
235static void CreateRandomStarShapedPolygon(int radius, std::span<Point> shape)
236{
237 /* Valid values for the phase of blob harmonics are between 0 and Tau. we can get a value in the correct range
238 * from Random() by dividing the maximum possible value by the desired maximum, and then dividing the random
239 * value by the result. */
240 static constexpr float PHASE_DIVISOR = static_cast<float>(INT32_MAX / M_PI * 2);
241
242 /* These values are ones found in testing that result in suitable-looking polygons that did not self-intersect
243 * and fit within a square of radius * radius dimensions. */
244 std::initializer_list<BlobHarmonic> harmonics = {
245 {radius / 2, Random() / PHASE_DIVISOR, 1},
246 {radius / 4, Random() / PHASE_DIVISOR, 2},
247 {radius / 8, Random() / PHASE_DIVISOR, 3},
248 {radius / 16, Random() / PHASE_DIVISOR, 4},
249 };
250
251 CreateStarShapedPolygon(radius, harmonics, shape);
252}
253
263static bool IsPointInTriangle(int x, int y, const Point &v1, const Point &v2, const Point &v3)
264{
265 const int s = ((v1.x - v3.x) * (y - v3.y)) - ((v1.y - v3.y) * (x - v3.x));
266 const int t = ((v2.x - v1.x) * (y - v1.y)) - ((v2.y - v1.y) * (x - v1.x));
267
268 if ((s < 0) != (t < 0) && s != 0 && t != 0) return false;
269
270 const int d = (v3.x - v2.x) * (y - v2.y) - (v3.y - v2.y) * (x - v2.x);
271 return (d < 0) == (s + t <= 0);
272}
273
282static bool IsPointInStarShapedPolygon(int x, int y, std::span<Point> shape)
283{
284 for (auto it = std::begin(shape); it != std::end(shape); /* nothing */) {
285 const Point &v1 = *it;
286 ++it;
287 const Point &v2 = (it == std::end(shape)) ? shape.front() : *it;
288
289 if (IsPointInTriangle(x, y, v1, v2, {0, 0})) return true;
290 }
291
292 return false;
293}
294
301static void PlaceTreeGroups(uint num_groups)
302{
303 static constexpr uint GROVE_SEGMENTS = 16;
304 static constexpr uint GROVE_RADIUS = 16;
305
306 /* Shape in which trees may be contained. Array is here to reduce allocations. */
307 std::array<Point, GROVE_SEGMENTS> grove;
308
309 do {
310 TileIndex center_tile = RandomTile();
311
312 CreateRandomStarShapedPolygon(GROVE_RADIUS, grove);
313
314 for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) {
316
317 uint32_t r = Random();
318 int x = GB(r, 0, 5) - GROVE_RADIUS;
319 int y = GB(r, 8, 5) - GROVE_RADIUS;
320 TileIndex cur_tile = TileAddWrap(center_tile, x, y);
321
322 if (cur_tile == INVALID_TILE) continue;
323 if (!CanPlantTreesOnTile(cur_tile, true)) continue;
324 if (!IsPointInStarShapedPolygon(x, y, grove)) continue;
325
326 PlaceTree(cur_tile, r);
327 }
328
329 } while (--num_groups);
330}
331
341static void PlaceTreeAtSameHeight(TileIndex tile, int height)
342{
343 for (uint i = 0; i < DEFAULT_TREE_STEPS; i++) {
344 uint32_t r = Random();
345 int x = GB(r, 0, 5) - 16;
346 int y = GB(r, 8, 5) - 16;
347 TileIndex cur_tile = TileAddWrap(tile, x, y);
348 if (cur_tile == INVALID_TILE) continue;
349
350 /* Keep in range of the existing tree */
351 if (abs(x) + abs(y) > 16) continue;
352
353 /* Clear tile, no farm-tiles or rocks */
354 if (!CanPlantTreesOnTile(cur_tile, true)) continue;
355
356 /* Not too much height difference */
357 if (Delta(GetTileZ(cur_tile), height) > 2) continue;
358
359 /* Place one tree and quit */
360 PlaceTree(cur_tile, r);
361 break;
362 }
363}
364
371{
372 int i, j, ht;
373 uint8_t max_height = _settings_game.construction.map_height_limit;
374
376 if (_game_mode == GameMode::Editor) i /= EDITOR_TREE_DIV;
377 do {
378 uint32_t r = Random();
379 TileIndex tile = RandomTileSeed(r);
380
382
383 if (CanPlantTreesOnTile(tile, true)) {
384 PlaceTree(tile, r);
385 if (_settings_game.game_creation.tree_placer != TreePlacer::Improved) continue;
386
387 /* Place a number of trees based on the tile height.
388 * This gives a cool effect of multiple trees close together.
389 * It is almost real life ;) */
390 ht = GetTileZ(tile);
391 /* The higher we get, the more trees we plant */
392 j = GetTileZ(tile) * 2;
393 /* Above snowline more trees! */
394 if (_settings_game.game_creation.landscape == LandscapeType::Arctic && ht > GetSnowLine()) j *= 3;
395 /* Scale generation by maximum map height. */
396 if (max_height > MAP_HEIGHT_LIMIT_ORIGINAL) j = j * MAP_HEIGHT_LIMIT_ORIGINAL / max_height;
397 while (j--) {
398 PlaceTreeAtSameHeight(tile, ht);
399 }
400 }
401 } while (--i);
402
403 /* place extra trees at rainforest area */
404 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
406 if (_game_mode == GameMode::Editor) i /= EDITOR_TREE_DIV;
407
408 do {
409 uint32_t r = Random();
410 TileIndex tile = RandomTileSeed(r);
411
413
414 if (GetTropicZone(tile) == TropicZone::Rainforest && CanPlantTreesOnTile(tile, false)) {
415 PlaceTree(tile, r);
416 }
417 } while (--i);
418 }
419}
420
433uint PlaceTreeGroupAroundTile(TileIndex tile, TreeType treetype, uint radius, uint count, bool set_zone)
434{
435 assert(_game_mode == GameMode::Editor); // Due to InteractiveRandom being used in this function
436 assert(treetype < TREE_TOYLAND + TREE_COUNT_TOYLAND);
437 const bool allow_desert = treetype == TREE_CACTUS;
438 uint planted = 0;
439
440 for (; count > 0; count--) {
441 /* Simple quasi-normal distribution with range [-radius; radius) */
442 auto mkcoord = [&]() -> int32_t {
443 const uint32_t rand = InteractiveRandom();
444 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);
445 const int32_t scu = dist * radius / 512;
446 return scu - radius;
447 };
448 const int32_t xofs = mkcoord();
449 const int32_t yofs = mkcoord();
450 const TileIndex tile_to_plant = TileAddWrap(tile, xofs, yofs);
451 if (tile_to_plant != INVALID_TILE) {
452 if (IsTileType(tile_to_plant, TileType::Trees) && GetTreeCount(tile_to_plant) < 4) {
453 AddTreeCount(tile_to_plant, 1);
455 MarkTileDirtyByTile(tile_to_plant, 0);
456 planted++;
457 } else if (CanPlantTreesOnTile(tile_to_plant, allow_desert)) {
458 PlantTreesOnTile(tile_to_plant, treetype, 0, TreeGrowthStage::Grown);
459 MarkTileDirtyByTile(tile_to_plant, 0);
460 planted++;
461 }
462 }
463 }
464
465 if (set_zone && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) {
466 for (TileIndex t : TileArea(tile).Expand(radius)) {
467 if (GetTileType(t) != TileType::Void && DistanceSquare(tile, t) < radius * radius) SetTropicZone(t, TropicZone::Rainforest);
468 }
469 }
470
471 return planted;
472}
473
481{
482 uint i, total;
483
484 if (_settings_game.game_creation.tree_placer == TreePlacer::None) return;
485
486 switch (_settings_game.game_creation.tree_placer) {
487 case TreePlacer::Original: i = _settings_game.game_creation.landscape == LandscapeType::Arctic ? 15 : 6; break;
488 case TreePlacer::Improved: i = _settings_game.game_creation.landscape == LandscapeType::Arctic ? 4 : 2; break;
489 default: NOT_REACHED();
490 }
491
494 total *= i;
495 uint num_groups = (_settings_game.game_creation.landscape != LandscapeType::Toyland) ? Map::ScaleBySize(GB(Random(), 0, 5) + 25) : 0;
496 total += num_groups * DEFAULT_TREE_STEPS;
498
499 if (num_groups != 0) PlaceTreeGroups(num_groups);
500
501 for (; i != 0; i--) {
503 }
504}
505
515CommandCost CmdPlantTree(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, uint8_t tree_to_plant, bool diagonal)
516{
519
520 if (start_tile >= Map::Size()) return CMD_ERROR;
521 /* Check the tree type within the current climate */
522 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;
523
524 Company *c = (_game_mode != GameMode::Editor) ? Company::GetIfValid(_current_company) : nullptr;
525 int limit = (c == nullptr ? INT32_MAX : GB(c->tree_limit, 16, 16));
526
527 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
528 for (; *iter != INVALID_TILE; ++(*iter)) {
529 TileIndex current_tile = *iter;
530 TileType tile_type = GetTileType(current_tile);
531 switch (tile_type) {
532 case TileType::Trees:
533 /* no more space for trees? */
534 if (GetTreeCount(current_tile) == 4) {
535 msg = STR_ERROR_TREE_ALREADY_HERE;
536 continue;
537 }
538
539 /* Test tree limit. */
540 if (--limit < 1) {
541 msg = STR_ERROR_TREE_PLANT_LIMIT_REACHED;
542 break;
543 }
544
545 if (flags.Test(DoCommandFlag::Execute)) {
546 AddTreeCount(current_tile, 1);
547 MarkTileDirtyByTile(current_tile);
548 if (c != nullptr) c->tree_limit -= 1 << 16;
549 }
550 /* 2x as expensive to add more trees to an existing tile */
552 break;
553
554 case TileType::Water:
555 if (!IsCoast(current_tile) || IsSlopeWithOneCornerRaised(GetTileSlope(current_tile))) {
556 msg = STR_ERROR_CAN_T_BUILD_ON_WATER;
557 continue;
558 }
559 [[fallthrough]];
560
561 case TileType::Clear: {
562 if (IsBridgeAbove(current_tile)) {
563 msg = STR_ERROR_SITE_UNSUITABLE;
564 continue;
565 }
566
567 TreeType treetype = (TreeType)tree_to_plant;
568 /* Be a bit picky about which trees go where. */
569 if (_settings_game.game_creation.landscape == LandscapeType::Tropic && treetype != TREE_INVALID && (
570 /* No cacti outside the desert */
571 (treetype == TREE_CACTUS && GetTropicZone(current_tile) != TropicZone::Desert) ||
572 /* No rainforest trees outside the rainforest, except in the editor mode where it makes those tiles rainforest tile */
573 (IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS) && GetTropicZone(current_tile) != TropicZone::Rainforest && _game_mode != GameMode::Editor) ||
574 /* And no subtropical trees in the desert/rainforest */
575 (IsInsideMM(treetype, TREE_SUB_TROPICAL, TREE_TOYLAND) && GetTropicZone(current_tile) != TropicZone::Normal))) {
576 msg = STR_ERROR_TREE_WRONG_TERRAIN_FOR_TREE_TYPE;
577 continue;
578 }
579
580 /* Test tree limit. */
581 if (--limit < 1) {
582 msg = STR_ERROR_TREE_PLANT_LIMIT_REACHED;
583 break;
584 }
585
586 bool tile_needs_to_be_cleared = false;
587 if (tile_type == TileType::Clear) {
588 /* Remove fields or rocks. Note that the ground will get barrened */
589 switch (GetClearGround(current_tile)) {
592 tile_needs_to_be_cleared = true;
593 break;
594
595 default:
596 break;
597 }
598 } else if (tile_type == TileType::Water) {
599 tile_needs_to_be_cleared = GetWaterTileType(current_tile) != WaterTileType::Coast;
600 }
601
602 if (tile_needs_to_be_cleared) {
603 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags, current_tile);
604 if (ret.Failed()) return ret;
605 cost.AddCost(ret.GetCost());
606 }
607
609 Town *t = ClosestTownFromTile(current_tile, _settings_game.economy.dist_local_authority);
610 if (t != nullptr) ChangeTownRating(t, RATING_TREE_UP_STEP, RATING_TREE_MAXIMUM, flags);
611 }
612
613 if (flags.Test(DoCommandFlag::Execute)) {
614 if (treetype == TREE_INVALID) {
615 treetype = GetRandomTreeType(current_tile, GB(Random(), 24, 8));
616 if (treetype == TREE_INVALID) treetype = TREE_CACTUS;
617 }
618
619 /* Plant full grown trees in scenario editor */
620 PlantTreesOnTile(current_tile, treetype, 0, _game_mode == GameMode::Editor ? TreeGrowthStage::Grown : TreeGrowthStage::Growing1);
621 MarkTileDirtyByTile(current_tile);
622 if (c != nullptr) c->tree_limit -= 1 << 16;
623
624 /* When planting rainforest-trees, set tropiczone to rainforest in editor. */
625 if (_game_mode == GameMode::Editor && IsInsideMM(treetype, TREE_RAINFOREST, TREE_CACTUS)) {
627 }
628 }
630 break;
631 }
632
633 default:
634 msg = STR_ERROR_SITE_UNSUITABLE;
635 break;
636 }
637
638 /* Tree limit used up? No need to check more. */
639 if (limit < 0) break;
640 }
641
642 if (cost.GetCost() == 0) {
643 return CommandCost(msg);
644 } else {
645 return cost;
646 }
647}
648
649struct TreeListEnt : PalSpriteID, Coord2D<int8_t> {};
650
652static void DrawTile_Trees(TileInfo *ti)
653{
654 switch (GetTreeGround(ti->tile)) {
655 case TreeGround::Shore: DrawShoreTile(ti->tileh); break;
657 case TreeGround::Rough: DrawRoughLandTile(ti); break;
659 }
660
661 /* Do not draw trees when the invisible trees setting is set */
663
664 uint tmp = CountBits(ti->tile.base() + ti->x + ti->y);
665 uint index = GB(tmp, 0, 2) + (GetTreeType(ti->tile) << 2);
666
667 /* different tree styles above one of the grounds */
669 GetTreeDensity(ti->tile) >= 2 &&
670 IsInsideMM(index, TREE_SUB_ARCTIC << 2, TREE_RAINFOREST << 2)) {
671 index += 164 - (TREE_SUB_ARCTIC << 2);
672 }
673
674 assert(index < lengthof(_tree_layout_sprite));
675
676 const PalSpriteID *s = _tree_layout_sprite[index];
677 const Coord2D<uint8_t> *d = _tree_layout_xy[GB(tmp, 2, 2)];
678
679 /* combine trees into one sprite object */
681
682 TreeListEnt te[4];
683
684 /* put the trees to draw in a list */
685 uint trees = GetTreeCount(ti->tile);
686
687 for (uint i = 0; i < trees; i++) {
688 SpriteID sprite = s[0].sprite + to_underlying(i == trees - 1 ? GetTreeGrowth(ti->tile) : TreeGrowthStage::Grown);
689 PaletteID pal = s[0].pal;
690
691 te[i].sprite = sprite;
692 te[i].pal = pal;
693 te[i].x = d->x;
694 te[i].y = d->y;
695 s++;
696 d++;
697 }
698
699 /* draw them in a sorted way */
700 int z = ti->z + GetSlopeMaxPixelZ(ti->tileh) / 2;
701
702 for (; trees > 0; trees--) {
703 uint min = te[0].x + te[0].y;
704 uint mi = 0;
705
706 for (uint i = 1; i < trees; i++) {
707 if ((uint)(te[i].x + te[i].y) < min) {
708 min = te[i].x + te[i].y;
709 mi = i;
710 }
711 }
712
713 SpriteBounds bounds{{}, {TILE_SIZE, TILE_SIZE, 48}, {te[mi].x, te[mi].y, 0}};
714 AddSortableSpriteToDraw(te[mi].sprite, te[mi].pal, ti->x, ti->y, z, bounds, IsTransparencySet(TransparencyOption::Trees));
715
716 /* replace the removed one with the last one */
717 te[mi] = te[trees - 1];
718 }
719
721}
722
723
725static int GetSlopePixelZ_Trees(TileIndex tile, uint x, uint y, [[maybe_unused]] bool ground_vehicle)
726{
727 auto [tileh, z] = GetTilePixelSlope(tile);
728
729 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
730}
731
734{
736 Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
737 if (t != nullptr) ChangeTownRating(t, RATING_TREE_DOWN_STEP, RATING_TREE_MINIMUM, flags);
738 }
739
740 uint num = GetTreeCount(tile);
741 if (IsInsideMM(GetTreeType(tile), TREE_RAINFOREST, TREE_CACTUS)) num *= 4;
742
743 if (flags.Test(DoCommandFlag::Execute)) DoClearSquare(tile);
744
746}
747
750{
751 TreeType tt = GetTreeType(tile);
752
754 td.str = STR_LAI_TREE_NAME_RAINFOREST;
755 } else {
756 td.str = tt == TREE_CACTUS ? STR_LAI_TREE_NAME_CACTUS_PLANTS : STR_LAI_TREE_NAME_TREES;
757 }
758
759 td.owner[0] = GetTileOwner(tile);
760}
761
762static void TileLoopTreesDesert(TileIndex tile)
763{
764 switch (GetTropicZone(tile)) {
769 }
770 break;
771
773 static const SoundFx forest_sounds[] = {
778 };
779 uint32_t r = Random();
780
781 if (Chance16I(1, 200, r) && _settings_client.sound.ambient) SndPlayTileFx(forest_sounds[GB(r, 16, 2)], tile);
782 break;
783 }
784
785 default: break;
786 }
787}
788
789static void TileLoopTreesAlps(TileIndex tile)
790{
791 int k = GetTileZ(tile) - GetSnowLine() + 1;
792
793 if (k < 0) {
794 switch (GetTreeGround(tile)) {
797 default: return;
798 }
799 } else {
800 uint density = std::min<uint>(k, 3);
801
804 SetTreeGroundDensity(tile, tg, density);
805 } else if (GetTreeDensity(tile) != density) {
806 SetTreeGroundDensity(tile, GetTreeGround(tile), density);
807 } else {
808 if (GetTreeDensity(tile) == 3) {
809 uint32_t r = Random();
810 if (Chance16I(1, 200, r) && _settings_client.sound.ambient) {
811 SndPlayTileFx((r & 0x80000000) ? SND_39_ARCTIC_SNOW_2 : SND_34_ARCTIC_SNOW_1, tile);
812 }
813 }
814 return;
815 }
816 }
818}
819
827{
828 /* Desert and rainforest trees need special handling. */
829 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
830 switch (GetTropicZone(tile)) {
832 /* Cacti never spread. */
833 return false;
835 return (_settings_game.construction.extra_tree_placement == ETP_SPREAD_ALL || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST);
836 default:
837 return _settings_game.construction.extra_tree_placement == ETP_SPREAD_ALL;
838 }
839 }
840
841 return (_settings_game.construction.extra_tree_placement == ETP_SPREAD_ALL);
842}
843
845static void TileLoop_Trees(TileIndex tile)
846{
847 if (GetTreeGround(tile) == TreeGround::Shore) {
848 TileLoop_Water(tile);
849 } else {
850 switch (_settings_game.game_creation.landscape) {
851 case LandscapeType::Tropic: TileLoopTreesDesert(tile); break;
852 case LandscapeType::Arctic: TileLoopTreesAlps(tile); break;
853 default: break;
854 }
855 }
856
857 AmbientSoundEffect(tile);
858
859 /* TimerGameTick::counter is incremented by 256 between each call, so ignore lower 8 bits.
860 * Also, we use a simple hash to spread the updates evenly over the map.
861 * 11 and 9 are just some co-prime numbers for better spread.
862 */
863 uint32_t cycle = 11 * TileX(tile) + 9 * TileY(tile) + (TimerGameTick::counter >> 8);
864
865 /* Handle growth of grass (under trees/on TileType::Trees tiles) at every 8th processings, like it's done for grass on TileType::Clear tiles. */
866 if ((cycle & 7) == 7 && GetTreeGround(tile) == TreeGround::Grass) {
867 uint density = GetTreeDensity(tile);
868 if (density < 3) {
869 SetTreeGroundDensity(tile, TreeGround::Grass, density + 1);
871 }
872 }
873
874 if (_settings_game.construction.extra_tree_placement == ETP_NO_GROWTH_NO_SPREAD) return;
875
876 static const uint32_t TREE_UPDATE_FREQUENCY = 16; // How many tile updates happen for one tree update
877 if (cycle % TREE_UPDATE_FREQUENCY != TREE_UPDATE_FREQUENCY - 1) return;
878
879 switch (GetTreeGrowth(tile)) {
880 case TreeGrowthStage::Grown: // regular sized tree
881 if (_settings_game.game_creation.landscape == LandscapeType::Tropic &&
882 GetTreeType(tile) != TREE_CACTUS &&
884 AddTreeGrowth(tile, 1);
885 } else {
886 switch (GB(Random(), 0, 3)) {
887 case 0: // start destructing
888 AddTreeGrowth(tile, 1);
889 break;
890
891 case 1: // add a tree
892 if (GetTreeCount(tile) < 4 && TreesOnTileCanSpread(tile)) {
893 AddTreeCount(tile, 1);
895 break;
896 }
897 [[fallthrough]];
898
899 case 2: { // add a neighbouring tree
900 if (!TreesOnTileCanSpread(tile)) break;
901
902 TreeType treetype = GetTreeType(tile);
903
905
906 if (!CanPlantTreesOnTile(tile, false)) return;
907
908 /* Don't plant trees, if ground was freshly cleared */
909 if (IsTileType(tile, TileType::Clear) && GetClearGround(tile) == ClearGround::Grass && !IsSnowTile(tile) && GetClearDensity(tile) != 3) return;
910
912
913 break;
914 }
915
916 default:
917 return;
918 }
919 }
920 break;
921
922 case TreeGrowthStage::Dead: // final stage of tree destruction
923 if (!TreesOnTileCanSpread(tile)) {
924 /* if trees can't spread just plant a new one to prevent deforestation */
926 } else if (GetTreeCount(tile) > 1) {
927 /* more than one tree, delete it */
928 AddTreeCount(tile, -1);
930 } else {
931 /* just one tree, change type into TileType::Clear */
932 switch (GetTreeGround(tile)) {
933 case TreeGround::Shore: MakeShore(tile); break;
935 case TreeGround::Rough: MakeClear(tile, ClearGround::Rough, 3); break;
937 uint density = GetTreeDensity(tile);
939 MakeSnow(tile, density);
940 break;
941 }
942 default: // snow or desert
943 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
945 } else {
946 uint density = GetTreeDensity(tile);
948 MakeSnow(tile, density);
949 }
950 break;
951 }
952 }
953 break;
954
955 default:
956 AddTreeGrowth(tile, 1);
957 break;
958 }
959
961}
962
970{
971 /* Ensure _trees_tick_ctr can be decremented past zero only once for the largest map size. */
972 static_assert(2 * (MAX_MAP_SIZE_BITS - MIN_MAP_SIZE_BITS) - 4 <= std::numeric_limits<uint8_t>::digits);
973
974 /* byte underflow */
975 uint8_t old_trees_tick_ctr = _trees_tick_ctr;
977 return old_trees_tick_ctr <= _trees_tick_ctr;
978}
979
984static void PlantRandomTree(bool rainforest)
985{
986 uint32_t r = Random();
987 TileIndex tile = RandomTileSeed(r);
988
989 if (rainforest && GetTropicZone(tile) != TropicZone::Rainforest) return;
990 if (!CanPlantTreesOnTile(tile, false)) return;
991
992 TreeType tree = GetRandomTreeType(tile, GB(r, 24, 8));
993 if (tree == TREE_INVALID) return;
994
996}
997
998void OnTick_Trees()
999{
1000 /* Don't spread trees if that's not allowed */
1001 if (_settings_game.construction.extra_tree_placement == ETP_NO_SPREAD || _settings_game.construction.extra_tree_placement == ETP_NO_GROWTH_NO_SPREAD) return;
1002
1003 /* Skip some tree ticks for map sizes below 256 * 256. 64 * 64 is 16 times smaller, so
1004 * this is the maximum number of ticks that are skipped. Number of ticks to skip is
1005 * inversely proportional to map size, so that is handled to create a mask. */
1006 int skip = Map::ScaleBySize(16);
1007 if (skip < 16 && (TimerGameTick::counter & (16 / skip - 1)) != 0) return;
1008
1009 /* place a tree at a random rainforest spot */
1010 if (_settings_game.game_creation.landscape == LandscapeType::Tropic) {
1011 for (uint c = Map::ScaleBySize(1); c > 0; c--) {
1012 PlantRandomTree(true);
1013 }
1014 }
1015
1016 if (!DecrementTreeCounter() || _settings_game.construction.extra_tree_placement == ETP_SPREAD_RAINFOREST) return;
1017
1018 /* place a tree at a random spot */
1019 PlantRandomTree(false);
1020}
1021
1022void InitializeTrees()
1023{
1024 _trees_tick_ctr = 0;
1025}
1026
1027
1030 .draw_tile_proc = DrawTile_Trees,
1031 .get_slope_pixel_z_proc = GetSlopePixelZ_Trees,
1032 .clear_tile_proc = ClearTile_Trees,
1033 .get_tile_desc_proc = GetTileDesc_Trees,
1034 .tile_loop_proc = TileLoop_Trees,
1035 .terraform_tile_proc = [](TileIndex tile, DoCommandFlags flags, int, Slope) { return Command<Commands::LandscapeClear>::Do(flags, tile); }
1036};
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
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:292
static TickCounter counter
Monotonic counter, in ticks, since start of game.
void DrawClearLandTile(const TileInfo *ti, uint8_t density)
Draw a ClearGround::Grass tile.
Definition clear_cmd.cpp:61
void DrawRoughLandTile(const TileInfo *ti)
Draw a ClearGround::Rough tile.
Definition clear_cmd.cpp:70
Functions related to clear (TileType::Clear) land.
Tables with sprites for clear land and fences.
static const SpriteID _clear_land_sprites_snow_desert[4]
Sprites of the flat tile base for each density of grass -> snow/desert transition.
Definition clear_land.h:88
Map accessors for 'clear' tiles.
bool IsClearGround(Tile t, ClearGround ct)
Set the type of clear tile.
Definition clear_map.h:65
void MakeSnow(Tile t, uint density=0)
Make a snow tile.
Definition clear_map.h:294
ClearGround
Ground types.
Definition clear_map.h:21
@ Desert
Desert with transition (1,3).
Definition clear_map.h:26
@ Rocks
Rocks with snow transition (0-3).
Definition clear_map.h:24
@ Fields
Farm fields (3).
Definition clear_map.h:25
@ Grass
Plain grass with dirt transition (0-3).
Definition clear_map.h:22
@ Rough
Rough mounds (3).
Definition clear_map.h:23
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:253
ClearGround GetClearGround(Tile t)
Get the type of clear tile.
Definition clear_map.h:52
bool IsSnowTile(Tile t)
Test if a tile is covered with snow.
Definition clear_map.h:40
uint GetClearDensity(Tile t)
Get the density of a non-field clear tile.
Definition clear_map.h:77
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
execute the given command
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
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.
@ End
Used to iterate.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:107
@ Construction
Construction costs.
@ Other
Other expenses.
@ ClearTrees
Price for destroying trees.
@ BuildTrees
Price for planting trees.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to world/map generation.
void IncreaseGeneratingWorldProgress(GenWorldProgress cls)
Increases the current stage of the world generation with one.
@ Trees
Generate trees.
Definition genworld.h:68
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:50
All geometry types in OpenTTD.
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.
const TileTypeProcs _tile_type_trees_procs
TileTypeProcs definitions for TileType::Trees tiles.
Definition landscape.cpp:56
Functions related to OTTD's landscape.
Command definitions related to landscape (slopes etc.).
@ Arctic
Landscape with snow levels.
@ Toyland
Landscape with funky industries and vehicles.
@ Tropic
Landscape with distinct rainforests and deserts,.
@ Temperate
Base landscape.
#define Point
Macro that prevents name conflicts between included headers.
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:186
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:120
TileIndex RandomTileSeed(uint32_t r)
Get a random tile out of a given seed.
Definition map_func.h:645
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
#define RandomTile()
Get a valid random tile.
Definition map_func.h:656
TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition map_func.h:588
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.
uint8_t _trees_tick_ctr
Determines when to consider building more trees.
Definition tree_cmd.cpp:45
Functions related to generic callbacks.
void AmbientSoundEffect(TileIndex tile)
Play an ambient sound effect for an empty tile.
@ Editor
In the scenario editor.
Definition openttd.h:21
Pseudo random number generator.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
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:61
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
@ Original
The original algorithm.
@ None
No tree placer algorithm.
@ Improved
A 'improved' algorithm.
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:98
uint SlopeToSpriteOffset(Slope s)
Returns the Sprite offset for a given Slope.
Definition slope_func.h:423
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:183
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
Functions related to sound.
SoundFx
Sound effects from baseset.
Definition sound_type.h:46
@ SND_39_ARCTIC_SNOW_2
57 == 0x39 Tree ambient: arctic snow (2): heavy wind
Definition sound_type.h:105
@ SND_44_RAINFOREST_3
68 == 0x44 Tree ambient: rainforest ambient (3): monkeys
Definition sound_type.h:116
@ SND_34_ARCTIC_SNOW_1
52 == 0x34 Tree ambient: arctic snow (1): wind
Definition sound_type.h:100
@ SND_43_RAINFOREST_2
67 == 0x43 Tree ambient: rainforest ambient (2): lion
Definition sound_type.h:115
@ SND_42_RAINFOREST_1
66 == 0x42 Tree ambient: rainforest ambient (1): bird (1)
Definition sound_type.h:114
@ SND_48_RAINFOREST_4
72 == 0x48 Tree ambient: rainforest ambient (4): bird (2)
Definition sound_type.h:120
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:261
StrongType::Typedef< uint32_t, struct StringIDTag, StrongType::Compare, StrongType::Integer > StringID
Numeric value that represents a string, independent of the selected language.
static constexpr StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
uint32_t tree_limit
Amount of trees we can (still) plant (times 65536).
A coordinate with two dimensions.
T y
Y coordinate.
T x
X coordinate.
T x
X coordinate.
T y
Y coordinate.
T z
Z coordinate.
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:331
static uint Size()
Get the size of the map.
Definition map_func.h:280
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 Company * GetIfValid(auto index)
Tile description for the 'land area information' tool.
Definition tile_cmd.h:40
StringID str
Description of the tile.
Definition tile_cmd.h:41
std::array< Owner, 4 > owner
Name of the owner(s).
Definition tile_cmd.h:43
Tile information, used while rendering the tile.
Definition tile_cmd.h:34
Slope tileh
Slope of the tile.
Definition tile_cmd.h:35
TileIndex tile
Tile index.
Definition tile_cmd.h:36
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:214
Town data structure.
Definition town.h:64
int GetTileZ(TileIndex tile)
Get bottom height of the tile.
Definition tile_map.cpp:115
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
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
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
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
@ Desert
Tile is desert.
Definition tile_type.h:83
@ Rainforest
Rainforest tile.
Definition tile_type.h:84
@ Normal
Normal tropiczone.
Definition tile_type.h:82
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
TileType
The different types of tiles.
Definition tile_type.h:48
@ Water
Water tile.
Definition tile_type.h:55
@ Void
Invisible tiles at the SW and SE border.
Definition tile_type.h:56
@ Trees
Tile with one or more trees.
Definition tile_type.h:53
@ Clear
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition tile_type.h:49
OrthogonalTileArea TileArea
Shorthand for the much more common orthogonal tile area.
Definition of the tick-based game-timer.
Base of the town class.
void ChangeTownRating(Town *t, int add, int max, DoCommandFlags flags)
Changes town rating of the current company.
Town * ClosestTownFromTile(TileIndex tile, uint threshold)
Return the town closest (in distance or ownership) to a given tile, within a given threshold.
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...
void PlaceTree(TileIndex tile, uint32_t r, bool keep_density)
Make a random tree tile of the given tile.
Definition tree_cmd.cpp:172
static bool TreesOnTileCanSpread(TileIndex tile)
Check if trees on this tile are allowed to spread.
Definition tree_cmd.cpp:826
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:433
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:99
static TreeType GetRandomTreeType(TileIndex tile, uint seed)
Get a random TreeType for the given tile based on a given seed.
Definition tree_cmd.cpp:141
static bool IsPointInTriangle(int x, int y, const Point &v1, const Point &v2, const Point &v3)
Returns true if the given coordinates lie within a triangle.
Definition tree_cmd.cpp:263
void GenerateTrees()
Place new trees.
Definition tree_cmd.cpp:480
static void DrawTile_Trees(TileInfo *ti)
Tile callback function signature for drawing a tile and its contents to the screen.
Definition tree_cmd.cpp:652
static void CreateStarShapedPolygon(int radius, std::span< const BlobHarmonic > harmonics, std::span< Point > shape)
Creates a star-shaped polygon originating from (0, 0) as defined by the given harmonics.
Definition tree_cmd.cpp:204
static const uint16_t EDITOR_TREE_DIV
Game editor tree generation divisor factor.
Definition tree_cmd.cpp:49
static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
Tests if a tile can be converted to TileType::Trees This is true for clear ground without farms or ro...
Definition tree_cmd.cpp:59
void PlaceTreesRandomly()
Place some trees randomly.
Definition tree_cmd.cpp:370
static const uint16_t DEFAULT_TREE_STEPS
Default number of attempts for placing trees.
Definition tree_cmd.cpp:47
static const uint16_t DEFAULT_RAINFOREST_TREE_STEPS
Default number of attempts for placing extra trees at rainforest in tropic.
Definition tree_cmd.cpp:48
static bool IsPointInStarShapedPolygon(int x, int y, std::span< Point > shape)
Returns true if the given coordinates lie within a star shaped polygon.
Definition tree_cmd.cpp:282
static TreeGround TreeGroundFromClearGround(ClearGround clearground)
Get equivalent TreeGround for a ClearGround.
Definition tree_cmd.cpp:79
static void PlantRandomTree(bool rainforest)
Place a random tree on a random tile.
Definition tree_cmd.cpp:984
CommandCost CmdPlantTree(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, uint8_t tree_to_plant, bool diagonal)
Plant a tree.
Definition tree_cmd.cpp:515
static void PlaceTreeAtSameHeight(TileIndex tile, int height)
Place a tree at the same height as an existing tree.
Definition tree_cmd.cpp:341
static void CreateRandomStarShapedPolygon(int radius, std::span< Point > shape)
Creates a random star-shaped polygon originating from (0, 0).
Definition tree_cmd.cpp:235
static CommandCost ClearTile_Trees(TileIndex tile, DoCommandFlags flags)
Tile callback function signature for clearing a tile.
Definition tree_cmd.cpp:733
static int GetSlopePixelZ_Trees(TileIndex tile, uint x, uint y, bool ground_vehicle)
Tile callback function signature for obtaining the world Z coordinate of a given point of a tile.
Definition tree_cmd.cpp:725
static void PlaceTreeGroups(uint num_groups)
Creates a number of tree groups.
Definition tree_cmd.cpp:301
static void GetTileDesc_Trees(TileIndex tile, TileDesc &td)
Tile callback function signature for obtaining a tile description.
Definition tree_cmd.cpp:749
ExtraTreePlacement
Where to place trees while in-game?
Definition tree_cmd.cpp:37
@ ETP_SPREAD_RAINFOREST
Grow trees on tiles that have them, only spread to new ones in rainforests.
Definition tree_cmd.cpp:39
@ ETP_NO_SPREAD
Grow trees on tiles that have them but don't spread to new ones.
Definition tree_cmd.cpp:38
@ ETP_NO_GROWTH_NO_SPREAD
Don't grow trees and don't spread them at all.
Definition tree_cmd.cpp:41
@ ETP_SPREAD_ALL
Grow trees and spread them without restrictions.
Definition tree_cmd.cpp:40
bool DecrementTreeCounter()
Decrement the tree tick counter.
Definition tree_cmd.cpp:969
static void TileLoop_Trees(TileIndex tile)
Tile callback function signature for running periodic tile updates.
Definition tree_cmd.cpp:845
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:164
TreeGrowthStage GetTreeGrowth(Tile t)
Returns the tree growth stage.
Definition tree_map.h:196
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:245
void SetTreeGrowth(Tile t, TreeGrowthStage g)
Sets the tree growth stage of a tile.
Definition tree_map.h:227
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:181
TreeGround
Enumeration for ground types of tiles with trees.
Definition tree_map.h:52
@ SnowOrDesert
Snow or desert, depending on landscape.
Definition tree_map.h:55
@ Shore
Shore.
Definition tree_map.h:56
@ RoughSnow
A snow tile that is rough underneath.
Definition tree_map.h:57
@ Grass
Normal grass.
Definition tree_map.h:53
@ Rough
Rough land.
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:145
void AddTreeGrowth(Tile t, int a)
Add a value to the tree growth stage.
Definition tree_map.h:211
uint GetTreeDensity(Tile t)
Returns the 'density' of a tile with trees.
Definition tree_map.h:128
TreeGrowthStage
Enumeration for tree growth stages.
Definition tree_map.h:65
@ Grown
Fully grown tree.
Definition tree_map.h:69
@ Dead
Dead tree.
Definition tree_map.h:72
@ Growing1
First stage of growth.
Definition tree_map.h:66
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:765
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:664
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition viewport.cpp:775
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:579
Functions related to (drawing on) viewports.
Functions related to water management.
void TileLoop_Water(TileIndex tile)
Tile callback function signature for running periodic tile updates.
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:99
bool IsCoast(Tile t)
Is it a coast tile?
Definition water_map.h:205
WaterTileType GetWaterTileType(Tile t)
Get the water tile type of a tile.
Definition water_map.h:82
void MakeShore(Tile t, bool rocks=false)
Helper function to make a coast tile.
Definition water_map.h:389
@ Coast
Coast.
Definition water_map.h:33