OpenTTD Source 20260311-master-g511d3794ce
water_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 "landscape.h"
12#include "viewport_func.h"
13#include "command_func.h"
14#include "town.h"
15#include "news_func.h"
16#include "depot_base.h"
17#include "depot_func.h"
18#include "water.h"
19#include "industry_map.h"
20#include "newgrf_canal.h"
21#include "strings_func.h"
22#include "vehicle_func.h"
23#include "sound_func.h"
24#include "company_func.h"
25#include "clear_map.h"
26#include "tree_map.h"
27#include "aircraft.h"
28#include "effectvehicle_func.h"
29#include "tunnelbridge_map.h"
30#include "station_base.h"
31#include "ai/ai.hpp"
32#include "game/game.hpp"
33#include "core/random_func.hpp"
34#include "core/backup_type.hpp"
36#include "company_base.h"
37#include "company_gui.h"
38#include "newgrf_generic.h"
39#include "industry.h"
40#include "water_cmd.h"
41#include "landscape_cmd.h"
43#include "town_type.h"
44
45#include "table/strings.h"
46
47#include "safeguards.h"
48
52static const Directions _flood_from_dirs[] = {
53 {DIR_NW, DIR_SW, DIR_SE, DIR_NE}, // SLOPE_FLAT
54 {DIR_NE, DIR_SE}, // SLOPE_W
55 {DIR_NW, DIR_NE}, // SLOPE_S
56 {DIR_NE}, // SLOPE_SW
57 {DIR_NW, DIR_SW}, // SLOPE_E
58 {}, // SLOPE_EW
59 {DIR_NW}, // SLOPE_SE
60 {DIR_N, DIR_NW, DIR_NE}, // SLOPE_WSE, SLOPE_STEEP_S
61 {DIR_SW, DIR_SE}, // SLOPE_N
62 {DIR_SE}, // SLOPE_NW
63 {}, // SLOPE_NS
64 {DIR_E, DIR_NE, DIR_SE}, // SLOPE_NWS, SLOPE_STEEP_W
65 {DIR_SW}, // SLOPE_NE
66 {DIR_S, DIR_SW, DIR_SE}, // SLOPE_ENW, SLOPE_STEEP_N
67 {DIR_W, DIR_SW, DIR_NW}, // SLOPE_SEN, SLOPE_STEEP_E
68};
69
76static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
77{
78 if (IsValidTile(tile) && IsTileType(tile, TileType::Water) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
79}
80
88{
89 for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
91 }
92}
93
99{
100 for (Direction dir = DIR_BEGIN; dir != DIR_END; dir++) {
101 TileIndex dest = tile + TileOffsByDir(dir);
102 if (IsValidTile(dest) && IsTileType(dest, TileType::Water)) SetNonFloodingWaterTile(dest, false);
103 }
104}
105
113CommandCost CmdBuildShipDepot(DoCommandFlags flags, TileIndex tile, Axis axis)
114{
115 if (!IsValidAxis(axis)) return CMD_ERROR;
116 TileIndex tile2 = tile + TileOffsByAxis(axis);
117
118 if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
119 return CommandCost(STR_ERROR_MUST_BE_BUILT_ON_WATER);
120 }
121
122 if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
123
124 if (!IsTileFlat(tile) || !IsTileFlat(tile2)) {
125 /* Prevent depots on rapids */
126 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
127 }
128
129 if (!Depot::CanAllocateItem()) return CMD_ERROR;
130
131 WaterClass wc1 = GetWaterClass(tile);
132 WaterClass wc2 = GetWaterClass(tile2);
134
135 bool add_cost = !IsWaterTile(tile);
136 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags | DoCommandFlag::Auto, tile);
137 if (ret.Failed()) return ret;
138 if (add_cost) {
139 cost.AddCost(ret.GetCost());
140 }
141 add_cost = !IsWaterTile(tile2);
142 ret = Command<Commands::LandscapeClear>::Do(flags | DoCommandFlag::Auto, tile2);
143 if (ret.Failed()) return ret;
144 if (add_cost) {
145 cost.AddCost(ret.GetCost());
146 }
147
148 if (flags.Test(DoCommandFlag::Execute)) {
149 Depot *depot = Depot::Create(tile);
150
151 uint new_water_infra = 2 * LOCK_DEPOT_TILE_FACTOR;
152 /* Update infrastructure counts after the tile clears earlier.
153 * Clearing object tiles may result in water tiles which are already accounted for in the water infrastructure total.
154 * See: MakeWaterKeepingClass() */
155 if (wc1 == WaterClass::Canal && !(HasTileWaterClass(tile) && GetWaterClass(tile) == WaterClass::Canal && IsTileOwner(tile, _current_company))) new_water_infra++;
156 if (wc2 == WaterClass::Canal && !(HasTileWaterClass(tile2) && GetWaterClass(tile2) == WaterClass::Canal && IsTileOwner(tile2, _current_company))) new_water_infra++;
157
158 Company::Get(_current_company)->infrastructure.water += new_water_infra;
160
161 MakeShipDepot(tile, _current_company, depot->index, DepotPart::North, axis, wc1);
162 MakeShipDepot(tile2, _current_company, depot->index, DepotPart::South, axis, wc2);
164 CheckForDockingTile(tile2);
166 MarkTileDirtyByTile(tile2);
167 MakeDefaultName(depot);
168 }
169
170 return cost;
171}
172
180{
181 assert(IsValidTile(t));
182 switch (GetTileType(t)) {
183 case TileType::Water:
184 if (IsLock(t) && GetLockPart(t) == LockPart::Middle) return false;
185 [[fallthrough]];
190
191 default:
192 return false;
193 }
194}
195
202{
203 for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
204 TileIndex tile = t + TileOffsByDiagDir(d);
205 if (!IsValidTile(tile)) continue;
206
207 if (IsDockTile(tile) && IsDockWaterPart(tile)) {
208 Station::GetByTile(tile)->docking_station.Add(t);
209 SetDockingTile(t, true);
210 }
211 if (IsTileType(tile, TileType::Industry)) {
213 if (st != nullptr) {
214 st->docking_station.Add(t);
215 SetDockingTile(t, true);
216 }
217 }
218 if (IsTileType(tile, TileType::Station) && IsOilRig(tile)) {
219 Station::GetByTile(tile)->docking_station.Add(t);
220 SetDockingTile(t, true);
221 }
222 }
223}
224
225void MakeWaterKeepingClass(TileIndex tile, Owner o)
226{
227 WaterClass wc = GetWaterClass(tile);
228
229 /* Autoslope might turn an originally canal or river tile into land */
230 auto [slope, z] = GetTileSlopeZ(tile);
231
232 if (slope != SLOPE_FLAT) {
233 if (wc == WaterClass::Canal) {
234 /* If we clear the canal, we have to remove it from the infrastructure count as well. */
236 if (c != nullptr) {
239 }
240 /* Sloped canals are locks and no natural water remains whatever the slope direction */
242 }
243
244 /* Only river water should be restored on appropriate slopes. Other water would be invalid on slopes */
247 }
248 }
249
250 if (wc == WaterClass::Sea && z > 0) {
251 /* Update company infrastructure count. */
253 if (c != nullptr) {
256 }
257
259 }
260
261 /* Zero map array and terminate animation */
262 DoClearSquare(tile);
263
264 /* Maybe change to water */
265 switch (wc) {
266 case WaterClass::Sea: MakeSea(tile); break;
267 case WaterClass::Canal: MakeCanal(tile, o, Random()); break;
268 case WaterClass::River: MakeRiver(tile, Random()); break;
269 default: break;
270 }
271
274}
275
276static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlags flags)
277{
278 if (!IsShipDepot(tile)) return CMD_ERROR;
279
281 if (ret.Failed()) return ret;
282
283 TileIndex tile2 = GetOtherShipDepotTile(tile);
284
285 /* do not check for ship on tile when company goes bankrupt */
286 if (!flags.Test(DoCommandFlag::Bankrupt)) {
287 ret = EnsureNoVehicleOnGround(tile);
288 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
289 if (ret.Failed()) return ret;
290 }
291
292 bool do_clear = flags.Test(DoCommandFlag::ForceClearTile);
293
294 if (flags.Test(DoCommandFlag::Execute)) {
295 delete Depot::GetByTile(tile);
296
298 if (c != nullptr) {
300 if (do_clear && GetWaterClass(tile) == WaterClass::Canal) c->infrastructure.water--;
302 }
303
304 if (!do_clear) MakeWaterKeepingClass(tile, GetTileOwner(tile));
305 MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
306 }
307
309}
310
317{
318 static constexpr uint8_t MINIMAL_BRIDGE_HEIGHT[to_underlying(LockPart::End)] = {
319 2, // LockPart::Middle
320 3, // LockPart::Lower
321 2, // LockPart::Upper
322 };
323 return MINIMAL_BRIDGE_HEIGHT[to_underlying(lock_part)];
324}
325
333static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlags flags)
334{
336
337 TileIndexDiff delta = TileOffsByDiagDir(dir);
339 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
340 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
341 if (ret.Failed()) return ret;
342
343 /* middle tile */
345 ret = Command<Commands::LandscapeClear>::Do(flags, tile);
346 if (ret.Failed()) return ret;
347 cost.AddCost(ret.GetCost());
348
349 /* lower tile */
350 if (!IsWaterTile(tile - delta)) {
351 ret = Command<Commands::LandscapeClear>::Do(flags, tile - delta);
352 if (ret.Failed()) return ret;
353 cost.AddCost(ret.GetCost());
355 }
356 if (!IsTileFlat(tile - delta)) {
357 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
358 }
359 WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WaterClass::Canal;
360
361 /* upper tile */
362 if (!IsWaterTile(tile + delta)) {
363 ret = Command<Commands::LandscapeClear>::Do(flags, tile + delta);
364 if (ret.Failed()) return ret;
365 cost.AddCost(ret.GetCost());
367 }
368 if (!IsTileFlat(tile + delta)) {
369 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
370 }
371 WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WaterClass::Canal;
372
373 for (LockPart lock_part = LockPart::Middle; TileIndex t : {tile, tile - delta, tile + delta}) {
376 return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff);
377 }
378 ++lock_part;
379 }
380
381 if (flags.Test(DoCommandFlag::Execute)) {
382 /* Update company infrastructure counts. */
384 if (c != nullptr) {
385 /* Counts for the water. */
386 if (!IsWaterTile(tile - delta)) c->infrastructure.water++;
387 if (!IsWaterTile(tile + delta)) c->infrastructure.water++;
388 /* Count for the lock itself. */
389 c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock is three tiles.
391 }
392
393 MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
394 CheckForDockingTile(tile - delta);
395 CheckForDockingTile(tile + delta);
397 MarkTileDirtyByTile(tile - delta);
398 MarkTileDirtyByTile(tile + delta);
399 MarkCanalsAndRiversAroundDirty(tile - delta);
400 MarkCanalsAndRiversAroundDirty(tile + delta);
401 InvalidateWaterRegion(tile - delta);
402 InvalidateWaterRegion(tile + delta);
403 }
405
406 return cost;
407}
408
415static CommandCost RemoveLock(TileIndex tile, DoCommandFlags flags)
416{
417 if (GetTileOwner(tile) != OWNER_NONE) {
419 if (ret.Failed()) return ret;
420 }
421
423
424 /* make sure no vehicle is on the tile. */
426 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
427 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
428 if (ret.Failed()) return ret;
429
430 if (flags.Test(DoCommandFlag::Execute)) {
431 /* Remove middle part from company infrastructure count. */
433 if (c != nullptr) {
434 c->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // three parts of the lock.
436 }
437
438 if (GetWaterClass(tile) == WaterClass::River) {
439 MakeRiver(tile, Random());
440 } else {
441 DoClearSquare(tile);
443 }
444 MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
445 MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
447 MarkCanalsAndRiversAroundDirty(tile - delta);
448 MarkCanalsAndRiversAroundDirty(tile + delta);
449 }
450
452}
453
460CommandCost CmdBuildLock(DoCommandFlags flags, TileIndex tile)
461{
463 if (dir == INVALID_DIAGDIR) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
464
465 TileIndex lower_tile = TileAddByDiagDir(tile, ReverseDiagDir(dir));
466
467 /* If freeform edges are disabled, don't allow building on edge tiles. */
468 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(lower_tile), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(lower_tile), 1, Map::MaxY() - 1))) {
469 return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
470 }
471
472 return DoBuildLock(tile, dir, flags);
473}
474
480{
481 MakeRiver(tile, Random());
483
484 /* Remove desert directly around the river tile. */
487 }
488}
489
499CommandCost CmdBuildCanal(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
500{
501 if (start_tile >= Map::Size() || !IsValidWaterClass(wc)) return CMD_ERROR;
502
503 /* Outside of the editor you can only build canals, not oceans */
504 if (wc != WaterClass::Canal && _game_mode != GM_EDITOR) return CMD_ERROR;
505
507
508 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
509 for (; *iter != INVALID_TILE; ++(*iter)) {
510 TileIndex current_tile = *iter;
511 CommandCost ret;
512
513 Slope slope = GetTileSlope(current_tile);
514 if (slope != SLOPE_FLAT && (wc != WaterClass::River || !IsInclinedSlope(slope))) {
515 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
516 }
517
518 bool water = IsWaterTile(current_tile);
519
520 /* Outside the editor, prevent building canals over your own or OWNER_NONE owned canals */
521 if (water && IsCanal(current_tile) && _game_mode != GM_EDITOR && (IsTileOwner(current_tile, _current_company) || IsTileOwner(current_tile, OWNER_NONE))) continue;
522
523 ret = Command<Commands::LandscapeClear>::Do(flags, current_tile);
524 if (ret.Failed()) return ret;
525
526 if (!water) cost.AddCost(ret.GetCost());
527
528 if (flags.Test(DoCommandFlag::Execute)) {
529 if (IsTileType(current_tile, TileType::Water) && IsCanal(current_tile)) {
530 Owner owner = GetTileOwner(current_tile);
531 if (Company::IsValidID(owner)) {
532 Company::Get(owner)->infrastructure.water--;
534 }
535 }
536
537 switch (wc) {
539 MakeRiver(current_tile, Random());
540 if (_game_mode == GM_EDITOR) {
541 /* Remove desert directly around the river tile. */
542 for (auto t : SpiralTileSequence(current_tile, RIVER_OFFSET_DESERT_DISTANCE)) {
544 }
545 }
546 break;
547
548 case WaterClass::Sea:
549 if (TileHeight(current_tile) == 0) {
550 MakeSea(current_tile);
551 break;
552 }
553 [[fallthrough]];
554
555 default:
556 MakeCanal(current_tile, _current_company, Random());
558 Company::Get(_current_company)->infrastructure.water++;
560 }
561 break;
562 }
563 MarkTileDirtyByTile(current_tile);
564 MarkCanalsAndRiversAroundDirty(current_tile);
565 CheckForDockingTile(current_tile);
566 }
567
569 }
570
571 if (cost.GetCost() == 0) {
572 return CommandCost(STR_ERROR_ALREADY_BUILT);
573 } else {
574 return cost;
575 }
576}
577
578
580static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlags flags)
581{
582 switch (GetWaterTileType(tile)) {
584 if (flags.Test(DoCommandFlag::NoWater)) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
585
586 Money base_cost = IsCanal(tile) ? _price[Price::ClearCanal] : _price[Price::ClearWater];
587 /* Make sure freeform edges are allowed or it's not an edge tile. */
588 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(tile), 1, Map::MaxX() - 1) ||
589 !IsInsideMM(TileY(tile), 1, Map::MaxY() - 1))) {
590 return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
591 }
592
593 /* Make sure no vehicle is on the tile */
595 if (ret.Failed()) return ret;
596
597 Owner owner = GetTileOwner(tile);
598 if (owner != OWNER_WATER && owner != OWNER_NONE) {
599 ret = CheckTileOwnership(tile);
600 if (ret.Failed()) return ret;
601 }
602
603 if (flags.Test(DoCommandFlag::Execute)) {
604 if (IsCanal(tile) && Company::IsValidID(owner)) {
605 Company::Get(owner)->infrastructure.water--;
607 }
608
609 /* Handle local authority impact */
610 if (IsRiver(tile)) {
612 Town *town = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
613 if (town != nullptr) ChangeTownRating(town, RATING_WATER_RIVER_DOWN_STEP, RATING_WATER_MINIMUM, flags);
614 }
615 }
616
617 DoClearSquare(tile);
620 }
621
622 return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
623 }
624
626 Slope slope = GetTileSlope(tile);
627
628 /* Make sure no vehicle is on the tile */
630 if (ret.Failed()) return ret;
631
632 if (flags.Test(DoCommandFlag::Execute)) {
633 DoClearSquare(tile);
636 }
637 if (IsSlopeWithOneCornerRaised(slope)) {
639 } else {
641 }
642 }
643
644 case WaterTileType::Lock: {
645 static const TileIndexDiffC _lock_tomiddle_offs[to_underlying(LockPart::End)][DIAGDIR_END] = {
646 /* NE SE SW NW */
647 { { 0, 0}, {0, 0}, { 0, 0}, {0, 0} }, // LockPart::Middle
648 { {-1, 0}, {0, 1}, { 1, 0}, {0, -1} }, // LockPart::Lower
649 { { 1, 0}, {0, -1}, {-1, 0}, {0, 1} }, // LockPart::Upper
650 };
651
652 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
654 /* move to the middle tile.. */
655 return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[to_underlying(GetLockPart(tile))][GetLockDirection(tile)]), flags);
656 }
657
659 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
660 return RemoveShipDepot(tile, flags);
661
662 default:
663 NOT_REACHED();
664 }
665}
666
676{
677 switch (GetTileType(tile)) {
678 case TileType::Water:
679 switch (GetWaterTileType(tile)) {
680 default: NOT_REACHED();
681 case WaterTileType::Depot: case WaterTileType::Clear: return true;
683
685 switch (GetTileSlope(tile)) {
686 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
687 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
688 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
689 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
690 default: return false;
691 }
692 }
693
696 assert(IsPlainRail(tile));
697 switch (GetTileSlope(tile)) {
698 case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
699 case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
700 case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
701 case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
702 default: return false;
703 }
704 }
705 return false;
706
708 if (IsOilRig(tile)) {
709 /* Do not draw waterborders inside of industries.
710 * Note: There is no easy way to detect the industry of an oilrig tile. */
711 TileIndex src_tile = tile + TileOffsByDir(from);
712 if ((IsTileType(src_tile, TileType::Station) && IsOilRig(src_tile)) ||
713 (IsTileType(src_tile, TileType::Industry))) return true;
714
715 return IsTileOnWater(tile);
716 }
717 return (IsDock(tile) && IsTileFlat(tile)) || IsBuoy(tile);
718
719 case TileType::Industry: {
720 /* Do not draw waterborders inside of industries.
721 * Note: There is no easy way to detect the industry of an oilrig tile. */
722 TileIndex src_tile = tile + TileOffsByDir(from);
723 if ((IsTileType(src_tile, TileType::Station) && IsOilRig(src_tile)) ||
724 (IsTileType(src_tile, TileType::Industry) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
725
726 return IsTileOnWater(tile);
727 }
728
729 case TileType::Object: return IsTileOnWater(tile);
730
732
733 case TileType::Void: return true; // consider map border as water, esp. for rivers
734
735 default: return false;
736 }
737}
738
746static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
747{
748 if (base != SPR_FLAT_WATER_TILE) {
749 /* Only call offset callback if the sprite is NewGRF-provided. */
750 offset = GetCanalSpriteOffset(feature, tile, offset);
751 }
752 DrawGroundSprite(base + offset, PAL_NONE);
753}
754
761static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
762{
763 CanalFeature feature;
764 SpriteID base = 0;
765 if (canal) {
766 feature = CF_DIKES;
767 base = GetCanalSprite(CF_DIKES, tile);
768 if (base == 0) base = SPR_CANAL_DIKES_BASE;
769 } else {
770 feature = CF_RIVER_EDGE;
771 base = GetCanalSprite(CF_RIVER_EDGE, tile);
772 if (base == 0) return; // Don't draw if no sprites provided.
773 }
774
775 uint wa;
776
777 /* determine the edges around with water. */
778 wa = IsWateredTile(TileAddXY(tile, -1, 0), DIR_SW) << 0;
779 wa += IsWateredTile(TileAddXY(tile, 0, 1), DIR_NW) << 1;
780 wa += IsWateredTile(TileAddXY(tile, 1, 0), DIR_NE) << 2;
781 wa += IsWateredTile(TileAddXY(tile, 0, -1), DIR_SE) << 3;
782
783 if (!(wa & 1)) DrawWaterSprite(base, offset, feature, tile);
784 if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
785 if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
786 if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
787
788 /* right corner */
789 switch (wa & 0x03) {
790 case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
791 case 3: if (!IsWateredTile(TileAddXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
792 }
793
794 /* bottom corner */
795 switch (wa & 0x06) {
796 case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
797 case 6: if (!IsWateredTile(TileAddXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
798 }
799
800 /* left corner */
801 switch (wa & 0x0C) {
802 case 0: DrawWaterSprite(base, offset + 6, feature, tile); break;
803 case 12: if (!IsWateredTile(TileAddXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
804 }
805
806 /* upper corner */
807 switch (wa & 0x09) {
808 case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
809 case 9: if (!IsWateredTile(TileAddXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
810 }
811}
812
815{
816 DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
817}
818
823static void DrawCanalWater(TileIndex tile)
824{
825 SpriteID image = SPR_FLAT_WATER_TILE;
826 if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
827 /* First water slope sprite is flat water. */
828 image = GetCanalSprite(CF_WATERSLOPE, tile);
829 if (image == 0) image = SPR_FLAT_WATER_TILE;
830 }
831 DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
832
833 DrawWaterEdges(true, 0, tile);
834}
835
836#include "table/water_land.h"
837
848static void DrawWaterTileStruct(const TileInfo *ti, std::span<const DrawTileSeqStruct> seq, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
849{
850 /* Don't draw if buildings are invisible. */
851 if (IsInvisibilitySet(TO_BUILDINGS)) return;
852
853 for (const DrawTileSeqStruct &dtss : seq) {
854 uint tile_offs = offset + dtss.image.sprite;
855 if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
856 AddSortableSpriteToDraw(base + tile_offs, palette, *ti, dtss, IsTransparencySet(TO_BUILDINGS));
857 }
858}
859
864static void DrawWaterLock(const TileInfo *ti)
865{
866 LockPart part = GetLockPart(ti->tile);
867 const DrawTileSprites &dts = _lock_display_data[to_underlying(part)][GetLockDirection(ti->tile)];
868
869 /* Draw ground sprite. */
870 SpriteID image = dts.ground.sprite;
871
872 SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
873 if (water_base == 0) {
874 /* Use default sprites. */
875 water_base = SPR_CANALS_BASE;
876 } else if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
877 /* NewGRF supplies a flat sprite as first sprite. */
878 if (image == SPR_FLAT_WATER_TILE) {
879 image = water_base;
880 } else {
881 image++;
882 }
883 }
884
885 if (image < 5) image += water_base;
886 DrawGroundSprite(image, PAL_NONE);
887
888 /* Draw structures. */
889 uint zoffs = 0;
890 SpriteID base = GetCanalSprite(CF_LOCKS, ti->tile);
891
892 if (base == 0) {
893 /* If no custom graphics, use defaults. */
894 base = SPR_LOCK_BASE;
895 uint8_t z_threshold = part == LockPart::Upper ? 8 : 0;
896 zoffs = ti->z > z_threshold ? 24 : 0;
897 }
898
899 DrawWaterTileStruct(ti, dts.GetSequence(), base, zoffs, PAL_NONE, CF_LOCKS);
900}
901
906static void DrawWaterDepot(const TileInfo *ti)
907{
908 DrawWaterClassGround(ti);
909 DrawWaterTileStruct(ti, _shipdepot_display_data[GetShipDepotAxis(ti->tile)][to_underlying(GetShipDepotPart(ti->tile))].seq, 0, 0, GetCompanyPalette(GetTileOwner(ti->tile)), CF_END);
910}
911
912static void DrawRiverWater(const TileInfo *ti)
913{
914 SpriteID image = SPR_FLAT_WATER_TILE;
915 uint offset = 0;
916 uint edges_offset = 0;
917
918 if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
919 image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
920 if (image == 0) {
921 switch (ti->tileh) {
922 case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
923 case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
924 case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
925 case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
926 default: image = SPR_FLAT_WATER_TILE; break;
927 }
928 } else {
929 /* Flag bit 0 indicates that the first sprite is flat water. */
930 offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
931
932 switch (ti->tileh) {
933 case SLOPE_SE: edges_offset += 12; break;
934 case SLOPE_NE: offset += 1; edges_offset += 24; break;
935 case SLOPE_SW: offset += 2; edges_offset += 36; break;
936 case SLOPE_NW: offset += 3; edges_offset += 48; break;
937 default: offset = 0; break;
938 }
939
940 offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
941 }
942 }
943
944 DrawGroundSprite(image + offset, PAL_NONE);
945
946 /* Draw river edges if available. */
947 DrawWaterEdges(false, edges_offset, ti->tile);
948}
949
950void DrawShoreTile(Slope tileh)
951{
952 /* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
953 * This allows to calculate the proper sprite to display for this Slope */
954 static const uint8_t tileh_to_shoresprite[32] = {
955 0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
956 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 15, 0,
957 };
958
959 assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
960 assert(tileh != SLOPE_FLAT); // Shore is never flat
961
962 assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS)); // No suitable sprites for current flooding behaviour
963
964 DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
965}
966
967void DrawWaterClassGround(const TileInfo *ti)
968{
969 switch (GetWaterClass(ti->tile)) {
970 case WaterClass::Sea: DrawSeaWater(ti->tile); break;
971 case WaterClass::Canal: DrawCanalWater(ti->tile); break;
972 case WaterClass::River: DrawRiverWater(ti); break;
973 default: NOT_REACHED();
974 }
975}
976
978static void DrawTile_Water(TileInfo *ti)
979{
980 switch (GetWaterTileType(ti->tile)) {
982 DrawWaterClassGround(ti);
983 /* A plain water tile can be traversed in any direction, so setting blocked pillars here would mean all bridges
984 * with edges would have no pillars above water. Instead prefer current behaviour of ships passing through. */
985 DrawBridgeMiddle(ti, {});
986 break;
987
989 DrawShoreTile(ti->tileh);
990 DrawBridgeMiddle(ti, {});
991 break;
992 }
993
995 DrawWaterLock(ti);
997 ? BridgePillarFlags{BridgePillarFlag::EdgeNE, BridgePillarFlag::EdgeSW}
998 : BridgePillarFlags{BridgePillarFlag::EdgeNW, BridgePillarFlag::EdgeSE});
999 break;
1000
1002 DrawWaterDepot(ti);
1003 break;
1004 }
1005}
1006
1007void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
1008{
1009 const DrawTileSprites &dts = _shipdepot_display_data[axis][to_underlying(part)];
1010
1011 DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
1013}
1014
1015
1017static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y, [[maybe_unused]] bool ground_vehicle)
1018{
1019 auto [tileh, z] = GetTilePixelSlope(tile);
1020
1021 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1022}
1023
1026{
1027 switch (GetWaterTileType(tile)) {
1029 switch (GetWaterClass(tile)) {
1030 case WaterClass::Sea: td.str = STR_LAI_WATER_DESCRIPTION_WATER; break;
1031 case WaterClass::Canal: td.str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
1032 case WaterClass::River: td.str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
1033 default: NOT_REACHED();
1034 }
1035 break;
1036 case WaterTileType::Coast: td.str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
1037 case WaterTileType::Lock : td.str = STR_LAI_WATER_DESCRIPTION_LOCK; break;
1039 td.str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
1040 td.build_date = Depot::GetByTile(tile)->build_date;
1041 break;
1042 default: NOT_REACHED();
1043 }
1044
1045 td.owner[0] = GetTileOwner(tile);
1046}
1047
1053static void FloodVehicle(Vehicle *v)
1054{
1055 uint victims = v->Crash(true);
1056
1057 AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims, v->owner));
1058 Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims, v->owner));
1059 AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_FLOOD_VEHICLE, victims), NewsType::Accident, v->tile);
1061 if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1062}
1063
1069static void FloodVehicleProc(Vehicle *v, int z)
1070{
1071 if (v->vehstatus.Test(VehState::Crashed)) return;
1072
1073 switch (v->type) {
1074 default: break;
1075
1076 case VEH_AIRCRAFT: {
1077 if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
1078 if (v->subtype == AIR_SHADOW) break;
1079
1080 /* We compare v->z_pos against delta_z + 1 because the shadow
1081 * is at delta_z and the actual aircraft at delta_z + 1. */
1082 const Station *st = Station::GetByTile(v->tile);
1083 const AirportFTAClass *airport = st->airport.GetFTA();
1084 if (v->z_pos != airport->delta_z + 1) break;
1085
1086 FloodVehicle(v);
1087 break;
1088 }
1089
1090 case VEH_TRAIN:
1091 case VEH_ROAD: {
1092 if (v->z_pos > z) break;
1093 FloodVehicle(v->First());
1094 break;
1095 }
1096 }
1097}
1098
1099static void FloodVehiclesOnTile(TileIndex tile, int z)
1100{
1101 for (Vehicle *v : VehiclesOnTile(tile)) {
1102 FloodVehicleProc(v, z);
1103 }
1104}
1105
1111static void FloodVehicles(TileIndex tile)
1112{
1113 if (IsAirportTile(tile)) {
1114 const Station *st = Station::GetByTile(tile);
1115 for (TileIndex airport_tile : st->airport) {
1116 if (st->TileBelongsToAirport(airport_tile)) FloodVehiclesOnTile(airport_tile, 0);
1117 }
1118
1119 /* No vehicle could be flooded on this airport anymore */
1120 return;
1121 }
1122
1123 if (!IsBridgeTile(tile)) {
1124 FloodVehiclesOnTile(tile, 0);
1125 return;
1126 }
1127
1128 TileIndex end = GetOtherBridgeEnd(tile);
1129 int z = GetBridgePixelHeight(tile);
1130
1131 FloodVehiclesOnTile(tile, z);
1132 FloodVehiclesOnTile(end, z);
1133}
1134
1141{
1142 /* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs
1143 * FLOOD_DRYUP: coast with more than one corner raised, coast with rail-track, coast with trees
1144 * FLOOD_PASSIVE: (not used)
1145 * FLOOD_NONE: canals, rivers, everything else
1146 */
1147 switch (GetTileType(tile)) {
1148 case TileType::Water:
1149 if (IsCoast(tile)) {
1150 Slope tileh = GetTileSlope(tile);
1152 }
1153 [[fallthrough]];
1154 case TileType::Station:
1155 case TileType::Industry:
1156 case TileType::Object:
1158
1159 case TileType::Railway:
1162 }
1163 return FLOOD_NONE;
1164
1165 case TileType::Trees:
1167
1168 case TileType::Void:
1169 return FLOOD_ACTIVE;
1170
1171 default:
1172 return FLOOD_NONE;
1173 }
1174}
1175
1180static void DoFloodTile(TileIndex target)
1181{
1182 assert(!IsTileType(target, TileType::Water));
1183
1184 bool flooded = false; // Will be set to true if something is changed.
1185
1187
1188 Slope tileh = GetTileSlope(target);
1189 if (tileh != SLOPE_FLAT) {
1190 /* make coast.. */
1191 switch (GetTileType(target)) {
1192 case TileType::Railway: {
1193 if (!IsPlainRail(target)) break;
1194 FloodVehicles(target);
1195 flooded = FloodHalftile(target);
1196 break;
1197 }
1198
1199 case TileType::Trees:
1200 if (!IsSlopeWithOneCornerRaised(tileh)) {
1202 MarkTileDirtyByTile(target);
1203 flooded = true;
1204 break;
1205 }
1206 [[fallthrough]];
1207
1208 case TileType::Clear:
1209 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, target).Succeeded()) {
1210 MakeShore(target);
1211 MarkTileDirtyByTile(target);
1212 flooded = true;
1213 }
1214 break;
1215
1216 default:
1217 break;
1218 }
1219 } else {
1220 /* Flood vehicles */
1221 FloodVehicles(target);
1222
1223 /* flood flat tile */
1224 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, target).Succeeded()) {
1225 MakeSea(target);
1226 MarkTileDirtyByTile(target);
1227 flooded = true;
1228 }
1229 }
1230
1231 if (flooded) {
1232 /* Mark surrounding canal tiles dirty too to avoid glitches */
1234
1235 /* update signals if needed */
1237
1238 if (IsPossibleDockingTile(target)) CheckForDockingTile(target);
1239 InvalidateWaterRegion(target);
1240 }
1241
1242 cur_company.Restore();
1243}
1244
1249static void DoDryUp(TileIndex tile)
1250{
1252
1253 switch (GetTileType(tile)) {
1254 case TileType::Railway:
1255 assert(IsPlainRail(tile));
1257
1258 RailGroundType new_ground;
1259 switch (GetTrackBits(tile)) {
1260 case TRACK_BIT_UPPER: new_ground = RailGroundType::FenceHoriz1; break;
1261 case TRACK_BIT_LOWER: new_ground = RailGroundType::FenceHoriz2; break;
1262 case TRACK_BIT_LEFT: new_ground = RailGroundType::FenceVert1; break;
1263 case TRACK_BIT_RIGHT: new_ground = RailGroundType::FenceVert2; break;
1264 default: NOT_REACHED();
1265 }
1266 SetRailGroundType(tile, new_ground);
1267 MarkTileDirtyByTile(tile);
1268 break;
1269
1270 case TileType::Trees:
1272 MarkTileDirtyByTile(tile);
1273 break;
1274
1275 case TileType::Water:
1276 assert(IsCoast(tile));
1277
1278 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, tile).Succeeded()) {
1279 MakeClear(tile, ClearGround::Grass, 3);
1280 MarkTileDirtyByTile(tile);
1281 }
1282 break;
1283
1284 default: NOT_REACHED();
1285 }
1286
1287 cur_company.Restore();
1288}
1289
1297{
1298 if (IsTileType(tile, TileType::Water)) {
1299 AmbientSoundEffect(tile);
1300 if (IsNonFloodingWaterTile(tile)) return;
1301 }
1302
1303 switch (GetFloodingBehaviour(tile)) {
1304 case FLOOD_ACTIVE: {
1305 bool continue_flooding = false;
1306 for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
1308 /* Contrary to drying up, flooding does not consider TileType::Void tiles. */
1309 if (!IsValidTile(dest)) continue;
1310 /* do not try to flood water tiles - increases performance a lot */
1311 if (IsTileType(dest, TileType::Water)) continue;
1312
1313 /* Buoys and docks cannot be flooded, and when removed turn into flooding water. */
1314 if (IsTileType(dest, TileType::Station) && (IsBuoy(dest) || IsDock(dest))) continue;
1315
1316 /* This neighbour tile might be floodable later if the tile is cleared, so allow flooding to continue. */
1317 continue_flooding = true;
1318
1319 /* TreeGround::Shore is the sign of a previous flood. */
1320 if (IsTileType(dest, TileType::Trees) && GetTreeGround(dest) == TreeGround::Shore) continue;
1321
1322 auto [slope_dest, z_dest] = GetFoundationSlope(dest);
1323 if (z_dest > 0) continue;
1324
1325 if (!_flood_from_dirs[slope_dest & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP].Test(ReverseDir(dir))) continue;
1326
1327 DoFloodTile(dest);
1328 }
1329 if (!continue_flooding && IsTileType(tile, TileType::Water)) SetNonFloodingWaterTile(tile, true);
1330 break;
1331 }
1332
1333 case FLOOD_DRYUP: {
1334 Slope slope_here = std::get<0>(GetFoundationSlope(tile)) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
1335 for (Direction dir : _flood_from_dirs[slope_here]) {
1337 /* Contrary to flooding, drying up does consider TileType::Void tiles. */
1338 if (dest == INVALID_TILE) continue;
1339
1340 FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
1341 if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
1342 }
1343 DoDryUp(tile);
1344 break;
1345 }
1346
1347 default: return;
1348 }
1349}
1350
1351void ConvertGroundTilesIntoWaterTiles()
1352{
1353 for (const auto tile : Map::Iterate()) {
1354 auto [slope, z] = GetTileSlopeZ(tile);
1355 if (IsTileType(tile, TileType::Clear) && z == 0) {
1356 /* Make both water for tiles at level 0
1357 * and make shore, as that looks much better
1358 * during the generation. */
1359 switch (slope) {
1360 case SLOPE_FLAT:
1361 MakeSea(tile);
1362 break;
1363
1364 case SLOPE_N:
1365 case SLOPE_E:
1366 case SLOPE_S:
1367 case SLOPE_W:
1368 MakeShore(tile);
1369 break;
1370
1371 default:
1372 for (Direction dir : _flood_from_dirs[slope & ~SLOPE_STEEP]) {
1373 TileIndex dest = TileAddByDir(tile, dir);
1374 Slope slope_dest = GetTileSlope(dest) & ~SLOPE_STEEP;
1375 if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest) || IsTileType(dest, TileType::Void)) {
1376 MakeShore(tile);
1377 break;
1378 }
1379 }
1380 break;
1381 }
1382 }
1383 }
1384}
1385
1387static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, [[maybe_unused]] uint sub_mode, [[maybe_unused]] DiagDirection side)
1388{
1391
1392 TrackBits ts;
1393
1394 if (mode != TRANSPORT_WATER) return 0;
1395
1396 switch (GetWaterTileType(tile)) {
1397 case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
1398 case WaterTileType::Coast: ts = coast_tracks[GetTileSlope(tile) & 0xF]; break;
1400 case WaterTileType::Depot: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
1401 default: return 0;
1402 }
1403 if (TileX(tile) == 0) {
1404 /* NE border: remove tracks that connects NE tile edge */
1406 }
1407 if (TileY(tile) == 0) {
1408 /* NW border: remove tracks that connects NW tile edge */
1410 }
1412}
1413
1416{
1419 return true;
1420 }
1421 return false;
1422}
1423
1425static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
1426{
1427 if (!IsTileOwner(tile, old_owner)) return;
1428
1429 bool is_lock_middle = IsLock(tile) && GetLockPart(tile) == LockPart::Middle;
1430
1431 /* No need to dirty company windows here, we'll redraw the whole screen anyway. */
1432 if (is_lock_middle) Company::Get(old_owner)->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1433 if (new_owner != INVALID_OWNER) {
1434 if (is_lock_middle) Company::Get(new_owner)->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1435 /* Only subtract from the old owner here if the new owner is valid,
1436 * otherwise we clear ship depots and canal water below. */
1437 if (GetWaterClass(tile) == WaterClass::Canal && !is_lock_middle) {
1438 Company::Get(old_owner)->infrastructure.water--;
1439 Company::Get(new_owner)->infrastructure.water++;
1440 }
1441 if (IsShipDepot(tile)) {
1442 Company::Get(old_owner)->infrastructure.water -= LOCK_DEPOT_TILE_FACTOR;
1443 Company::Get(new_owner)->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
1444 }
1445
1446 SetTileOwner(tile, new_owner);
1447 return;
1448 }
1449
1450 /* Remove depot */
1451 if (IsShipDepot(tile)) Command<Commands::LandscapeClear>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile);
1452
1453 /* Set owner of canals and locks ... and also canal under dock there was before.
1454 * Check if the new owner after removing depot isn't OWNER_WATER. */
1455 if (IsTileOwner(tile, old_owner)) {
1456 if (GetWaterClass(tile) == WaterClass::Canal && !is_lock_middle) Company::Get(old_owner)->infrastructure.water--;
1457 SetTileOwner(tile, OWNER_NONE);
1458 }
1459}
1460
1462static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] int z_new, [[maybe_unused]] Slope tileh_new)
1463{
1464 /* Canals can't be terraformed */
1465 if (IsWaterTile(tile) && IsCanal(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
1466
1467 /* Rivers can't be terraformed */
1468 if (IsWaterTile(tile) && IsRiver(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_RIVER_FIRST);
1469
1470 return Command<Commands::LandscapeClear>::Do(flags, tile);
1471}
1472
1474static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] Axis axis, int height)
1475{
1476 if (IsWater(tile) || IsCoast(tile)) return CommandCost();
1477 if (IsLock(tile)) {
1478 if (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) <= height) return CommandCost();
1479 int height_diff = (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) - height) * TILE_HEIGHT_STEP;
1480 return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff);
1481 }
1482 return Command<Commands::LandscapeClear>::Do(flags, tile);
1483}
1484
1487 .draw_tile_proc = DrawTile_Water,
1488 .get_slope_pixel_z_proc = GetSlopePixelZ_Water,
1489 .clear_tile_proc = ClearTile_Water,
1490 .get_tile_desc_proc = GetTileDesc_Water,
1491 .get_tile_track_status_proc = GetTileTrackStatus_Water,
1492 .click_tile_proc = ClickTile_Water,
1493 .tile_loop_proc = TileLoop_Water,
1494 .change_tile_owner_proc = ChangeTileOwner_Water,
1495 .vehicle_enter_tile_proc = [](Vehicle *, TileIndex, int, int) -> VehicleEnterTileStates { return {}; },
1496 .terraform_tile_proc = TerraformTile_Water,
1497 .check_build_above_proc = CheckBuildAbove_Water,
1498};
Base functions for all AIs.
Base for aircraft.
@ AIR_SHADOW
shadow of the aircraft
Definition aircraft.h:31
Class for backupping variables and making sure they are restored later.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars)
Draw the middle bits of a bridge.
TileIndex GetSouthernBridgeEnd(TileIndex t)
Finds the southern end of a bridge starting at a middle tile.
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
int GetBridgeHeight(TileIndex t)
Get the height ('z') of a bridge.
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition bridge_map.h:35
int GetBridgePixelHeight(TileIndex tile)
Get the height ('z') of a bridge in pixels.
Definition bridge_map.h:84
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:235
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
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 void NewEvent(class ScriptEvent *event)
Queue a new event for the game script.
Generate TileIndices around a center tile or tile area, with increasing distance.
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
Wrapper class to abstract away the way the tiles are stored.
Definition map_func.h:25
Iterate over all vehicles on a tile.
Map accessors for 'clear' tiles.
@ Grass
Plain grass with dirt transition (0-3).
Definition clear_map.h:22
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition clear_map.h:253
CommandCost CommandCostWithParam(StringID str, uint64_t value)
Return an error status, with string and parameter.
Definition command.cpp:416
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Auto
don't allow building on structures
@ NoWater
don't allow building on water
@ Execute
execute the given command
@ Bankrupt
company bankrupts, skip money check, skip vehicle on tile check in some cases
@ ForceClearTile
do not only remove the object on the tile, but also clear any water left on it
Definition of stuff that is very close to a company, like the company struct itself.
CommandCost CheckTileOwnership(TileIndex tile)
Check whether the current owner owns the stuff on the given tile.
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
static constexpr Owner OWNER_NONE
The tile has no ownership.
static constexpr Owner INVALID_OWNER
An invalid owner.
static constexpr Owner OWNER_WATER
The tile/execution is done by "water".
Base for all depots (except hangars).
Functions related to depots.
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
bool IsValidAxis(Axis d)
Checks if an integer value is a valid Axis.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
Direction ReverseDir(Direction d)
Return the reverse of a direction.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Direction
Defines the 8 directions on the map.
@ DIR_BEGIN
Used to iterate.
@ DIR_SW
Southwest.
@ DIR_NW
Northwest.
@ DIR_N
North.
@ DIR_SE
Southeast.
@ DIR_S
South.
@ DIR_NE
Northeast.
@ DIR_END
Used to iterate.
@ DIR_W
West.
@ DIR_E
East.
EnumBitSet< Direction, uint8_t > Directions
Allow incrementing of Direction variables.
Axis
Allow incrementing of DiagDirDiff variables.
@ AXIS_X
The X axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:106
static const uint LOCK_DEPOT_TILE_FACTOR
Multiplier for how many regular tiles a lock counts.
@ EXPENSES_CONSTRUCTION
Construction costs.
@ ClearCanal
Price for destroying canals.
@ ClearRough
Price for destroying rough land.
@ BuildDepotShip
Price for building ship depots.
@ BuildCanal
Price for building new canals.
@ ClearWater
Price for destroying water e.g. see, rives.
@ ClearDepotShip
Price for destroying ship depots.
@ ClearLock
Price for destroying locks.
@ BuildLock
Price for building new locks.
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
Functions related to effect vehicles.
@ EV_EXPLOSION_LARGE
Various explosions.
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
Base functions for all Games.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1038
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
static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
Marks the tiles around a tile as dirty, if they are canals or rivers.
Definition water_cmd.cpp:87
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Base of all industries.
Accessors to map for industries.
IndustryID GetIndustryIndex(Tile t)
Get the industry ID of the given tile.
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
std::tuple< Slope, int > GetFoundationSlope(TileIndex tile)
Get slope of a tile on top of a (possible) foundation If a tile does not have a foundation,...
const TileTypeProcs _tile_type_water_procs
TileTypeProcs definitions for TileType::Water tiles.
Definition landscape.cpp:58
Functions related to OTTD's landscape.
Command definitions related to landscape (slopes etc.).
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition map_func.h:474
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition map_func.h:519
TileIndex TileAddByDir(TileIndex tile, Direction dir)
Adds a Direction to a tile.
Definition map_func.h:603
TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
Return the offset between two tiles from a TileIndexDiffC struct.
Definition map_func.h:444
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:615
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition map_func.h:559
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
TileIndexDiffC TileIndexDiffCByDir(Direction dir)
Returns the TileIndexDiffC offset from a Direction.
Definition map_func.h:501
TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition map_func.h:588
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:574
int32_t TileIndexDiff
An offset value between two tiles.
Definition map_type.h:23
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
CanalFeature
List of different canal 'features'.
Definition newgrf.h:27
uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
Get the new sprite offset for a water tile.
std::array< WaterFeature, CF_END > _water_feature
Table of canal 'feature' sprite groups.
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
Lookup the base sprite to use for a canal.
Handling of NewGRF canals.
@ CFF_HAS_FLAT_SPRITE
Additional flat ground sprite in the beginning.
Functions related to generic callbacks.
void AmbientSoundEffect(TileIndex tile)
Play an ambient sound effect for an empty tile.
Functions related to news.
@ Accident
An accident or disaster has occurred.
Definition news_type.h:32
bool FloodHalftile(TileIndex t)
Called from water_cmd if a non-flat rail-tile gets flooded and should be converted to shore.
Definition rail_cmd.cpp:761
static bool IsPlainRail(Tile t)
Returns whether this is plain rails, with or without signals.
Definition rail_map.h:49
RailGroundType GetRailGroundType(Tile t)
Get the ground type for rail tiles.
Definition rail_map.h:591
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition rail_map.h:136
RailGroundType
The ground 'under' the rail.
Definition rail_map.h:558
@ FenceVert2
Grass with a fence at the western side.
Definition rail_map.h:568
@ FenceHoriz2
Grass with a fence at the northern side.
Definition rail_map.h:570
@ HalfTileWater
Grass with a fence and shore or water on the free halftile.
Definition rail_map.h:572
@ FenceVert1
Grass with a fence at the eastern side.
Definition rail_map.h:567
@ FenceHoriz1
Grass with a fence at the southern side.
Definition rail_map.h:569
void SetRailGroundType(Tile t, RailGroundType rgt)
Set the ground type for rail tiles.
Definition rail_map.h:581
Pseudo random number generator.
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
void UpdateSignalsInBuffer()
Update signals in buffer Called from 'outside'.
Definition signal.cpp:580
bool IsSlopeWithOneCornerRaised(Slope s)
Tests if a specific slope has exactly one corner raised.
Definition slope_func.h:88
bool IsInclinedSlope(Slope s)
Tests if a specific slope is an inclined slope.
Definition slope_func.h:228
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:47
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:239
Slope
Enumeration for the slope-type.
Definition slope_type.h:47
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:49
@ SLOPE_HALFTILE_MASK
three bits used for halftile slopes
Definition slope_type.h:71
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:59
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:51
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:50
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:52
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:55
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:48
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:57
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:56
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:54
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:58
@ SLOPE_STEEP
indicates the slope is steep
Definition slope_type.h:53
Functions related to sound.
@ SND_12_EXPLOSION
16 == 0x10 Destruction, crashes, disasters, ...
Definition sound_type.h:64
void DrawOrigTileSeqInGUI(int x, int y, const DrawTileSprites *dts, PaletteID default_palette)
Draw TTD sprite sequence in GUI.
Definition sprite.h:146
static const SpriteID SPR_SHORE_BASE
shore tiles - action 05-0D
Definition sprites.h:226
Base classes/functions for stations.
bool IsAirportTile(Tile t)
Is this tile a station tile and an airport tile?
bool IsBuoy(Tile t)
Is tile t a buoy tile?
bool IsDockTile(Tile t)
Is tile t a dock tile?
bool IsOilRig(Tile t)
Is tile t part of an oilrig?
bool IsDockWaterPart(Tile t)
Check whether a dock tile is the tile on water.
bool IsDock(Tile t)
Is tile t a dock tile?
Definition of base types and functions in a cross-platform compatible way.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
Functions related to OTTD's strings.
Finite sTate mAchine (FTA) of an airport.
Definition airport.h:158
uint8_t delta_z
Z adjustment for helicopter pads.
Definition airport.h:196
const AirportFTAClass * GetFTA() const
Get the finite-state machine for this airport or the finite-state machine for the dummy airport in ca...
Class to backup a specific variable and restore it later.
void Restore()
Restore the variable.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
VehicleType type
Type of vehicle.
uint32_t water
Count of company owned track bits for canals.
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
T z
Z coordinate.
A tile child sprite and palette to draw for stations etc, with 3D bounding box.
Definition sprite.h:33
Ground palette sprite of a tile, together with its sprite layout.
Definition sprite.h:55
PalSpriteID ground
Palette and sprite for the ground.
Definition sprite.h:56
virtual std::span< const DrawTileSeqStruct > GetSequence() const =0
The child sprites to draw.
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition industry.h:251
Station * neutral_station
Associated neutral station.
Definition industry.h:108
static IterateWrapper Iterate()
Returns an iterable ensemble of all Tiles.
Definition map_func.h:366
static uint MaxY()
Gets the maximum Y coordinate within the map, including TileType::Void.
Definition map_func.h:298
static uint MaxX()
Gets the maximum X coordinate within the map, including TileType::Void.
Definition map_func.h:289
static uint Size()
Get the size of the map.
Definition map_func.h:280
void Add(TileIndex to_add)
Add a single tile to a tile area; enlarge if needed.
Definition tilearea.cpp:43
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 * Get(auto index)
static bool CanAllocateItem(size_t n=1)
static T * Create(Targs &&... args)
static Company * GetIfValid(auto index)
Station data structure.
TileArea docking_station
Tile area the docking tiles cover.
Airport airport
Tile area the airport covers.
Tile description for the 'land area information' tool.
Definition tile_cmd.h:38
StringID str
Description of the tile.
Definition tile_cmd.h:39
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:43
std::array< Owner, 4 > owner
Name of the owner(s).
Definition tile_cmd.h:41
A pair-construct of a TileIndexDiff.
Definition map_type.h:31
Tile information, used while rendering the tile.
Definition tile_cmd.h:32
Slope tileh
Slope of the tile.
Definition tile_cmd.h:33
TileIndex tile
Tile index.
Definition tile_cmd.h:34
Set of callback functions for performing tile operations of a given tile type.
Definition tile_cmd.h:212
Town data structure.
Definition town.h:63
Vehicle data structure.
int32_t z_pos
z coordinate.
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition vehicle.cpp:300
uint8_t subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
VehStates vehstatus
Status.
Vehicle * First() const
Get the first vehicle of this vehicle chain.
TileIndex tile
Current tile index.
Owner owner
Which company owns the vehicle?
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition tile_map.cpp:94
std::tuple< Slope, int > GetTileSlopeZ(TileIndex tile)
Return the slope of a given tile inside the map.
Definition tile_map.cpp:55
int GetTileMaxZ(TileIndex t)
Get top height of the tile inside the map.
Definition tile_map.cpp:135
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition tile_map.h:214
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
void SetTileOwner(Tile tile, Owner owner)
Sets the owner of a tile.
Definition tile_map.h:198
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition tile_map.h:289
bool IsValidTile(Tile tile)
Checks if a tile is valid.
Definition tile_map.h:161
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
@ TROPICZONE_DESERT
Tile is desert.
Definition tile_type.h:83
@ TROPICZONE_NORMAL
Normal tropiczone.
Definition tile_type.h:82
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
@ TunnelBridge
Tunnel entry/exit and bridge heads.
Definition tile_type.h:58
@ Water
Water tile.
Definition tile_type.h:55
@ Station
A tile of a station or airport.
Definition tile_type.h:54
@ Object
Contains objects such as transmitters and owned land.
Definition tile_type.h:59
@ Industry
Part of an industry.
Definition tile_type.h:57
@ Railway
A tile with railway.
Definition tile_type.h:50
@ 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
Definition of the game-calendar-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.
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition town.h:287
Types related to towns.
static constexpr int RATING_WATER_MINIMUM
minimum rating after removing water features near town
Definition town_type.h:81
static constexpr int RATING_WATER_RIVER_DOWN_STEP
removing a river tile
Definition town_type.h:80
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:319
TrackStatus CombineTrackStatus(TrackdirBits trackdirbits, TrackdirBits red_signals)
Builds a TrackStatus.
Definition track_func.h:390
TrackBits AxisToTrackBits(Axis a)
Maps an Axis to the corresponding TrackBits value.
Definition track_func.h:88
TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal track bits incidating with that diagdir.
Definition track_func.h:529
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition track_func.h:365
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
@ TRACK_BIT_UPPER
Upper track.
Definition track_type.h:39
@ TRACK_BIT_LEFT
Left track.
Definition track_type.h:41
@ TRACK_BIT_Y
Y-axis track.
Definition track_type.h:38
@ TRACK_BIT_NONE
No track.
Definition track_type.h:36
@ TRACK_BIT_X
X-axis track.
Definition track_type.h:37
@ TRACK_BIT_LOWER
Lower track.
Definition track_type.h:40
@ TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:50
@ TRACK_BIT_RIGHT
Right track.
Definition track_type.h:42
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
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_BUILDINGS
company buildings - depots, stations, HQ, ...
TransportType
Available types of transport.
@ TRANSPORT_WATER
Transport over water.
Map accessors for tree tiles.
TreeGround GetTreeGround(Tile t)
Returns the groundtype for tree tiles.
Definition tree_map.h:102
@ Shore
Shore.
Definition tree_map.h:56
@ Grass
Normal grass.
Definition tree_map.h:53
void SetTreeGroundDensity(Tile t, TreeGround g, uint d)
Set the density and ground type of a tile with trees.
Definition tree_map.h:145
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:556
@ Crashed
Vehicle is crashed.
Functions related to vehicles.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
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:658
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.
static const int TILE_HEIGHT_STEP
One Z unit tile height difference is displayed as 50m.
Functions related to water management.
void TileLoop_Water(TileIndex tile)
Tile callback function signature for running periodic tile updates.
FloodingBehaviour
Describes the behaviour of a tile during flooding.
Definition water.h:19
@ FLOOD_NONE
The tile does not flood neighboured tiles.
Definition water.h:20
@ FLOOD_ACTIVE
The tile floods neighboured tiles.
Definition water.h:21
@ FLOOD_DRYUP
The tile drys up if it is not constantly flooded from neighboured tiles.
Definition water.h:23
@ FLOOD_PASSIVE
The tile does not actively flood neighboured tiles, but it prevents them from drying up.
Definition water.h:22
static const uint RIVER_OFFSET_DESERT_DISTANCE
Circular tile search diameter to create non-desert around a river tile.
Definition water.h:44
static uint8_t GetLockPartMinimalBridgeHeight(LockPart lock_part)
Get the minimal height required for a bridge above a lock part.
void TileLoop_Water(TileIndex tile)
Tile callback function signature for running periodic tile updates.
static void DrawWaterDepot(const TileInfo *ti)
Draw a ship depot tile.
static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
Draw a water sprite, potentially with a NewGRF-modified sprite offset.
static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new)
Tile callback function signature of the terraforming callback.
static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlags flags)
Builds a lock.
CommandCost CmdBuildLock(DoCommandFlags flags, TileIndex tile)
Builds a lock.
static CommandCost RemoveLock(TileIndex tile, DoCommandFlags flags)
Remove a lock.
static void DrawWaterLock(const TileInfo *ti)
Draw a lock tile.
static void FloodVehicle(Vehicle *v)
Handle the flooding of a vehicle.
static void FloodVehicles(TileIndex tile)
Finds a vehicle to flood.
static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
Draw canal or river edges.
static void GetTileDesc_Water(TileIndex tile, TileDesc &td)
Tile callback function signature for obtaining a tile description.
static void FloodVehicleProc(Vehicle *v, int z)
Flood a vehicle if we are allowed to flood it, i.e.
static const Directions _flood_from_dirs[]
Describes from which directions a specific slope can be flooded (if the tile is floodable at all).
Definition water_cmd.cpp:52
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:98
static int GetSlopePixelZ_Water(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.
static void DrawWaterTileStruct(const TileInfo *ti, std::span< const DrawTileSeqStruct > seq, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
Draw a build sprite sequence for water tiles.
static void DoDryUp(TileIndex tile)
Drys a tile up.
static void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
Marks tile dirty if it is a canal or river tile.
Definition water_cmd.cpp:76
FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
Returns the behaviour of a tile during flooding.
bool IsPossibleDockingTile(Tile t)
Check whether it is feasible that the given tile could be a docking tile.
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
static void DrawSeaWater(TileIndex)
Draw a plain sea water tile with no edges.
CommandCost CmdBuildShipDepot(DoCommandFlags flags, TileIndex tile, Axis axis)
Build a ship depot.
static void DrawCanalWater(TileIndex tile)
Draw a canal styled water tile with dikes around.
static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlags flags)
Tile callback function signature for clearing a tile.
static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, Axis axis, int height)
Tile callback function signature to test if a bridge can be built above a tile.
static bool ClickTile_Water(TileIndex tile)
Tile callback function signature for clicking a tile.
void MakeRiverAndModifyDesertZoneAround(TileIndex tile)
Make a river tile and remove desert directly around it.
static void DoFloodTile(TileIndex target)
Floods a tile.
bool IsWateredTile(TileIndex tile, Direction from)
return true if a tile is a water tile wrt.
static void DrawTile_Water(TileInfo *ti)
Tile callback function signature for drawing a tile and its contents to the screen.
CommandCost CmdBuildCanal(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
Build a piece of canal.
static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Tile callback function signature for getting the possible tracks that can be taken on a given tile by...
static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
Tile callback function signature for changing the owner of a tile.
Command definitions related to water tiles.
Sprites to use and how to display them for water tiles (depots/locks).
void MakeShore(Tile t)
Helper function to make a coast tile.
Definition water_map.h:385
bool HasTileWaterGround(Tile t)
Checks whether the tile has water at the ground.
Definition water_map.h:353
TileIndex GetShipDepotNorthTile(Tile t)
Get the most northern tile of a ship depot.
Definition water_map.h:291
void MakeLock(Tile t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper, WaterClass wc_middle)
Make a water lock.
Definition water_map.h:514
DepotPart GetShipDepotPart(Tile t)
Get the part of a ship depot.
Definition water_map.h:257
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:138
bool IsShipDepot(Tile t)
Is it a water tile with a ship depot on it?
Definition water_map.h:224
bool IsValidWaterClass(WaterClass wc)
Checks if a water class is valid.
Definition water_map.h:52
bool IsRiver(Tile t)
Is it a river water tile?
Definition water_map.h:182
DiagDirection GetLockDirection(Tile t)
Get the direction of the water lock.
Definition water_map.h:316
WaterClass
classes of water (for WaterTileType::Clear water tile type).
Definition water_map.h:39
@ River
River.
Definition water_map.h:42
@ Invalid
Used for industry tiles on land (also for oilrig if newgrf says so).
Definition water_map.h:43
@ Canal
Canal.
Definition water_map.h:41
@ Sea
Sea.
Definition water_map.h:40
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:103
bool IsCanal(Tile t)
Is it a canal tile?
Definition water_map.h:171
bool IsCoast(Tile t)
Is it a coast tile?
Definition water_map.h:203
void MakeRiver(Tile t, uint8_t random_bits)
Make a river tile.
Definition water_map.h:438
WaterTileType GetWaterTileType(Tile t)
Get the water tile type of a tile.
Definition water_map.h:80
void SetNonFloodingWaterTile(Tile t, bool b)
Set the non-flooding water tile state of a tile.
Definition water_map.h:532
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:114
void MakeCanal(Tile t, Owner o, uint8_t random_bits)
Make a canal tile.
Definition water_map.h:449
TileIndex GetOtherShipDepotTile(Tile t)
Get the other tile of the ship depot.
Definition water_map.h:280
DepotPart
Sections of the water depot.
Definition water_map.h:58
@ South
Southern part of a depot.
Definition water_map.h:60
@ North
Northern part of a depot.
Definition water_map.h:59
@ Coast
Coast.
Definition water_map.h:33
@ Depot
Water Depot.
Definition water_map.h:35
@ Lock
Water lock.
Definition water_map.h:34
@ Clear
Plain water.
Definition water_map.h:32
bool IsNonFloodingWaterTile(Tile t)
Checks whether the tile is marked as a non-flooding water tile.
Definition water_map.h:542
void SetDockingTile(Tile t, bool b)
Set the docking tile state of a tile.
Definition water_map.h:364
LockPart
Sections of the water lock.
Definition water_map.h:65
@ Upper
Upper part of a lock.
Definition water_map.h:68
@ End
End marker.
Definition water_map.h:69
@ Middle
Middle part of a lock.
Definition water_map.h:66
bool IsWater(Tile t)
Is it a plain water tile?
Definition water_map.h:149
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:192
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition water_map.h:305
void MakeShipDepot(Tile t, Owner o, DepotID did, DepotPart part, Axis a, WaterClass original_water_class)
Make a ship depot section.
Definition water_map.h:464
void MakeSea(Tile t)
Make a sea tile.
Definition water_map.h:428
LockPart GetLockPart(Tile t)
Get the part of a lock.
Definition water_map.h:328
Axis GetShipDepotAxis(Tile t)
Get the axis of the ship depot.
Definition water_map.h:245
void InvalidateWaterRegion(TileIndex tile)
Marks the water region that tile is part of as invalid.
Handles dividing the water in the map into regions to assist pathfinding.