OpenTTD Source 20260911-master-gee2b2ac12a
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#include "script/api/script_event_types.hpp"
45
46#include "table/strings.h"
47
48#include "safeguards.h"
49
55 {Direction::NE, Direction::SE}, // SLOPE_W
56 {Direction::NW, Direction::NE}, // SLOPE_S
57 {Direction::NE}, // SLOPE_SW
58 {Direction::NW, Direction::SW}, // SLOPE_E
59 {}, // SLOPE_EW
60 {Direction::NW}, // SLOPE_SE
61 {Direction::N, Direction::NW, Direction::NE}, // SLOPE_WSE, SLOPE_STEEP_S
62 {Direction::SW, Direction::SE}, // SLOPE_N
63 {Direction::SE}, // SLOPE_NW
64 {}, // SLOPE_NS
65 {Direction::E, Direction::NE, Direction::SE}, // SLOPE_NWS, SLOPE_STEEP_W
66 {Direction::SW}, // SLOPE_NE
67 {Direction::S, Direction::SW, Direction::SE}, // SLOPE_ENW, SLOPE_STEEP_N
68 {Direction::W, Direction::SW, Direction::NW}, // SLOPE_SEN, SLOPE_STEEP_E
69}}};
70
77static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
78{
79 if (IsValidTile(tile) && IsTileType(tile, TileType::Water) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
80}
81
94
100{
101 for (Direction dir : EnumRange(Direction::End)) {
102 TileIndex dest = tile + TileOffsByDir(dir);
103 if (IsValidTile(dest) && IsTileType(dest, TileType::Water)) SetNonFloodingWaterTile(dest, false);
104 }
105}
106
115{
116 if (!IsValidAxis(axis)) return CMD_ERROR;
117 TileIndex tile2 = tile + TileOffsByAxis(axis);
118
119 if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
120 return CommandCost(STR_ERROR_MUST_BE_BUILT_ON_WATER);
121 }
122
123 for (Tile t : {tile, tile2}) {
124 if (IsBridgeAbove(t)) {
126 if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_SHIP_DEPOT, height_diff * TILE_HEIGHT_STEP);
127 }
128 }
129
130 if (!IsTileFlat(tile) || !IsTileFlat(tile2)) {
131 /* Prevent depots on rapids */
132 return CommandCost(STR_ERROR_SITE_UNSUITABLE);
133 }
134
135 if (!Depot::CanAllocateItem()) return CMD_ERROR;
136
137 WaterClass wc1 = GetWaterClass(tile);
138 WaterClass wc2 = GetWaterClass(tile2);
140
141 bool add_cost = !IsWaterTile(tile);
142 CommandCost ret = Command<Commands::LandscapeClear>::Do(flags | DoCommandFlag::Auto, tile);
143 if (ret.Failed()) return ret;
144 if (add_cost) {
145 cost.AddCost(ret.GetCost());
146 }
147 add_cost = !IsWaterTile(tile2);
148 ret = Command<Commands::LandscapeClear>::Do(flags | DoCommandFlag::Auto, tile2);
149 if (ret.Failed()) return ret;
150 if (add_cost) {
151 cost.AddCost(ret.GetCost());
152 }
153
154 if (flags.Test(DoCommandFlag::Execute)) {
155 Depot *depot = Depot::Create(tile);
156
157 uint new_water_infra = 2 * LOCK_DEPOT_TILE_FACTOR;
158 /* Update infrastructure counts after the tile clears earlier.
159 * Clearing object tiles may result in water tiles which are already accounted for in the water infrastructure total.
160 * See: MakeWaterKeepingClass() */
161 if (wc1 == WaterClass::Canal && !(HasTileWaterClass(tile) && GetWaterClass(tile) == WaterClass::Canal && IsTileOwner(tile, _current_company))) new_water_infra++;
162 if (wc2 == WaterClass::Canal && !(HasTileWaterClass(tile2) && GetWaterClass(tile2) == WaterClass::Canal && IsTileOwner(tile2, _current_company))) new_water_infra++;
163
164 Company::Get(_current_company)->infrastructure.water += new_water_infra;
166
167 MakeShipDepot(tile, _current_company, depot->index, DepotPart::North, axis, wc1);
168 MakeShipDepot(tile2, _current_company, depot->index, DepotPart::South, axis, wc2);
170 CheckForDockingTile(tile2);
172 MarkTileDirtyByTile(tile2);
173 MakeDefaultName(depot);
174 }
175
176 return cost;
177}
178
186{
187 assert(IsValidTile(t));
188 switch (GetTileType(t)) {
189 case TileType::Water:
190 if (IsLock(t) && GetLockPart(t) == LockPart::Middle) return false;
191 [[fallthrough]];
196
197 default:
198 return false;
199 }
200}
201
208{
210 TileIndex tile = t + TileOffsByDiagDir(d);
211 if (!IsValidTile(tile)) continue;
212
213 if (IsDockTile(tile) && IsDockWaterPart(tile)) {
214 Station::GetByTile(tile)->docking_station.Add(t);
215 SetDockingTile(t, true);
216 }
217 if (IsTileType(tile, TileType::Industry)) {
219 if (st != nullptr) {
220 st->docking_station.Add(t);
221 SetDockingTile(t, true);
222 }
223 }
224 if (IsTileType(tile, TileType::Station) && IsOilRig(tile)) {
225 Station::GetByTile(tile)->docking_station.Add(t);
226 SetDockingTile(t, true);
227 }
228 }
229}
230
231void MakeWaterKeepingClass(TileIndex tile, Owner o)
232{
233 WaterClass wc = GetWaterClass(tile);
234
235 /* Autoslope might turn an originally canal or river tile into land */
236 auto [slope, z] = GetTileSlopeZ(tile);
237
238 if (slope != SLOPE_FLAT) {
239 if (wc == WaterClass::Canal) {
240 /* If we clear the canal, we have to remove it from the infrastructure count as well. */
242 if (c != nullptr) {
245 }
246 /* Sloped canals are locks and no natural water remains whatever the slope direction */
248 }
249
250 /* Only river water should be restored on appropriate slopes. Other water would be invalid on slopes */
253 }
254 }
255
256 if (wc == WaterClass::Sea && z > 0) {
257 /* Update company infrastructure count. */
259 if (c != nullptr) {
262 }
263
265 }
266
267 /* Zero map array and terminate animation */
268 DoClearSquare(tile);
269
270 /* Maybe change to water */
271 switch (wc) {
272 case WaterClass::Sea: MakeSea(tile); break;
273 case WaterClass::Canal: MakeCanal(tile, o, Random()); break;
274 case WaterClass::River: MakeRiver(tile, Random()); break;
275 default: break;
276 }
277
280}
281
282static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlags flags)
283{
284 if (!IsShipDepot(tile)) return CMD_ERROR;
285
287 if (ret.Failed()) return ret;
288
289 TileIndex tile2 = GetOtherShipDepotTile(tile);
290
291 /* do not check for ship on tile when company goes bankrupt */
292 if (!flags.Test(DoCommandFlag::Bankrupt)) {
293 ret = EnsureNoVehicleOnGround(tile);
294 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
295 if (ret.Failed()) return ret;
296 }
297
298 bool do_clear = flags.Test(DoCommandFlag::ForceClearTile);
299
300 if (flags.Test(DoCommandFlag::Execute)) {
301 delete Depot::GetByTile(tile);
302
304 if (c != nullptr) {
306 if (do_clear && GetWaterClass(tile) == WaterClass::Canal) c->infrastructure.water--;
308 }
309
310 if (!do_clear) MakeWaterKeepingClass(tile, GetTileOwner(tile));
311 MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
312 }
313
315}
316
323{
324 static constexpr uint8_t MINIMAL_BRIDGE_HEIGHT[to_underlying(LockPart::End)] = {
325 2, // LockPart::Middle
326 3, // LockPart::Lower
327 2, // LockPart::Upper
328 };
329 return MINIMAL_BRIDGE_HEIGHT[to_underlying(lock_part)];
330}
331
340{
342
343 TileIndexDiff delta = TileOffsByDiagDir(dir);
345 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
346 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
347 if (ret.Failed()) return ret;
348
349 /* middle tile */
351 ret = Command<Commands::LandscapeClear>::Do(flags, tile);
352 if (ret.Failed()) return ret;
353 cost.AddCost(ret.GetCost());
354
355 /* lower tile */
356 if (!IsWaterTile(tile - delta)) {
357 ret = Command<Commands::LandscapeClear>::Do(flags, tile - delta);
358 if (ret.Failed()) return ret;
359 cost.AddCost(ret.GetCost());
361 }
362 if (!IsTileFlat(tile - delta)) {
363 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
364 }
365 WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WaterClass::Canal;
366
367 /* upper tile */
368 if (!IsWaterTile(tile + delta)) {
369 ret = Command<Commands::LandscapeClear>::Do(flags, tile + delta);
370 if (ret.Failed()) return ret;
371 cost.AddCost(ret.GetCost());
373 }
374 if (!IsTileFlat(tile + delta)) {
375 return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
376 }
377 WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WaterClass::Canal;
378
379 for (LockPart lock_part = LockPart::Middle; TileIndex t : {tile, tile - delta, tile + delta}) {
380 if (IsBridgeAbove(t)) {
381 int height_diff = GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(lock_part) - GetBridgeHeight(GetSouthernBridgeEnd(t));
382 if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff * TILE_HEIGHT_STEP);
383 }
384 ++lock_part;
385 }
386
387 if (flags.Test(DoCommandFlag::Execute)) {
388 /* Update company infrastructure counts. */
390 if (c != nullptr) {
391 /* Counts for the water. */
392 if (!IsWaterTile(tile - delta)) c->infrastructure.water++;
393 if (!IsWaterTile(tile + delta)) c->infrastructure.water++;
394 /* Count for the lock itself. */
395 c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock is three tiles.
397 }
398
399 MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
400 CheckForDockingTile(tile - delta);
401 CheckForDockingTile(tile + delta);
403 MarkTileDirtyByTile(tile - delta);
404 MarkTileDirtyByTile(tile + delta);
405 MarkCanalsAndRiversAroundDirty(tile - delta);
406 MarkCanalsAndRiversAroundDirty(tile + delta);
407 InvalidateWaterRegion(tile - delta);
408 InvalidateWaterRegion(tile + delta);
409 }
411
412 return cost;
413}
414
422{
423 if (GetTileOwner(tile) != OWNER_NONE) {
425 if (ret.Failed()) return ret;
426 }
427
429
430 /* make sure no vehicle is on the tile. */
432 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
433 if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
434 if (ret.Failed()) return ret;
435
436 if (flags.Test(DoCommandFlag::Execute)) {
437 /* Remove middle part from company infrastructure count. */
439 if (c != nullptr) {
440 c->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // three parts of the lock.
442 }
443
444 if (GetWaterClass(tile) == WaterClass::River) {
445 MakeRiver(tile, Random());
446 } else {
447 DoClearSquare(tile);
449 }
450 MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
451 MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
453 MarkCanalsAndRiversAroundDirty(tile - delta);
454 MarkCanalsAndRiversAroundDirty(tile + delta);
455 }
456
458}
459
467{
469 if (dir == DiagDirection::Invalid) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
470
471 TileIndex lower_tile = TileAddByDiagDir(tile, ReverseDiagDir(dir));
472
473 /* If freeform edges are disabled, don't allow building on edge tiles. */
474 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(lower_tile), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(lower_tile), 1, Map::MaxY() - 1))) {
475 return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
476 }
477
478 return DoBuildLock(tile, dir, flags);
479}
480
486{
487 MakeRiver(tile, Random());
489
490 /* Remove desert directly around the river tile. */
493 }
494}
495
505CommandCost CmdBuildCanal(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
506{
507 if (start_tile >= Map::Size() || !IsValidWaterClass(wc)) return CMD_ERROR;
508
509 /* Outside of the editor you can only build canals, not oceans */
510 if (wc != WaterClass::Canal && _game_mode != GameMode::Editor) return CMD_ERROR;
511
513
514 std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
515 for (; *iter != INVALID_TILE; ++(*iter)) {
516 TileIndex current_tile = *iter;
517 CommandCost ret;
518
519 Slope slope = GetTileSlope(current_tile);
520 if (slope != SLOPE_FLAT && (wc != WaterClass::River || !IsInclinedSlope(slope))) {
521 return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
522 }
523
524 bool water = IsWaterTile(current_tile);
525
526 /* Outside the editor, prevent building canals over your own or OWNER_NONE owned canals */
527 if (water && IsCanal(current_tile) && _game_mode != GameMode::Editor && (IsTileOwner(current_tile, _current_company) || IsTileOwner(current_tile, OWNER_NONE))) continue;
528
529 ret = Command<Commands::LandscapeClear>::Do(flags, current_tile);
530 if (ret.Failed()) return ret;
531
532 if (!water) cost.AddCost(ret.GetCost());
533
534 if (flags.Test(DoCommandFlag::Execute)) {
535 if (IsTileType(current_tile, TileType::Water) && IsCanal(current_tile)) {
536 Owner owner = GetTileOwner(current_tile);
537 if (Company::IsValidID(owner)) {
538 Company::Get(owner)->infrastructure.water--;
540 }
541 }
542
543 switch (wc) {
545 MakeRiver(current_tile, Random());
546 if (_game_mode == GameMode::Editor) {
547 /* Remove desert directly around the river tile. */
548 for (auto t : SpiralTileSequence(current_tile, RIVER_OFFSET_DESERT_DISTANCE)) {
550 }
551 }
552 break;
553
554 case WaterClass::Sea:
555 if (TileHeight(current_tile) == 0) {
556 MakeSea(current_tile);
557 break;
558 }
559 [[fallthrough]];
560
561 default:
562 MakeCanal(current_tile, _current_company, Random());
564 Company::Get(_current_company)->infrastructure.water++;
566 }
567 break;
568 }
569 MarkTileDirtyByTile(current_tile);
570 MarkCanalsAndRiversAroundDirty(current_tile);
571 CheckForDockingTile(current_tile);
572 }
573
575 }
576
577 if (cost.GetCost() == 0) {
578 return CommandCost(STR_ERROR_ALREADY_BUILT);
579 } else {
580 return cost;
581 }
582}
583
584
587{
588 switch (GetWaterTileType(tile)) {
591 if (flags.Test(DoCommandFlag::NoWater)) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER);
592
593 Money base_cost = IsCanal(tile) ? _price[Price::ClearCanal] : _price[Price::ClearWater];
594 /* Make sure freeform edges are allowed or it's not an edge tile. */
595 if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(tile), 1, Map::MaxX() - 1) ||
596 !IsInsideMM(TileY(tile), 1, Map::MaxY() - 1))) {
597 return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
598 }
599
600 /* Make sure no vehicle is on the tile */
602 if (ret.Failed()) return ret;
603
604 Owner owner = GetTileOwner(tile);
605 if (owner != OWNER_WATER && owner != OWNER_NONE) {
606 ret = CheckTileOwnership(tile);
607 if (ret.Failed()) return ret;
608 }
609
610 if (flags.Test(DoCommandFlag::Execute)) {
611 if (IsCanal(tile) && Company::IsValidID(owner)) {
612 Company::Get(owner)->infrastructure.water--;
614 }
615
616 /* Handle local authority impact */
617 if (IsRiver(tile)) {
619 Town *town = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
620 if (town != nullptr) ChangeTownRating(town, RATING_WATER_RIVER_DOWN_STEP, RATING_WATER_MINIMUM, flags);
621 }
622 }
623
624 DoClearSquare(tile);
627 }
628
629 return CommandCost(ExpensesType::Construction, base_cost);
630 }
631
634 Slope slope = GetTileSlope(tile);
635
636 /* Make sure no vehicle is on the tile */
638 if (ret.Failed()) return ret;
639
640 if (flags.Test(DoCommandFlag::Execute)) {
641 DoClearSquare(tile);
644 }
645 if (IsSlopeWithOneCornerRaised(slope)) {
647 } else {
649 }
650 }
651
652 case WaterTileType::Lock: {
654 /* NE SE SW NW */
655 {{{ { 0, 0}, {0, 0}, { 0, 0}, {0, 0} }}}, // LockPart::Middle
656 {{{ {-1, 0}, {0, 1}, { 1, 0}, {0, -1} }}}, // LockPart::Lower
657 {{{ { 1, 0}, {0, -1}, {-1, 0}, {0, 1} }}}, // LockPart::Upper
658 }}};
659
660 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
662 /* move to the middle tile.. */
663 return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[GetLockPart(tile)][GetLockDirection(tile)]), flags);
664 }
665
667 if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
668 return RemoveShipDepot(tile, flags);
669
670 default:
671 NOT_REACHED();
672 }
673}
674
684{
685 switch (GetTileType(tile)) {
686 case TileType::Water:
687 switch (GetWaterTileType(tile)) {
688 default: NOT_REACHED();
692 return true;
693
696
699 switch (GetTileSlope(tile)) {
700 case SLOPE_W: return (from == Direction::SE) || (from == Direction::E) || (from == Direction::NE);
701 case SLOPE_S: return (from == Direction::NE) || (from == Direction::N) || (from == Direction::NW);
702 case SLOPE_E: return (from == Direction::NW) || (from == Direction::W) || (from == Direction::SW);
703 case SLOPE_N: return (from == Direction::SW) || (from == Direction::S) || (from == Direction::SE);
704 default: return false;
705 }
706 }
707
710 assert(IsPlainRail(tile));
711 switch (GetTileSlope(tile)) {
712 case SLOPE_W: return (from == Direction::SE) || (from == Direction::E) || (from == Direction::NE);
713 case SLOPE_S: return (from == Direction::NE) || (from == Direction::N) || (from == Direction::NW);
714 case SLOPE_E: return (from == Direction::NW) || (from == Direction::W) || (from == Direction::SW);
715 case SLOPE_N: return (from == Direction::SW) || (from == Direction::S) || (from == Direction::SE);
716 default: return false;
717 }
718 }
719 return false;
720
722 if (IsOilRig(tile)) {
723 /* Do not draw waterborders inside of industries.
724 * Note: There is no easy way to detect the industry of an oilrig tile. */
725 TileIndex src_tile = tile + TileOffsByDir(from);
726 if ((IsTileType(src_tile, TileType::Station) && IsOilRig(src_tile)) ||
727 (IsTileType(src_tile, TileType::Industry))) return true;
728
729 return IsTileOnWater(tile);
730 }
731 return (IsDock(tile) && IsTileFlat(tile)) || IsBuoy(tile);
732
733 case TileType::Industry: {
734 /* Do not draw waterborders inside of industries.
735 * Note: There is no easy way to detect the industry of an oilrig tile. */
736 TileIndex src_tile = tile + TileOffsByDir(from);
737 if ((IsTileType(src_tile, TileType::Station) && IsOilRig(src_tile)) ||
738 (IsTileType(src_tile, TileType::Industry) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
739
740 return IsTileOnWater(tile);
741 }
742
743 case TileType::Object: return IsTileOnWater(tile);
744
746
747 case TileType::Void: return true; // consider map border as water, esp. for rivers
748
749 default: return false;
750 }
751}
752
760static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
761{
762 if (base != SPR_FLAT_WATER_TILE) {
763 /* Only call offset callback if the sprite is NewGRF-provided. */
764 offset = GetCanalSpriteOffset(feature, tile, offset);
765 }
766 DrawGroundSprite(base + offset, PAL_NONE);
767}
768
775static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
776{
777 CanalFeature feature;
778 SpriteID base = 0;
779 if (canal) {
780 feature = CanalFeature::Dikes;
782 if (base == 0) base = SPR_CANAL_DIKES_BASE;
783 } else {
784 feature = CanalFeature::RiverEdge;
786 if (base == 0) return; // Don't draw if no sprites provided.
787 }
788
789 uint wa;
790
791 /* determine the edges around with water. */
792 wa = IsWateredTile(TileAddXY(tile, -1, 0), Direction::SW) << 0;
793 wa += IsWateredTile(TileAddXY(tile, 0, 1), Direction::NW) << 1;
794 wa += IsWateredTile(TileAddXY(tile, 1, 0), Direction::NE) << 2;
795 wa += IsWateredTile(TileAddXY(tile, 0, -1), Direction::SE) << 3;
796
797 if (!(wa & 1)) DrawWaterSprite(base, offset, feature, tile);
798 if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
799 if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
800 if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
801
802 /* right corner */
803 switch (wa & 0x03) {
804 case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
805 case 3: if (!IsWateredTile(TileAddXY(tile, -1, 1), Direction::W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
806 }
807
808 /* bottom corner */
809 switch (wa & 0x06) {
810 case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
811 case 6: if (!IsWateredTile(TileAddXY(tile, 1, 1), Direction::N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
812 }
813
814 /* left corner */
815 switch (wa & 0x0C) {
816 case 0: DrawWaterSprite(base, offset + 6, feature, tile); break;
817 case 12: if (!IsWateredTile(TileAddXY(tile, 1, -1), Direction::E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
818 }
819
820 /* upper corner */
821 switch (wa & 0x09) {
822 case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
823 case 9: if (!IsWateredTile(TileAddXY(tile, -1, -1), Direction::S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
824 }
825}
826
829{
831}
832
837static void DrawCanalWater(TileIndex tile)
838{
841 /* First water slope sprite is flat water. */
843 if (image == 0) image = SPR_FLAT_WATER_TILE;
844 }
846
847 DrawWaterEdges(true, 0, tile);
848}
849
850#include "table/water_land.h"
851
862static void DrawWaterTileStruct(const TileInfo *ti, std::span<const DrawTileSeqStruct> seq, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
863{
864 /* Don't draw if buildings are invisible. */
866
867 for (const DrawTileSeqStruct &dtss : seq) {
868 uint tile_offs = offset + dtss.image.sprite;
869 if (feature < CanalFeature::End) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
870 AddSortableSpriteToDraw(base + tile_offs, palette, *ti, dtss, IsTransparencySet(TransparencyOption::Buildings));
871 }
872}
873
878static void DrawWaterLock(const TileInfo *ti)
879{
880 LockPart part = GetLockPart(ti->tile);
882
883 /* Draw ground sprite. */
884 SpriteID image = dts.ground.sprite;
885
887 if (water_base == 0) {
888 /* Use default sprites. */
889 water_base = SPR_CANALS_BASE;
891 /* NewGRF supplies a flat sprite as first sprite. */
892 if (image == SPR_FLAT_WATER_TILE) {
893 image = water_base;
894 } else {
895 image++;
896 }
897 }
898
899 if (image < 5) image += water_base;
900 DrawGroundSprite(image, PAL_NONE);
901
902 /* Draw structures. */
903 uint zoffs = 0;
905
906 if (base == 0) {
907 /* If no custom graphics, use defaults. */
908 base = SPR_LOCK_BASE;
909 uint8_t z_threshold = part == LockPart::Upper ? 8 : 0;
910 zoffs = ti->z > z_threshold ? 24 : 0;
911 }
912
913 DrawWaterTileStruct(ti, dts.GetSequence(), base, zoffs, PAL_NONE, CanalFeature::Locks);
914}
915
920static void DrawWaterDepot(const TileInfo *ti)
921{
922 DrawWaterClassGround(ti);
924}
925
926static void DrawRiverWater(const TileInfo *ti)
927{
929 uint offset = 0;
930 uint edges_offset = 0;
931
934 if (image == 0) {
935 switch (ti->tileh) {
936 case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
937 case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
938 case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
939 case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
940 default: image = SPR_FLAT_WATER_TILE; break;
941 }
942 } else {
943 /* Flag bit 0 indicates that the first sprite is flat water. */
945
946 switch (ti->tileh) {
947 case SLOPE_SE: edges_offset += 12; break;
948 case SLOPE_NE: offset += 1; edges_offset += 24; break;
949 case SLOPE_SW: offset += 2; edges_offset += 36; break;
950 case SLOPE_NW: offset += 3; edges_offset += 48; break;
951 default: offset = 0; break;
952 }
953
955 }
956 }
957
958 DrawGroundSprite(image + offset, PAL_NONE);
959
960 /* Draw river edges if available. */
961 DrawWaterEdges(false, edges_offset, ti->tile);
962}
963
964void DrawShoreTile(Slope tileh)
965{
966 /* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
967 * This allows to calculate the proper sprite to display for this Slope */
968 static constexpr SlopeIndexArray<uint8_t> tileh_to_shoresprite = {
969 0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 15,
971 };
972
973 assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
974 assert(tileh != SLOPE_FLAT); // Shore is never flat
975
976 assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS)); // No suitable sprites for current flooding behaviour
977
978 DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
979}
980
981void DrawWaterClassGround(const TileInfo *ti)
982{
983 switch (GetWaterClass(ti->tile)) {
984 case WaterClass::Sea: DrawSeaWater(ti->tile); break;
985 case WaterClass::Canal: DrawCanalWater(ti->tile); break;
986 case WaterClass::River: DrawRiverWater(ti); break;
987 default: NOT_REACHED();
988 }
989}
990
992static void DrawTile_Water(TileInfo *ti)
993{
994 switch (GetWaterTileType(ti->tile)) {
996 DrawWaterClassGround(ti);
997 /* A plain water tile can be traversed in any direction, so setting blocked pillars here would mean all bridges
998 * with edges would have no pillars above water. Instead prefer current behaviour of ships passing through. */
999 DrawBridgeMiddle(ti, {});
1000 break;
1001
1002 case WaterTileType::Coast: {
1003 DrawShoreTile(ti->tileh);
1004 DrawBridgeMiddle(ti, {});
1005 break;
1006 }
1007
1009 DrawWaterLock(ti);
1011 ? BridgePillarFlags{BridgePillarFlag::EdgeNE, BridgePillarFlag::EdgeSW}
1012 : BridgePillarFlags{BridgePillarFlag::EdgeNW, BridgePillarFlag::EdgeSE});
1013 break;
1014
1016 DrawWaterDepot(ti);
1017 DrawBridgeMiddle(ti, BRIDGEPILLARFLAGS_ALL);
1018 break;
1019
1021 DrawWaterClassGround(ti);
1023 DrawBridgeMiddle(ti, {});
1024 break;
1025
1027 DrawShoreTile(ti->tileh);
1029 DrawBridgeMiddle(ti, {});
1030 break;
1031 }
1032}
1033
1034void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
1035{
1036 const DrawTileSprites &dts = _shipdepot_display_data[axis][part];
1037
1038 DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
1040}
1041
1042
1044static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y, [[maybe_unused]] bool ground_vehicle)
1045{
1046 auto [tileh, z] = GetTilePixelSlope(tile);
1047
1048 return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
1049}
1050
1053{
1054 switch (GetWaterTileType(tile)) {
1056 switch (GetWaterClass(tile)) {
1057 case WaterClass::Sea: td.str = STR_LAI_WATER_DESCRIPTION_WATER; break;
1058 case WaterClass::Canal: td.str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
1059 case WaterClass::River: td.str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
1060 default: NOT_REACHED();
1061 }
1062 break;
1063 case WaterTileType::Coast: td.str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
1064 case WaterTileType::Lock : td.str = STR_LAI_WATER_DESCRIPTION_LOCK; break;
1066 td.str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
1067 td.build_date = Depot::GetByTile(tile)->build_date;
1068 break;
1069 case WaterTileType::ClearRocks: td.str = STR_LAI_WATER_DESCRIPTION_WATER_ROCKS; break;
1070 case WaterTileType::CoastRocks: td.str = STR_LAI_WATER_DESCRIPTION_COAST_ROCKS; break;
1071 default: NOT_REACHED();
1072 }
1073
1074 td.owner[0] = GetTileOwner(tile);
1075}
1076
1082static void FloodVehicle(Vehicle *v)
1083{
1084 uint victims = v->Crash(true);
1085
1086 AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims, v->owner));
1087 Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims, v->owner));
1088 AddTileNewsItem(GetEncodedString(STR_NEWS_DISASTER_FLOOD_VEHICLE, victims), NewsType::Accident, v->tile);
1090 if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1091}
1092
1098static void FloodVehicleProc(Vehicle *v, int z)
1099{
1100 if (v->vehstatus.Test(VehState::Crashed)) return;
1101
1102 switch (v->type) {
1103 default: break;
1104
1105 case VehicleType::Aircraft: {
1106 if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
1107 if (v->subtype == AIR_SHADOW) break;
1108
1109 /* We compare v->z_pos against delta_z + 1 because the shadow
1110 * is at delta_z and the actual aircraft at delta_z + 1. */
1111 const Station *st = Station::GetByTile(v->tile);
1112 const AirportFTAClass *airport = st->airport.GetFTA();
1113 if (v->z_pos != airport->delta_z + 1) break;
1114
1115 FloodVehicle(v);
1116 break;
1117 }
1118
1119 case VehicleType::Train:
1120 case VehicleType::Road: {
1121 if (v->z_pos > z) break;
1122 FloodVehicle(v->First());
1123 break;
1124 }
1125 }
1126}
1127
1128static void FloodVehiclesOnTile(TileIndex tile, int z)
1129{
1130 for (Vehicle *v : VehiclesOnTile(tile)) {
1131 FloodVehicleProc(v, z);
1132 }
1133}
1134
1140static void FloodVehicles(TileIndex tile)
1141{
1142 if (IsAirportTile(tile)) {
1143 const Station *st = Station::GetByTile(tile);
1144 for (TileIndex airport_tile : st->airport) {
1145 if (st->TileBelongsToAirport(airport_tile)) FloodVehiclesOnTile(airport_tile, 0);
1146 }
1147
1148 /* No vehicle could be flooded on this airport anymore */
1149 return;
1150 }
1151
1152 if (!IsBridgeTile(tile)) {
1153 FloodVehiclesOnTile(tile, 0);
1154 return;
1155 }
1156
1157 TileIndex end = GetOtherBridgeEnd(tile);
1158 int z = GetBridgePixelHeight(tile);
1159
1160 FloodVehiclesOnTile(tile, z);
1161 FloodVehiclesOnTile(end, z);
1162}
1163
1170{
1171 /* FloodingBehaviour::Active: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs
1172 * FloodingBehaviour::DryOut: coast with more than one corner raised, coast with rail-track, coast with trees
1173 * FloodingBehaviour::Passive: (not used)
1174 * FloodingBehaviour::None: canals, rivers, everything else
1175 */
1176 switch (GetTileType(tile)) {
1177 case TileType::Water:
1178 if (IsCoast(tile)) {
1179 Slope tileh = GetTileSlope(tile);
1181 }
1182 [[fallthrough]];
1183 case TileType::Station:
1184 case TileType::Industry:
1185 case TileType::Object:
1187
1188 case TileType::Railway:
1191 }
1193
1194 case TileType::Trees:
1196
1197 case TileType::Void:
1199
1200 default:
1202 }
1203}
1204
1209static void DoFloodTile(TileIndex target)
1210{
1211 assert(!IsTileType(target, TileType::Water));
1212
1213 bool flooded = false; // Will be set to true if something is changed.
1214
1216
1217 /* Flooded rocks can stay as water-logged rocks. */
1218 TileType tiletype = GetTileType(target);
1219 bool is_rocks = tiletype == TileType::Clear && GetClearGround(target) == ClearGround::Rocks;
1220
1221 Slope tileh = GetTileSlope(target);
1222 if (tileh != SLOPE_FLAT) {
1223 /* make coast.. */
1224 switch (tiletype) {
1225 case TileType::Railway: {
1226 if (!IsPlainRail(target)) break;
1227 FloodVehicles(target);
1228 flooded = FloodHalftile(target);
1229 break;
1230 }
1231
1232 case TileType::Trees:
1233 if (!IsSlopeWithOneCornerRaised(tileh)) {
1235 MarkTileDirtyByTile(target);
1236 flooded = true;
1237 break;
1238 }
1239 [[fallthrough]];
1240
1241 case TileType::Clear: {
1242 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, target).Succeeded()) {
1243 MakeShore(target, is_rocks);
1244 MarkTileDirtyByTile(target);
1245 flooded = true;
1246 }
1247 break;
1248 }
1249
1250 default:
1251 break;
1252 }
1253 } else {
1254 /* Flood vehicles */
1255 FloodVehicles(target);
1256
1257 /* flood flat tile */
1258 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, target).Succeeded()) {
1259 MakeSea(target, is_rocks);
1260 MarkTileDirtyByTile(target);
1261 flooded = true;
1262 }
1263 }
1264
1265 if (flooded) {
1266 /* Mark surrounding canal tiles dirty too to avoid glitches */
1268
1269 /* update signals if needed */
1271
1272 if (IsPossibleDockingTile(target)) CheckForDockingTile(target);
1273 InvalidateWaterRegion(target);
1274 }
1275}
1276
1281static void DoDryUp(TileIndex tile)
1282{
1284
1285 switch (GetTileType(tile)) {
1286 case TileType::Railway:
1287 assert(IsPlainRail(tile));
1289
1290 RailGroundType new_ground;
1291 switch (TrackBitsToTrack(GetTrackBits(tile))) {
1292 case Track::Upper: new_ground = RailGroundType::FenceHoriz1; break;
1293 case Track::Lower: new_ground = RailGroundType::FenceHoriz2; break;
1294 case Track::Left: new_ground = RailGroundType::FenceVert1; break;
1295 case Track::Right: new_ground = RailGroundType::FenceVert2; break;
1296 default: NOT_REACHED();
1297 }
1298 SetRailGroundType(tile, new_ground);
1299 MarkTileDirtyByTile(tile);
1300 break;
1301
1302 case TileType::Trees:
1304 MarkTileDirtyByTile(tile);
1305 break;
1306
1307 case TileType::Water: {
1308 assert(IsCoast(tile));
1309
1310 bool is_rocks = GetWaterTileType(tile) == WaterTileType::CoastRocks;
1311 if (Command<Commands::LandscapeClear>::Do(DoCommandFlag::Execute, tile).Succeeded()) {
1312 MakeClear(tile, is_rocks ? ClearGround::Rocks : ClearGround::Grass, 3);
1313 MarkTileDirtyByTile(tile);
1314 }
1315 break;
1316 }
1317
1318 default: NOT_REACHED();
1319 }
1320}
1321
1329{
1330 if (IsTileType(tile, TileType::Water)) {
1331 AmbientSoundEffect(tile);
1332 if (IsNonFloodingWaterTile(tile)) return;
1333 }
1334
1335 switch (GetFloodingBehaviour(tile)) {
1337 bool continue_flooding = false;
1338 for (Direction dir : EnumRange(Direction::End)) {
1340 /* Contrary to drying up, flooding does not consider TileType::Void tiles. */
1341 if (!IsValidTile(dest)) continue;
1342 /* do not try to flood water tiles - increases performance a lot */
1343 if (IsTileType(dest, TileType::Water)) continue;
1344
1345 /* Buoys and docks cannot be flooded, and when removed turn into flooding water. */
1346 if (IsTileType(dest, TileType::Station) && (IsBuoy(dest) || IsDock(dest))) continue;
1347
1348 /* This neighbour tile might be floodable later if the tile is cleared, so allow flooding to continue. */
1349 continue_flooding = true;
1350
1351 /* TreeGround::Shore is the sign of a previous flood. */
1352 if (IsTileType(dest, TileType::Trees) && GetTreeGround(dest) == TreeGround::Shore) continue;
1353
1354 auto [slope_dest, z_dest] = GetFoundationSlope(dest);
1355 if (z_dest > 0) continue;
1356
1357 if (!_flood_from_dirs[RemoveSteepSlope(RemoveHalftileSlope(slope_dest))].Test(ReverseDir(dir))) continue;
1358
1359 DoFloodTile(dest);
1360 }
1361 if (!continue_flooding && IsTileType(tile, TileType::Water)) SetNonFloodingWaterTile(tile, true);
1362 break;
1363 }
1364
1366 Slope slope_here = RemoveHalftileSlope(RemoveSteepSlope(std::get<Slope>(GetFoundationSlope(tile))));
1367 for (Direction dir : _flood_from_dirs[slope_here]) {
1369 /* Contrary to flooding, drying up does consider TileType::Void tiles. */
1370 if (dest == INVALID_TILE) continue;
1371
1372 FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
1373 if (dest_behaviour == FloodingBehaviour::Active || dest_behaviour == FloodingBehaviour::Passive) return;
1374 }
1375 DoDryUp(tile);
1376 break;
1377 }
1378
1379 default: return;
1380 }
1381}
1382
1383void ConvertGroundTilesIntoWaterTiles()
1384{
1385 for (const auto tile : Map::Iterate()) {
1386 auto [slope, z] = GetTileSlopeZ(tile);
1387 if (IsTileType(tile, TileType::Clear) && z == 0) {
1388 /* Make both water for tiles at level 0
1389 * and make shore, as that looks much better
1390 * during the generation. */
1391 switch (slope) {
1392 case SLOPE_FLAT:
1393 MakeSea(tile);
1394 break;
1395
1396 case SLOPE_N:
1397 case SLOPE_E:
1398 case SLOPE_S:
1399 case SLOPE_W:
1400 MakeShore(tile);
1401 break;
1402
1403 default:
1404 for (Direction dir : _flood_from_dirs[RemoveSteepSlope(slope)]) {
1405 TileIndex dest = TileAddByDir(tile, dir);
1406 Slope slope_dest = RemoveSteepSlope(GetTileSlope(dest));
1407 if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest) || IsTileType(dest, TileType::Void)) {
1408 MakeShore(tile);
1409 break;
1410 }
1411 }
1412 break;
1413 }
1414 }
1415 }
1416}
1417
1419static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, [[maybe_unused]] RoadTramType sub_mode, [[maybe_unused]] DiagDirection side)
1420{
1421 static constexpr NonSteepSlopeIndexArray<TrackBits> coast_tracks = {{{{}, Track::Right, Track::Upper, {}, Track::Left, {}, {}, {}, Track::Lower, {}, {}, {}, {}, {}, {}}}};
1422
1423 TrackBits ts;
1424
1425 if (mode != TransportType::Water) return {};
1426
1427 switch (GetWaterTileType(tile)) {
1428 case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TrackBits{}; break;
1429 case WaterTileType::Coast: ts = coast_tracks[GetTileSlope(tile) & SLOPE_ELEVATED]; break;
1431 case WaterTileType::Depot: ts = AxisToTrack(GetShipDepotAxis(tile)); break;
1432 default: return {};
1433 }
1434 if (TileX(tile) == 0) {
1435 /* NE border: remove tracks that connects NE tile edge */
1437 }
1438 if (TileY(tile) == 0) {
1439 /* NW border: remove tracks that connects NW tile edge */
1441 }
1442 return {TrackBitsToTrackdirBits(ts), {}};
1443}
1444
1447{
1450 return true;
1451 }
1452 return false;
1453}
1454
1456static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
1457{
1458 if (!IsTileOwner(tile, old_owner)) return;
1459
1460 bool is_lock_middle = IsLock(tile) && GetLockPart(tile) == LockPart::Middle;
1461
1462 /* No need to dirty company windows here, we'll redraw the whole screen anyway. */
1463 if (is_lock_middle) Company::Get(old_owner)->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1464 if (new_owner != INVALID_OWNER) {
1465 if (is_lock_middle) Company::Get(new_owner)->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1466 /* Only subtract from the old owner here if the new owner is valid,
1467 * otherwise we clear ship depots and canal water below. */
1468 if (GetWaterClass(tile) == WaterClass::Canal && !is_lock_middle) {
1469 Company::Get(old_owner)->infrastructure.water--;
1470 Company::Get(new_owner)->infrastructure.water++;
1471 }
1472 if (IsShipDepot(tile)) {
1473 Company::Get(old_owner)->infrastructure.water -= LOCK_DEPOT_TILE_FACTOR;
1474 Company::Get(new_owner)->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
1475 }
1476
1477 SetTileOwner(tile, new_owner);
1478 return;
1479 }
1480
1481 /* Remove depot */
1482 if (IsShipDepot(tile)) Command<Commands::LandscapeClear>::Do({DoCommandFlag::Execute, DoCommandFlag::Bankrupt}, tile);
1483
1484 /* Set owner of canals and locks ... and also canal under dock there was before.
1485 * Check if the new owner after removing depot isn't OWNER_WATER. */
1486 if (IsTileOwner(tile, old_owner)) {
1487 if (GetWaterClass(tile) == WaterClass::Canal && !is_lock_middle) Company::Get(old_owner)->infrastructure.water--;
1488 SetTileOwner(tile, OWNER_NONE);
1489 }
1490}
1491
1493static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, [[maybe_unused]] int z_new, [[maybe_unused]] Slope tileh_new)
1494{
1495 /* Canals can't be terraformed */
1496 if (IsWaterTile(tile) && IsCanal(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
1497
1498 /* Rivers can't be terraformed */
1499 if (IsWaterTile(tile) && IsRiver(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_RIVER_FIRST);
1500
1501 return Command<Commands::LandscapeClear>::Do(flags, tile);
1502}
1503
1505static CommandCost CheckBuildAbove_Water(TileIndex tile, [[maybe_unused]] DoCommandFlags flags, [[maybe_unused]] Axis axis, int height)
1506{
1507 switch (GetWaterTileType(tile)) {
1512 break;
1513
1514 case WaterTileType::Lock: {
1515 int height_diff = GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) - height;
1516 if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff * TILE_HEIGHT_STEP);
1517 break;
1518 }
1519
1520 case WaterTileType::Depot: {
1521 int height_diff = GetTileMaxZ(tile) + MINIMAL_DEPOT_BRIDGE_HEIGHT - height;
1522 if (height_diff > 0) return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_SHIP_DEPOT, height_diff * TILE_HEIGHT_STEP);
1523 break;
1524 }
1525 }
1526
1527 return CommandCost();
1528}
1529
1532 .draw_tile_proc = DrawTile_Water,
1533 .get_slope_pixel_z_proc = GetSlopePixelZ_Water,
1534 .clear_tile_proc = ClearTile_Water,
1535 .get_tile_desc_proc = GetTileDesc_Water,
1536 .get_tile_track_status_proc = GetTileTrackStatus_Water,
1537 .click_tile_proc = ClickTile_Water,
1538 .tile_loop_proc = TileLoop_Water,
1539 .change_tile_owner_proc = ChangeTileOwner_Water,
1540 .vehicle_enter_tile_proc = [](Vehicle *, TileIndex, int, int) -> VehicleEnterTileStates { return {}; },
1541 .terraform_tile_proc = TerraformTile_Water,
1542 .check_build_above_proc = CheckBuildAbove_Water,
1543};
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.
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
EnumBitSet< BridgePillarFlag, uint8_t > BridgePillarFlags
Bitset of BridgePillarFlag elements.
Definition bridge_type.h:53
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:231
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are 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?
Iterate a range of enum values.
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.
@ Rocks
Rocks with snow transition (0-3).
Definition clear_map.h:24
@ 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
ClearGround GetClearGround(Tile t)
Get the type of clear tile.
Definition clear_map.h:52
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
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
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.
static constexpr uint8_t MINIMAL_DEPOT_BRIDGE_HEIGHT
Minimal height for a bridge above any depot tile.
Definition depot_type.h:21
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.
@ SW
Southwest.
@ NW
Northwest.
@ End
Used to iterate.
@ NE
Northeast.
@ SE
Southeast.
Axis
Enumeration for the two axis X and Y.
@ X
The X axis.
DiagDirection
Enumeration for diagonal directions.
@ Invalid
Flag for an invalid DiagDirection.
@ End
Used for iterations.
Prices _price
Prices and also the fractional part.
Definition economy.cpp:107
static const uint LOCK_DEPOT_TILE_FACTOR
Multiplier for how many regular tiles a lock counts.
@ 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
EnumClassIndexContainer< std::array< T, to_underlying(N)>, Index > EnumIndexArray
A typedef for EnumClassIndexContainer using std::array as the backing container type.
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:1037
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:88
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
static const SpriteID SPR_LOCK_BASE
Definition sprites.h:739
static const SpriteID SPR_CANAL_DIKES_BASE
Definition sprites.h:764
static const SpriteID SPR_WATER_SLOPE_X_UP
Water flowing negative X direction.
Definition sprites.h:729
static const SpriteID SPR_WATER_SLOPE_Y_DOWN
Water flowing positive Y direction.
Definition sprites.h:730
static const SpriteID SPR_WATER_SLOPE_X_DOWN
Water flowing positive X direction.
Definition sprites.h:728
static const SpriteID SPR_WATER_SLOPE_Y_UP
Water flowing negative Y direction.
Definition sprites.h:727
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.
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,...
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
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:28
@ RiverEdge
The river banks.
Definition newgrf.h:35
@ Locks
The sides of the lock.
Definition newgrf.h:30
@ End
End marker.
Definition newgrf.h:38
@ LockWaterSlope
The sloped water tiles in locks.
Definition newgrf.h:29
@ RiverSlope
The sloped water tiles for rivers.
Definition newgrf.h:34
@ Dikes
The canal dikes/embankment.
Definition newgrf.h:31
@ HasFlatSprite
Additional flat ground sprite in the beginning.
Definition newgrf.h:43
EnumIndexArray< WaterFeature, CanalFeature, CanalFeature::End > _water_feature
Table of canal 'feature' sprite groups.
uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
Get the new sprite offset for a water tile.
SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
Lookup the base sprite to use for a canal.
Handling of NewGRF canals.
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
@ Editor
In the scenario editor.
Definition openttd.h:21
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:601
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:568
@ FenceVert2
Grass with a fence at the western side.
Definition rail_map.h:578
@ FenceHoriz2
Grass with a fence at the northern side.
Definition rail_map.h:580
@ HalfTileWater
Grass with a fence and shore or water on the free halftile.
Definition rail_map.h:582
@ FenceVert1
Grass with a fence at the eastern side.
Definition rail_map.h:577
@ FenceHoriz1
Grass with a fence at the southern side.
Definition rail_map.h:579
void SetRailGroundType(Tile t, RailGroundType rgt)
Set the ground type for rail tiles.
Definition rail_map.h:591
Pseudo random number generator.
RoadTramType
The different types of road type.
Definition road_type.h:38
@ Invalid
Invalid marker.
Definition road_type.h:42
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:582
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:70
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 Slope RemoveSteepSlope(Slope s)
Removes a steep flag from a slope.
Definition slope_func.h:46
bool IsInclinedSlope(Slope s)
Tests if a specific slope is an inclined slope.
Definition slope_func.h:238
static constexpr bool IsHalftileSlope(Slope s)
Checks for non-continuous slope on halftile foundations.
Definition slope_func.h:57
DiagDirection GetInclinedSlopeDirection(Slope s)
Returns the direction of an inclined slope.
Definition slope_func.h:249
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
@ SLOPE_W
the west corner of the tile is raised
Definition slope_type.h:55
@ SLOPE_ELEVATED
bit mask containing all 'simple' slopes
Definition slope_type.h:66
@ SLOPE_NS
north and south corner are raised
Definition slope_type.h:65
@ SLOPE_E
the east corner of the tile is raised
Definition slope_type.h:57
@ SLOPE_S
the south corner of the tile is raised
Definition slope_type.h:56
@ SLOPE_N
the north corner of the tile is raised
Definition slope_type.h:58
@ SLOPE_SW
south and west corner are raised
Definition slope_type.h:61
@ SLOPE_FLAT
a flat tile
Definition slope_type.h:54
@ SLOPE_NE
north and east corner are raised
Definition slope_type.h:63
@ SLOPE_SE
south and east corner are raised
Definition slope_type.h:62
@ SLOPE_NW
north and west corner are raised
Definition slope_type.h:60
@ SLOPE_EW
east and west corner are raised
Definition slope_type.h:64
EnumClassIndexContainer< std::array< T, SLOPE_ELEVATED >, Slope > NonSteepSlopeIndexArray
Array with non steep Slope as index.
Definition slope_type.h:104
EnumClassIndexContainer< std::array< T, SLOPE_STEEP|SLOPE_ELEVATED >, Slope > SlopeIndexArray
Array with Slope as index.
Definition slope_type.h:95
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 constexpr SpriteID SPR_OVERLAY_ROCKS_WATER_COAST
Rocks on water and coast.
Definition sprites.h:366
static const SpriteID SPR_FLAT_WATER_TILE
Definition sprites.h:685
static const SpriteID SPR_SHORE_BASE
Definition sprites.h:244
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:161
uint8_t delta_z
Z adjustment for helicopter pads.
Definition airport.h:201
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 upon destruction of this object to prevent stack v...
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:253
Station * neutral_station
Associated neutral station.
Definition industry.h:110
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 T * Create(Targs &&... args)
static Company * Get(auto index)
static bool CanAllocateItem(size_t n=1)
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:40
StringID str
Description of the tile.
Definition tile_cmd.h:41
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition tile_cmd.h:45
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
Track status of a tile.
Definition track_type.h:105
Vehicle data structure.
int32_t z_pos
z coordinate.
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition vehicle.cpp:301
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?
EnumBitSet< VehicleEnterTileState, uint8_t > VehicleEnterTileStates
Bitset of VehicleEnterTileState elements.
Definition tile_cmd.h:31
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
@ Desert
Tile is desert.
Definition tile_type.h:83
@ Normal
Normal tropiczone.
Definition tile_type.h:82
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
TileType
The different types of tiles.
Definition tile_type.h:48
@ 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:335
Types related to towns.
static constexpr int RATING_WATER_MINIMUM
minimum rating after removing water features near town
Definition town_type.h:80
static constexpr int RATING_WATER_RIVER_DOWN_STEP
removing a river tile
Definition town_type.h:79
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:292
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition track_func.h:166
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track Axis::X -> Track::X Axis::Y -> Track::Y Uses the fact that...
Definition track_func.h:62
Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a DiagDirection to the associated diagonal Track.
Definition track_func.h:419
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:281
EnumBitSet< Track, uint8_t > TrackBits
Bitset of Track elements.
Definition track_type.h:43
static constexpr TrackBits TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:52
@ X
Track along the x-axis (north-east to south-west).
Definition track_type.h:21
@ Upper
Track in the upper corner of the tile (north).
Definition track_type.h:23
@ Y
Track along the y-axis (north-west to south-east).
Definition track_type.h:22
@ Right
Track in the right corner of the tile (east).
Definition track_type.h:26
@ Left
Track in the left corner of the tile (west).
Definition track_type.h:25
@ Lower
Track in the lower corner of the tile (south).
Definition track_type.h:24
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...
@ Buildings
company buildings - depots, stations, HQ, ...
TransportType
Available types of 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:558
@ Crashed
Vehicle is crashed.
Functions related to vehicles.
@ Ship
Ship vehicle type.
@ Aircraft
Aircraft vehicle type.
@ Road
Road vehicle type.
@ 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:664
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
@ Active
The tile floods neighboured tiles.
Definition water.h:21
@ None
The tile does not flood neighboured tiles.
Definition water.h:20
@ DryOut
The tile drys out if it is not constantly flooded from neighboured tiles.
Definition water.h:23
@ Passive
The tile does not actively flood neighboured tiles, but it prevents them from drying out.
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.
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition water_cmd.cpp:99
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 TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Tile callback function signature for getting the possible tracks that can be taken on a given tile by...
static void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
Marks tile dirty if it is a canal or river tile.
Definition water_cmd.cpp:77
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.
static const NonSteepSlopeIndexArray< 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:53
CommandCost CmdBuildCanal(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
Build a piece of canal.
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).
static const AxisIndexArray< EnumIndexArray< DrawTileSpriteSpan, DepotPart, DepotPart::End > > _shipdepot_display_data
Data for drawing ship depots by Axis and DepotPart.
Definition water_land.h:48
static const EnumIndexArray< DiagDirectionIndexArray< DrawTileSpriteSpan >, LockPart, LockPart::End > _lock_display_data
Sprite layout of a lock for each lock part and direction.
Definition water_land.h:127
bool HasTileWaterGround(Tile t)
Checks whether the tile has water at the ground.
Definition water_map.h:356
TileIndex GetShipDepotNorthTile(Tile t)
Get the most northern tile of a ship depot.
Definition water_map.h:294
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:520
DepotPart GetShipDepotPart(Tile t)
Get the part of a ship depot.
Definition water_map.h:260
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition water_map.h:140
bool IsShipDepot(Tile t)
Is it a water tile with a ship depot on it?
Definition water_map.h:227
bool IsValidWaterClass(WaterClass wc)
Checks if a water class is valid.
Definition water_map.h:54
bool IsRiver(Tile t)
Is it a river water tile?
Definition water_map.h:184
DiagDirection GetLockDirection(Tile t)
Get the direction of the water lock.
Definition water_map.h:319
WaterClass
classes of water (for WaterTileType::Clear water tile type).
Definition water_map.h:41
@ River
River.
Definition water_map.h:44
@ Invalid
Used for industry tiles on land (also for oilrig if newgrf says so).
Definition water_map.h:45
@ Canal
Canal.
Definition water_map.h:43
@ Sea
Sea.
Definition water_map.h:42
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition water_map.h:105
bool IsCanal(Tile t)
Is it a canal tile?
Definition water_map.h:173
bool IsCoast(Tile t)
Is it a coast tile?
Definition water_map.h:205
void MakeRiver(Tile t, uint8_t random_bits)
Make a river tile.
Definition water_map.h:444
WaterTileType GetWaterTileType(Tile t)
Get the water tile type of a tile.
Definition water_map.h:82
void SetNonFloodingWaterTile(Tile t, bool b)
Set the non-flooding water tile state of a tile.
Definition water_map.h:538
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition water_map.h:116
void MakeCanal(Tile t, Owner o, uint8_t random_bits)
Make a canal tile.
Definition water_map.h:455
TileIndex GetOtherShipDepotTile(Tile t)
Get the other tile of the ship depot.
Definition water_map.h:283
void MakeShore(Tile t, bool rocks=false)
Helper function to make a coast tile.
Definition water_map.h:389
DepotPart
Sections of the water depot.
Definition water_map.h:60
@ South
Southern part of a depot.
Definition water_map.h:62
@ North
Northern part of a depot.
Definition water_map.h:61
@ ClearRocks
Rocks on water.
Definition water_map.h:36
@ Coast
Coast.
Definition water_map.h:33
@ CoastRocks
Rocks on coast.
Definition water_map.h:37
@ 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:548
void SetDockingTile(Tile t, bool b)
Set the docking tile state of a tile.
Definition water_map.h:367
LockPart
Sections of the water lock.
Definition water_map.h:67
@ Upper
Upper part of a lock.
Definition water_map.h:70
@ End
End marker.
Definition water_map.h:71
@ Middle
Middle part of a lock.
Definition water_map.h:68
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition water_map.h:194
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition water_map.h:308
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:470
void MakeSea(Tile t, bool rocks=false)
Make a sea tile.
Definition water_map.h:434
LockPart GetLockPart(Tile t)
Get the part of a lock.
Definition water_map.h:331
Axis GetShipDepotAxis(Tile t)
Get the axis of the ship depot.
Definition water_map.h:248
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.