OpenTTD Source  20241108-master-g80f628063a
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 <http://www.gnu.org/licenses/>.
6  */
7 
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 
44 #include "table/strings.h"
45 
46 #include "safeguards.h"
47 
51 static const uint8_t _flood_from_dirs[] = {
52  (1 << DIR_NW) | (1 << DIR_SW) | (1 << DIR_SE) | (1 << DIR_NE), // SLOPE_FLAT
53  (1 << DIR_NE) | (1 << DIR_SE), // SLOPE_W
54  (1 << DIR_NW) | (1 << DIR_NE), // SLOPE_S
55  (1 << DIR_NE), // SLOPE_SW
56  (1 << DIR_NW) | (1 << DIR_SW), // SLOPE_E
57  0, // SLOPE_EW
58  (1 << DIR_NW), // SLOPE_SE
59  (1 << DIR_N ) | (1 << DIR_NW) | (1 << DIR_NE), // SLOPE_WSE, SLOPE_STEEP_S
60  (1 << DIR_SW) | (1 << DIR_SE), // SLOPE_N
61  (1 << DIR_SE), // SLOPE_NW
62  0, // SLOPE_NS
63  (1 << DIR_E ) | (1 << DIR_NE) | (1 << DIR_SE), // SLOPE_NWS, SLOPE_STEEP_W
64  (1 << DIR_SW), // SLOPE_NE
65  (1 << DIR_S ) | (1 << DIR_SW) | (1 << DIR_SE), // SLOPE_ENW, SLOPE_STEEP_N
66  (1 << DIR_W ) | (1 << DIR_SW) | (1 << DIR_NW), // SLOPE_SEN, SLOPE_STEEP_E
67 };
68 
75 static inline void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
76 {
77  if (IsValidTile(tile) && IsTileType(tile, MP_WATER) && (IsCanal(tile) || IsRiver(tile))) MarkTileDirtyByTile(tile);
78 }
79 
87 {
88  for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
90  }
91 }
92 
98 {
99  for (Direction dir = DIR_BEGIN; dir != DIR_END; dir++) {
100  TileIndex dest = tile + TileOffsByDir(dir);
101  if (IsValidTile(dest) && IsTileType(dest, MP_WATER)) SetNonFloodingWaterTile(dest, false);
102  }
103 }
104 
113 {
114  if (!IsValidAxis(axis)) return CMD_ERROR;
115  TileIndex tile2 = tile + TileOffsByAxis(axis);
116 
117  if (!HasTileWaterGround(tile) || !HasTileWaterGround(tile2)) {
118  return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER);
119  }
120 
121  if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
122 
123  if (!IsTileFlat(tile) || !IsTileFlat(tile2)) {
124  /* Prevent depots on rapids */
125  return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
126  }
127 
128  if (!Depot::CanAllocateItem()) return CMD_ERROR;
129 
130  WaterClass wc1 = GetWaterClass(tile);
131  WaterClass wc2 = GetWaterClass(tile2);
132  CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_DEPOT_SHIP]);
133 
134  bool add_cost = !IsWaterTile(tile);
136  if (ret.Failed()) return ret;
137  if (add_cost) {
138  cost.AddCost(ret);
139  }
140  add_cost = !IsWaterTile(tile2);
141  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags | DC_AUTO, tile2);
142  if (ret.Failed()) return ret;
143  if (add_cost) {
144  cost.AddCost(ret);
145  }
146 
147  if (flags & DC_EXEC) {
148  Depot *depot = new Depot(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 == WATER_CLASS_CANAL && !(HasTileWaterClass(tile) && GetWaterClass(tile) == WATER_CLASS_CANAL && IsTileOwner(tile, _current_company))) new_water_infra++;
156  if (wc2 == WATER_CLASS_CANAL && !(HasTileWaterClass(tile2) && GetWaterClass(tile2) == WATER_CLASS_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, DEPOT_PART_NORTH, axis, wc1);
162  MakeShipDepot(tile2, _current_company, depot->index, DEPOT_PART_SOUTH, axis, wc2);
163  CheckForDockingTile(tile);
164  CheckForDockingTile(tile2);
165  MarkTileDirtyByTile(tile);
166  MarkTileDirtyByTile(tile2);
167  MakeDefaultName(depot);
168  }
169 
170  return cost;
171 }
172 
173 bool IsPossibleDockingTile(Tile t)
174 {
175  assert(IsValidTile(t));
176  switch (GetTileType(t)) {
177  case MP_WATER:
178  if (IsLock(t) && GetLockPart(t) == LOCK_PART_MIDDLE) return false;
179  [[fallthrough]];
180  case MP_RAILWAY:
181  case MP_STATION:
182  case MP_TUNNELBRIDGE:
184 
185  default:
186  return false;
187  }
188 }
189 
196 {
197  for (DiagDirection d = DIAGDIR_BEGIN; d != DIAGDIR_END; d++) {
198  TileIndex tile = t + TileOffsByDiagDir(d);
199  if (!IsValidTile(tile)) continue;
200 
201  if (IsDockTile(tile) && IsDockWaterPart(tile)) {
203  SetDockingTile(t, true);
204  }
205  if (IsTileType(tile, MP_INDUSTRY)) {
207  if (st != nullptr) {
208  st->docking_station.Add(t);
209  SetDockingTile(t, true);
210  }
211  }
212  if (IsTileType(tile, MP_STATION) && IsOilRig(tile)) {
214  SetDockingTile(t, true);
215  }
216  }
217 }
218 
219 void MakeWaterKeepingClass(TileIndex tile, Owner o)
220 {
221  WaterClass wc = GetWaterClass(tile);
222 
223  /* Autoslope might turn an originally canal or river tile into land */
224  auto [slope, z] = GetTileSlopeZ(tile);
225 
226  if (slope != SLOPE_FLAT) {
227  if (wc == WATER_CLASS_CANAL) {
228  /* If we clear the canal, we have to remove it from the infrastructure count as well. */
230  if (c != nullptr) {
231  c->infrastructure.water--;
233  }
234  /* Sloped canals are locks and no natural water remains whatever the slope direction */
235  wc = WATER_CLASS_INVALID;
236  }
237 
238  /* Only river water should be restored on appropriate slopes. Other water would be invalid on slopes */
240  wc = WATER_CLASS_INVALID;
241  }
242  }
243 
244  if (wc == WATER_CLASS_SEA && z > 0) {
245  /* Update company infrastructure count. */
247  if (c != nullptr) {
248  c->infrastructure.water++;
250  }
251 
252  wc = WATER_CLASS_CANAL;
253  }
254 
255  /* Zero map array and terminate animation */
256  DoClearSquare(tile);
257 
258  /* Maybe change to water */
259  switch (wc) {
260  case WATER_CLASS_SEA: MakeSea(tile); break;
261  case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
262  case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break;
263  default: break;
264  }
265 
266  if (wc != WATER_CLASS_INVALID) CheckForDockingTile(tile);
267  MarkTileDirtyByTile(tile);
268 }
269 
270 static CommandCost RemoveShipDepot(TileIndex tile, DoCommandFlag flags)
271 {
272  if (!IsShipDepot(tile)) return CMD_ERROR;
273 
274  CommandCost ret = CheckTileOwnership(tile);
275  if (ret.Failed()) return ret;
276 
277  TileIndex tile2 = GetOtherShipDepotTile(tile);
278 
279  /* do not check for ship on tile when company goes bankrupt */
280  if (!(flags & DC_BANKRUPT)) {
281  ret = EnsureNoVehicleOnGround(tile);
282  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile2);
283  if (ret.Failed()) return ret;
284  }
285 
286  bool do_clear = (flags & DC_FORCE_CLEAR_TILE) != 0;
287 
288  if (flags & DC_EXEC) {
289  delete Depot::GetByTile(tile);
290 
292  if (c != nullptr) {
294  if (do_clear && GetWaterClass(tile) == WATER_CLASS_CANAL) c->infrastructure.water--;
296  }
297 
298  if (!do_clear) MakeWaterKeepingClass(tile, GetTileOwner(tile));
299  MakeWaterKeepingClass(tile2, GetTileOwner(tile2));
300  }
301 
302  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_SHIP]);
303 }
304 
313 {
315 
316  TileIndexDiff delta = TileOffsByDiagDir(dir);
318  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
319  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
320  if (ret.Failed()) return ret;
321 
322  /* middle tile */
323  WaterClass wc_middle = HasTileWaterGround(tile) ? GetWaterClass(tile) : WATER_CLASS_CANAL;
324  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
325  if (ret.Failed()) return ret;
326  cost.AddCost(ret);
327 
328  /* lower tile */
329  if (!IsWaterTile(tile - delta)) {
330  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile - delta);
331  if (ret.Failed()) return ret;
332  cost.AddCost(ret);
333  cost.AddCost(_price[PR_BUILD_CANAL]);
334  }
335  if (!IsTileFlat(tile - delta)) {
336  return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
337  }
338  WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
339 
340  /* upper tile */
341  if (!IsWaterTile(tile + delta)) {
342  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile + delta);
343  if (ret.Failed()) return ret;
344  cost.AddCost(ret);
345  cost.AddCost(_price[PR_BUILD_CANAL]);
346  }
347  if (!IsTileFlat(tile + delta)) {
348  return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
349  }
350  WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
351 
352  if (IsBridgeAbove(tile) || IsBridgeAbove(tile - delta) || IsBridgeAbove(tile + delta)) {
353  return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
354  }
355 
356  if (flags & DC_EXEC) {
357  /* Update company infrastructure counts. */
359  if (c != nullptr) {
360  /* Counts for the water. */
361  if (!IsWaterTile(tile - delta)) c->infrastructure.water++;
362  if (!IsWaterTile(tile + delta)) c->infrastructure.water++;
363  /* Count for the lock itself. */
364  c->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock is three tiles.
366  }
367 
368  MakeLock(tile, _current_company, dir, wc_lower, wc_upper, wc_middle);
369  CheckForDockingTile(tile - delta);
370  CheckForDockingTile(tile + delta);
371  MarkTileDirtyByTile(tile);
372  MarkTileDirtyByTile(tile - delta);
373  MarkTileDirtyByTile(tile + delta);
374  MarkCanalsAndRiversAroundDirty(tile - delta);
375  MarkCanalsAndRiversAroundDirty(tile + delta);
376  InvalidateWaterRegion(tile - delta);
377  InvalidateWaterRegion(tile + delta);
378  }
379  cost.AddCost(_price[PR_BUILD_LOCK]);
380 
381  return cost;
382 }
383 
391 {
392  if (GetTileOwner(tile) != OWNER_NONE) {
393  CommandCost ret = CheckTileOwnership(tile);
394  if (ret.Failed()) return ret;
395  }
396 
398 
399  /* make sure no vehicle is on the tile. */
401  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile + delta);
402  if (ret.Succeeded()) ret = EnsureNoVehicleOnGround(tile - delta);
403  if (ret.Failed()) return ret;
404 
405  if (flags & DC_EXEC) {
406  /* Remove middle part from company infrastructure count. */
408  if (c != nullptr) {
409  c->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // three parts of the lock.
411  }
412 
413  if (GetWaterClass(tile) == WATER_CLASS_RIVER) {
414  MakeRiver(tile, Random());
415  } else {
416  DoClearSquare(tile);
418  }
419  MakeWaterKeepingClass(tile + delta, GetTileOwner(tile + delta));
420  MakeWaterKeepingClass(tile - delta, GetTileOwner(tile - delta));
422  MarkCanalsAndRiversAroundDirty(tile - delta);
423  MarkCanalsAndRiversAroundDirty(tile + delta);
424  }
425 
426  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_LOCK]);
427 }
428 
436 {
438  if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
439 
440  return DoBuildLock(tile, dir, flags);
441 }
442 
444 static bool RiverModifyDesertZone(TileIndex tile, void *)
445 {
447  return false;
448 }
449 
455 {
456  MakeRiver(tile, Random());
457  MarkTileDirtyByTile(tile);
458 
459  /* Remove desert directly around the river tile. */
461 }
462 
472 CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
473 {
474  if (start_tile >= Map::Size() || !IsValidWaterClass(wc)) return CMD_ERROR;
475 
476  /* Outside of the editor you can only build canals, not oceans */
477  if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
478 
480 
481  std::unique_ptr<TileIterator> iter = TileIterator::Create(tile, start_tile, diagonal);
482  for (; *iter != INVALID_TILE; ++(*iter)) {
483  TileIndex current_tile = *iter;
484  CommandCost ret;
485 
486  Slope slope = GetTileSlope(current_tile);
487  if (slope != SLOPE_FLAT && (wc != WATER_CLASS_RIVER || !IsInclinedSlope(slope))) {
488  return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
489  }
490 
491  bool water = IsWaterTile(current_tile);
492 
493  /* Outside the editor, prevent building canals over your own or OWNER_NONE owned canals */
494  if (water && IsCanal(current_tile) && _game_mode != GM_EDITOR && (IsTileOwner(current_tile, _current_company) || IsTileOwner(current_tile, OWNER_NONE))) continue;
495 
496  ret = Command<CMD_LANDSCAPE_CLEAR>::Do(flags, current_tile);
497  if (ret.Failed()) return ret;
498 
499  if (!water) cost.AddCost(ret);
500 
501  if (flags & DC_EXEC) {
502  if (IsTileType(current_tile, MP_WATER) && IsCanal(current_tile)) {
503  Owner owner = GetTileOwner(current_tile);
504  if (Company::IsValidID(owner)) {
505  Company::Get(owner)->infrastructure.water--;
507  }
508  }
509 
510  switch (wc) {
511  case WATER_CLASS_RIVER:
512  MakeRiver(current_tile, Random());
513  if (_game_mode == GM_EDITOR) {
514  TileIndex tile2 = current_tile;
516  }
517  break;
518 
519  case WATER_CLASS_SEA:
520  if (TileHeight(current_tile) == 0) {
521  MakeSea(current_tile);
522  break;
523  }
524  [[fallthrough]];
525 
526  default:
527  MakeCanal(current_tile, _current_company, Random());
529  Company::Get(_current_company)->infrastructure.water++;
531  }
532  break;
533  }
534  MarkTileDirtyByTile(current_tile);
535  MarkCanalsAndRiversAroundDirty(current_tile);
536  CheckForDockingTile(current_tile);
537  }
538 
539  cost.AddCost(_price[PR_BUILD_CANAL]);
540  }
541 
542  if (cost.GetCost() == 0) {
543  return_cmd_error(STR_ERROR_ALREADY_BUILT);
544  } else {
545  return cost;
546  }
547 }
548 
549 
550 static CommandCost ClearTile_Water(TileIndex tile, DoCommandFlag flags)
551 {
552  switch (GetWaterTileType(tile)) {
553  case WATER_TILE_CLEAR: {
554  if (flags & DC_NO_WATER) return_cmd_error(STR_ERROR_CAN_T_BUILD_ON_WATER);
555 
556  Money base_cost = IsCanal(tile) ? _price[PR_CLEAR_CANAL] : _price[PR_CLEAR_WATER];
557  /* Make sure freeform edges are allowed or it's not an edge tile. */
559  !IsInsideMM(TileY(tile), 1, Map::MaxY() - 1))) {
560  return_cmd_error(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP);
561  }
562 
563  /* Make sure no vehicle is on the tile */
565  if (ret.Failed()) return ret;
566 
567  Owner owner = GetTileOwner(tile);
568  if (owner != OWNER_WATER && owner != OWNER_NONE) {
569  ret = CheckTileOwnership(tile);
570  if (ret.Failed()) return ret;
571  }
572 
573  if (flags & DC_EXEC) {
574  if (IsCanal(tile) && Company::IsValidID(owner)) {
575  Company::Get(owner)->infrastructure.water--;
577  }
578  DoClearSquare(tile);
581  }
582 
583  return CommandCost(EXPENSES_CONSTRUCTION, base_cost);
584  }
585 
586  case WATER_TILE_COAST: {
587  Slope slope = GetTileSlope(tile);
588 
589  /* Make sure no vehicle is on the tile */
591  if (ret.Failed()) return ret;
592 
593  if (flags & DC_EXEC) {
594  DoClearSquare(tile);
597  }
598  if (IsSlopeWithOneCornerRaised(slope)) {
599  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_WATER]);
600  } else {
601  return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_ROUGH]);
602  }
603  }
604 
605  case WATER_TILE_LOCK: {
606  static const TileIndexDiffC _lock_tomiddle_offs[][DIAGDIR_END] = {
607  /* NE SE SW NW */
608  { { 0, 0}, {0, 0}, { 0, 0}, {0, 0} }, // LOCK_PART_MIDDLE
609  { {-1, 0}, {0, 1}, { 1, 0}, {0, -1} }, // LOCK_PART_LOWER
610  { { 1, 0}, {0, -1}, {-1, 0}, {0, 1} }, // LOCK_PART_UPPER
611  };
612 
613  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
614  if (_current_company == OWNER_WATER) return CMD_ERROR;
615  /* move to the middle tile.. */
616  return RemoveLock(tile + ToTileIndexDiff(_lock_tomiddle_offs[GetLockPart(tile)][GetLockDirection(tile)]), flags);
617  }
618 
619  case WATER_TILE_DEPOT:
620  if (flags & DC_AUTO) return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
621  return RemoveShipDepot(tile, flags);
622 
623  default:
624  NOT_REACHED();
625  }
626 }
627 
637 {
638  switch (GetTileType(tile)) {
639  case MP_WATER:
640  switch (GetWaterTileType(tile)) {
641  default: NOT_REACHED();
642  case WATER_TILE_DEPOT: case WATER_TILE_CLEAR: return true;
644 
645  case WATER_TILE_COAST:
646  switch (GetTileSlope(tile)) {
647  case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
648  case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
649  case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
650  case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
651  default: return false;
652  }
653  }
654 
655  case MP_RAILWAY:
656  if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
657  assert(IsPlainRail(tile));
658  switch (GetTileSlope(tile)) {
659  case SLOPE_W: return (from == DIR_SE) || (from == DIR_E) || (from == DIR_NE);
660  case SLOPE_S: return (from == DIR_NE) || (from == DIR_N) || (from == DIR_NW);
661  case SLOPE_E: return (from == DIR_NW) || (from == DIR_W) || (from == DIR_SW);
662  case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
663  default: return false;
664  }
665  }
666  return false;
667 
668  case MP_STATION:
669  if (IsOilRig(tile)) {
670  /* Do not draw waterborders inside of industries.
671  * Note: There is no easy way to detect the industry of an oilrig tile. */
672  TileIndex src_tile = tile + TileOffsByDir(from);
673  if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
674  (IsTileType(src_tile, MP_INDUSTRY))) return true;
675 
676  return IsTileOnWater(tile);
677  }
678  return (IsDock(tile) && IsTileFlat(tile)) || IsBuoy(tile);
679 
680  case MP_INDUSTRY: {
681  /* Do not draw waterborders inside of industries.
682  * Note: There is no easy way to detect the industry of an oilrig tile. */
683  TileIndex src_tile = tile + TileOffsByDir(from);
684  if ((IsTileType(src_tile, MP_STATION) && IsOilRig(src_tile)) ||
685  (IsTileType(src_tile, MP_INDUSTRY) && GetIndustryIndex(src_tile) == GetIndustryIndex(tile))) return true;
686 
687  return IsTileOnWater(tile);
688  }
689 
690  case MP_OBJECT: return IsTileOnWater(tile);
691 
693 
694  case MP_VOID: return true; // consider map border as water, esp. for rivers
695 
696  default: return false;
697  }
698 }
699 
707 static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
708 {
709  if (base != SPR_FLAT_WATER_TILE) {
710  /* Only call offset callback if the sprite is NewGRF-provided. */
711  offset = GetCanalSpriteOffset(feature, tile, offset);
712  }
713  DrawGroundSprite(base + offset, PAL_NONE);
714 }
715 
722 static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
723 {
724  CanalFeature feature;
725  SpriteID base = 0;
726  if (canal) {
727  feature = CF_DIKES;
728  base = GetCanalSprite(CF_DIKES, tile);
729  if (base == 0) base = SPR_CANAL_DIKES_BASE;
730  } else {
731  feature = CF_RIVER_EDGE;
732  base = GetCanalSprite(CF_RIVER_EDGE, tile);
733  if (base == 0) return; // Don't draw if no sprites provided.
734  }
735 
736  uint wa;
737 
738  /* determine the edges around with water. */
739  wa = IsWateredTile(TileAddXY(tile, -1, 0), DIR_SW) << 0;
740  wa += IsWateredTile(TileAddXY(tile, 0, 1), DIR_NW) << 1;
741  wa += IsWateredTile(TileAddXY(tile, 1, 0), DIR_NE) << 2;
742  wa += IsWateredTile(TileAddXY(tile, 0, -1), DIR_SE) << 3;
743 
744  if (!(wa & 1)) DrawWaterSprite(base, offset, feature, tile);
745  if (!(wa & 2)) DrawWaterSprite(base, offset + 1, feature, tile);
746  if (!(wa & 4)) DrawWaterSprite(base, offset + 2, feature, tile);
747  if (!(wa & 8)) DrawWaterSprite(base, offset + 3, feature, tile);
748 
749  /* right corner */
750  switch (wa & 0x03) {
751  case 0: DrawWaterSprite(base, offset + 4, feature, tile); break;
752  case 3: if (!IsWateredTile(TileAddXY(tile, -1, 1), DIR_W)) DrawWaterSprite(base, offset + 8, feature, tile); break;
753  }
754 
755  /* bottom corner */
756  switch (wa & 0x06) {
757  case 0: DrawWaterSprite(base, offset + 5, feature, tile); break;
758  case 6: if (!IsWateredTile(TileAddXY(tile, 1, 1), DIR_N)) DrawWaterSprite(base, offset + 9, feature, tile); break;
759  }
760 
761  /* left corner */
762  switch (wa & 0x0C) {
763  case 0: DrawWaterSprite(base, offset + 6, feature, tile); break;
764  case 12: if (!IsWateredTile(TileAddXY(tile, 1, -1), DIR_E)) DrawWaterSprite(base, offset + 10, feature, tile); break;
765  }
766 
767  /* upper corner */
768  switch (wa & 0x09) {
769  case 0: DrawWaterSprite(base, offset + 7, feature, tile); break;
770  case 9: if (!IsWateredTile(TileAddXY(tile, -1, -1), DIR_S)) DrawWaterSprite(base, offset + 11, feature, tile); break;
771  }
772 }
773 
776 {
777  DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
778 }
779 
781 static void DrawCanalWater(TileIndex tile)
782 {
783  SpriteID image = SPR_FLAT_WATER_TILE;
784  if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
785  /* First water slope sprite is flat water. */
786  image = GetCanalSprite(CF_WATERSLOPE, tile);
787  if (image == 0) image = SPR_FLAT_WATER_TILE;
788  }
789  DrawWaterSprite(image, 0, CF_WATERSLOPE, tile);
790 
791  DrawWaterEdges(true, 0, tile);
792 }
793 
794 #include "table/water_land.h"
795 
805 static void DrawWaterTileStruct(const TileInfo *ti, const DrawTileSeqStruct *dtss, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
806 {
807  /* Don't draw if buildings are invisible. */
808  if (IsInvisibilitySet(TO_BUILDINGS)) return;
809 
810  for (; !dtss->IsTerminator(); dtss++) {
811  uint tile_offs = offset + dtss->image.sprite;
812  if (feature < CF_END) tile_offs = GetCanalSpriteOffset(feature, ti->tile, tile_offs);
813  AddSortableSpriteToDraw(base + tile_offs, palette,
814  ti->x + dtss->delta_x, ti->y + dtss->delta_y,
815  dtss->size_x, dtss->size_y,
816  dtss->size_z, ti->z + dtss->delta_z,
818  }
819 }
820 
822 static void DrawWaterLock(const TileInfo *ti)
823 {
824  int part = GetLockPart(ti->tile);
825  const DrawTileSprites &dts = _lock_display_data[part][GetLockDirection(ti->tile)];
826 
827  /* Draw ground sprite. */
828  SpriteID image = dts.ground.sprite;
829 
830  SpriteID water_base = GetCanalSprite(CF_WATERSLOPE, ti->tile);
831  if (water_base == 0) {
832  /* Use default sprites. */
833  water_base = SPR_CANALS_BASE;
834  } else if (HasBit(_water_feature[CF_WATERSLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
835  /* NewGRF supplies a flat sprite as first sprite. */
836  if (image == SPR_FLAT_WATER_TILE) {
837  image = water_base;
838  } else {
839  image++;
840  }
841  }
842 
843  if (image < 5) image += water_base;
844  DrawGroundSprite(image, PAL_NONE);
845 
846  /* Draw structures. */
847  uint zoffs = 0;
848  SpriteID base = GetCanalSprite(CF_LOCKS, ti->tile);
849 
850  if (base == 0) {
851  /* If no custom graphics, use defaults. */
852  base = SPR_LOCK_BASE;
853  uint8_t z_threshold = part == LOCK_PART_UPPER ? 8 : 0;
854  zoffs = ti->z > z_threshold ? 24 : 0;
855  }
856 
857  DrawWaterTileStruct(ti, dts.seq, base, zoffs, PAL_NONE, CF_LOCKS);
858 }
859 
861 static void DrawWaterDepot(const TileInfo *ti)
862 {
863  DrawWaterClassGround(ti);
864  DrawWaterTileStruct(ti, _shipdepot_display_data[GetShipDepotAxis(ti->tile)][GetShipDepotPart(ti->tile)].seq, 0, 0, COMPANY_SPRITE_COLOUR(GetTileOwner(ti->tile)), CF_END);
865 }
866 
867 static void DrawRiverWater(const TileInfo *ti)
868 {
869  SpriteID image = SPR_FLAT_WATER_TILE;
870  uint offset = 0;
871  uint edges_offset = 0;
872 
873  if (ti->tileh != SLOPE_FLAT || HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE)) {
874  image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
875  if (image == 0) {
876  switch (ti->tileh) {
877  case SLOPE_NW: image = SPR_WATER_SLOPE_Y_DOWN; break;
878  case SLOPE_SW: image = SPR_WATER_SLOPE_X_UP; break;
879  case SLOPE_SE: image = SPR_WATER_SLOPE_Y_UP; break;
880  case SLOPE_NE: image = SPR_WATER_SLOPE_X_DOWN; break;
881  default: image = SPR_FLAT_WATER_TILE; break;
882  }
883  } else {
884  /* Flag bit 0 indicates that the first sprite is flat water. */
885  offset = HasBit(_water_feature[CF_RIVER_SLOPE].flags, CFF_HAS_FLAT_SPRITE) ? 1 : 0;
886 
887  switch (ti->tileh) {
888  case SLOPE_SE: edges_offset += 12; break;
889  case SLOPE_NE: offset += 1; edges_offset += 24; break;
890  case SLOPE_SW: offset += 2; edges_offset += 36; break;
891  case SLOPE_NW: offset += 3; edges_offset += 48; break;
892  default: offset = 0; break;
893  }
894 
895  offset = GetCanalSpriteOffset(CF_RIVER_SLOPE, ti->tile, offset);
896  }
897  }
898 
899  DrawGroundSprite(image + offset, PAL_NONE);
900 
901  /* Draw river edges if available. */
902  DrawWaterEdges(false, edges_offset, ti->tile);
903 }
904 
905 void DrawShoreTile(Slope tileh)
906 {
907  /* Converts the enum Slope into an offset based on SPR_SHORE_BASE.
908  * This allows to calculate the proper sprite to display for this Slope */
909  static const uint8_t tileh_to_shoresprite[32] = {
910  0, 1, 2, 3, 4, 16, 6, 7, 8, 9, 17, 11, 12, 13, 14, 0,
911  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 10, 15, 0,
912  };
913 
914  assert(!IsHalftileSlope(tileh)); // Halftile slopes need to get handled earlier.
915  assert(tileh != SLOPE_FLAT); // Shore is never flat
916 
917  assert((tileh != SLOPE_EW) && (tileh != SLOPE_NS)); // No suitable sprites for current flooding behaviour
918 
919  DrawGroundSprite(SPR_SHORE_BASE + tileh_to_shoresprite[tileh], PAL_NONE);
920 }
921 
922 void DrawWaterClassGround(const TileInfo *ti)
923 {
924  switch (GetWaterClass(ti->tile)) {
925  case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break;
926  case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break;
927  case WATER_CLASS_RIVER: DrawRiverWater(ti); break;
928  default: NOT_REACHED();
929  }
930 }
931 
932 static void DrawTile_Water(TileInfo *ti)
933 {
934  switch (GetWaterTileType(ti->tile)) {
935  case WATER_TILE_CLEAR:
936  DrawWaterClassGround(ti);
937  DrawBridgeMiddle(ti);
938  break;
939 
940  case WATER_TILE_COAST: {
941  DrawShoreTile(ti->tileh);
942  DrawBridgeMiddle(ti);
943  break;
944  }
945 
946  case WATER_TILE_LOCK:
947  DrawWaterLock(ti);
948  break;
949 
950  case WATER_TILE_DEPOT:
951  DrawWaterDepot(ti);
952  break;
953  }
954 }
955 
956 void DrawShipDepotSprite(int x, int y, Axis axis, DepotPart part)
957 {
958  const DrawTileSprites &dts = _shipdepot_display_data[axis][part];
959 
960  DrawSprite(dts.ground.sprite, dts.ground.pal, x, y);
961  DrawOrigTileSeqInGUI(x, y, &dts, COMPANY_SPRITE_COLOUR(_local_company));
962 }
963 
964 
965 static int GetSlopePixelZ_Water(TileIndex tile, uint x, uint y, bool)
966 {
967  auto [tileh, z] = GetTilePixelSlope(tile);
968 
969  return z + GetPartialPixelZ(x & 0xF, y & 0xF, tileh);
970 }
971 
972 static Foundation GetFoundation_Water(TileIndex, Slope)
973 {
974  return FOUNDATION_NONE;
975 }
976 
977 static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
978 {
979  switch (GetWaterTileType(tile)) {
980  case WATER_TILE_CLEAR:
981  switch (GetWaterClass(tile)) {
982  case WATER_CLASS_SEA: td->str = STR_LAI_WATER_DESCRIPTION_WATER; break;
983  case WATER_CLASS_CANAL: td->str = STR_LAI_WATER_DESCRIPTION_CANAL; break;
984  case WATER_CLASS_RIVER: td->str = STR_LAI_WATER_DESCRIPTION_RIVER; break;
985  default: NOT_REACHED();
986  }
987  break;
988  case WATER_TILE_COAST: td->str = STR_LAI_WATER_DESCRIPTION_COAST_OR_RIVERBANK; break;
989  case WATER_TILE_LOCK : td->str = STR_LAI_WATER_DESCRIPTION_LOCK; break;
990  case WATER_TILE_DEPOT:
991  td->str = STR_LAI_WATER_DESCRIPTION_SHIP_DEPOT;
992  td->build_date = Depot::GetByTile(tile)->build_date;
993  break;
994  default: NOT_REACHED();
995  }
996 
997  td->owner[0] = GetTileOwner(tile);
998 }
999 
1005 static void FloodVehicle(Vehicle *v)
1006 {
1007  uint victims = v->Crash(true);
1008 
1009  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
1010  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED, victims));
1011  SetDParam(0, victims);
1012  AddTileNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NT_ACCIDENT, v->tile);
1014  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1015 }
1016 
1023 static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
1024 {
1025  if ((v->vehstatus & VS_CRASHED) != 0) return nullptr;
1026 
1027  switch (v->type) {
1028  default: break;
1029 
1030  case VEH_AIRCRAFT: {
1031  if (!IsAirportTile(v->tile) || GetTileMaxZ(v->tile) != 0) break;
1032  if (v->subtype == AIR_SHADOW) break;
1033 
1034  /* We compare v->z_pos against delta_z + 1 because the shadow
1035  * is at delta_z and the actual aircraft at delta_z + 1. */
1036  const Station *st = Station::GetByTile(v->tile);
1037  const AirportFTAClass *airport = st->airport.GetFTA();
1038  if (v->z_pos != airport->delta_z + 1) break;
1039 
1040  FloodVehicle(v);
1041  break;
1042  }
1043 
1044  case VEH_TRAIN:
1045  case VEH_ROAD: {
1046  int z = *(int*)data;
1047  if (v->z_pos > z) break;
1048  FloodVehicle(v->First());
1049  break;
1050  }
1051  }
1052 
1053  return nullptr;
1054 }
1055 
1061 static void FloodVehicles(TileIndex tile)
1062 {
1063  int z = 0;
1064 
1065  if (IsAirportTile(tile)) {
1066  const Station *st = Station::GetByTile(tile);
1067  for (TileIndex airport_tile : st->airport) {
1068  if (st->TileBelongsToAirport(airport_tile)) FindVehicleOnPos(airport_tile, &z, &FloodVehicleProc);
1069  }
1070 
1071  /* No vehicle could be flooded on this airport anymore */
1072  return;
1073  }
1074 
1075  if (!IsBridgeTile(tile)) {
1076  FindVehicleOnPos(tile, &z, &FloodVehicleProc);
1077  return;
1078  }
1079 
1080  TileIndex end = GetOtherBridgeEnd(tile);
1081  z = GetBridgePixelHeight(tile);
1082 
1083  FindVehicleOnPos(tile, &z, &FloodVehicleProc);
1085 }
1086 
1093 {
1094  /* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs
1095  * FLOOD_DRYUP: coast with more than one corner raised, coast with rail-track, coast with trees
1096  * FLOOD_PASSIVE: (not used)
1097  * FLOOD_NONE: canals, rivers, everything else
1098  */
1099  switch (GetTileType(tile)) {
1100  case MP_WATER:
1101  if (IsCoast(tile)) {
1102  Slope tileh = GetTileSlope(tile);
1104  }
1105  [[fallthrough]];
1106  case MP_STATION:
1107  case MP_INDUSTRY:
1108  case MP_OBJECT:
1109  return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
1110 
1111  case MP_RAILWAY:
1112  if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
1114  }
1115  return FLOOD_NONE;
1116 
1117  case MP_TREES:
1118  return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
1119 
1120  case MP_VOID:
1121  return FLOOD_ACTIVE;
1122 
1123  default:
1124  return FLOOD_NONE;
1125  }
1126 }
1127 
1131 static void DoFloodTile(TileIndex target)
1132 {
1133  assert(!IsTileType(target, MP_WATER));
1134 
1135  bool flooded = false; // Will be set to true if something is changed.
1136 
1138 
1139  Slope tileh = GetTileSlope(target);
1140  if (tileh != SLOPE_FLAT) {
1141  /* make coast.. */
1142  switch (GetTileType(target)) {
1143  case MP_RAILWAY: {
1144  if (!IsPlainRail(target)) break;
1145  FloodVehicles(target);
1146  flooded = FloodHalftile(target);
1147  break;
1148  }
1149 
1150  case MP_TREES:
1151  if (!IsSlopeWithOneCornerRaised(tileh)) {
1153  MarkTileDirtyByTile(target);
1154  flooded = true;
1155  break;
1156  }
1157  [[fallthrough]];
1158 
1159  case MP_CLEAR:
1160  if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC, target).Succeeded()) {
1161  MakeShore(target);
1162  MarkTileDirtyByTile(target);
1163  flooded = true;
1164  }
1165  break;
1166 
1167  default:
1168  break;
1169  }
1170  } else {
1171  /* Flood vehicles */
1172  FloodVehicles(target);
1173 
1174  /* flood flat tile */
1175  if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC, target).Succeeded()) {
1176  MakeSea(target);
1177  MarkTileDirtyByTile(target);
1178  flooded = true;
1179  }
1180  }
1181 
1182  if (flooded) {
1183  /* Mark surrounding canal tiles dirty too to avoid glitches */
1185 
1186  /* update signals if needed */
1188 
1189  if (IsPossibleDockingTile(target)) CheckForDockingTile(target);
1190  }
1191 
1192  cur_company.Restore();
1193 }
1194 
1198 static void DoDryUp(TileIndex tile)
1199 {
1201 
1202  switch (GetTileType(tile)) {
1203  case MP_RAILWAY:
1204  assert(IsPlainRail(tile));
1205  assert(GetRailGroundType(tile) == RAIL_GROUND_WATER);
1206 
1207  RailGroundType new_ground;
1208  switch (GetTrackBits(tile)) {
1209  case TRACK_BIT_UPPER: new_ground = RAIL_GROUND_FENCE_HORIZ1; break;
1210  case TRACK_BIT_LOWER: new_ground = RAIL_GROUND_FENCE_HORIZ2; break;
1211  case TRACK_BIT_LEFT: new_ground = RAIL_GROUND_FENCE_VERT1; break;
1212  case TRACK_BIT_RIGHT: new_ground = RAIL_GROUND_FENCE_VERT2; break;
1213  default: NOT_REACHED();
1214  }
1215  SetRailGroundType(tile, new_ground);
1216  MarkTileDirtyByTile(tile);
1217  break;
1218 
1219  case MP_TREES:
1221  MarkTileDirtyByTile(tile);
1222  break;
1223 
1224  case MP_WATER:
1225  assert(IsCoast(tile));
1226 
1227  if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_EXEC, tile).Succeeded()) {
1228  MakeClear(tile, CLEAR_GRASS, 3);
1229  MarkTileDirtyByTile(tile);
1230  }
1231  break;
1232 
1233  default: NOT_REACHED();
1234  }
1235 
1236  cur_company.Restore();
1237 }
1238 
1246 {
1247  if (IsTileType(tile, MP_WATER)) {
1248  AmbientSoundEffect(tile);
1249  if (IsNonFloodingWaterTile(tile)) return;
1250  }
1251 
1252  switch (GetFloodingBehaviour(tile)) {
1253  case FLOOD_ACTIVE: {
1254  bool continue_flooding = false;
1255  for (Direction dir = DIR_BEGIN; dir < DIR_END; dir++) {
1257  /* Contrary to drying up, flooding does not consider MP_VOID tiles. */
1258  if (!IsValidTile(dest)) continue;
1259  /* do not try to flood water tiles - increases performance a lot */
1260  if (IsTileType(dest, MP_WATER)) continue;
1261 
1262  /* Buoys and docks cannot be flooded, and when removed turn into flooding water. */
1263  if (IsTileType(dest, MP_STATION) && (IsBuoy(dest) || IsDock(dest))) continue;
1264 
1265  /* This neighbour tile might be floodable later if the tile is cleared, so allow flooding to continue. */
1266  continue_flooding = true;
1267 
1268  /* TREE_GROUND_SHORE is the sign of a previous flood. */
1269  if (IsTileType(dest, MP_TREES) && GetTreeGround(dest) == TREE_GROUND_SHORE) continue;
1270 
1271  auto [slope_dest, z_dest] = GetFoundationSlope(dest);
1272  if (z_dest > 0) continue;
1273 
1274  if (!HasBit(_flood_from_dirs[slope_dest & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP], ReverseDir(dir))) continue;
1275 
1276  DoFloodTile(dest);
1277  }
1278  if (!continue_flooding && IsTileType(tile, MP_WATER)) SetNonFloodingWaterTile(tile, true);
1279  break;
1280  }
1281 
1282  case FLOOD_DRYUP: {
1283  Slope slope_here = std::get<0>(GetFoundationSlope(tile)) & ~SLOPE_HALFTILE_MASK & ~SLOPE_STEEP;
1284  for (Direction dir : SetBitIterator<Direction>(_flood_from_dirs[slope_here])) {
1286  /* Contrary to flooding, drying up does consider MP_VOID tiles. */
1287  if (dest == INVALID_TILE) continue;
1288 
1289  FloodingBehaviour dest_behaviour = GetFloodingBehaviour(dest);
1290  if ((dest_behaviour == FLOOD_ACTIVE) || (dest_behaviour == FLOOD_PASSIVE)) return;
1291  }
1292  DoDryUp(tile);
1293  break;
1294  }
1295 
1296  default: return;
1297  }
1298 }
1299 
1300 void ConvertGroundTilesIntoWaterTiles()
1301 {
1302  for (TileIndex tile = 0; tile < Map::Size(); ++tile) {
1303  auto [slope, z] = GetTileSlopeZ(tile);
1304  if (IsTileType(tile, MP_CLEAR) && z == 0) {
1305  /* Make both water for tiles at level 0
1306  * and make shore, as that looks much better
1307  * during the generation. */
1308  switch (slope) {
1309  case SLOPE_FLAT:
1310  MakeSea(tile);
1311  break;
1312 
1313  case SLOPE_N:
1314  case SLOPE_E:
1315  case SLOPE_S:
1316  case SLOPE_W:
1317  MakeShore(tile);
1318  break;
1319 
1320  default:
1322  TileIndex dest = TileAddByDir(tile, dir);
1323  Slope slope_dest = GetTileSlope(dest) & ~SLOPE_STEEP;
1324  if (slope_dest == SLOPE_FLAT || IsSlopeWithOneCornerRaised(slope_dest) || IsTileType(dest, MP_VOID)) {
1325  MakeShore(tile);
1326  break;
1327  }
1328  }
1329  break;
1330  }
1331  }
1332  }
1333 }
1334 
1335 static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, uint, DiagDirection)
1336 {
1339 
1340  TrackBits ts;
1341 
1342  if (mode != TRANSPORT_WATER) return 0;
1343 
1344  switch (GetWaterTileType(tile)) {
1345  case WATER_TILE_CLEAR: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
1346  case WATER_TILE_COAST: ts = coast_tracks[GetTileSlope(tile) & 0xF]; break;
1347  case WATER_TILE_LOCK: ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break;
1348  case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
1349  default: return 0;
1350  }
1351  if (TileX(tile) == 0) {
1352  /* NE border: remove tracks that connects NE tile edge */
1354  }
1355  if (TileY(tile) == 0) {
1356  /* NW border: remove tracks that connects NW tile edge */
1358  }
1360 }
1361 
1362 static bool ClickTile_Water(TileIndex tile)
1363 {
1364  if (GetWaterTileType(tile) == WATER_TILE_DEPOT) {
1366  return true;
1367  }
1368  return false;
1369 }
1370 
1371 static void ChangeTileOwner_Water(TileIndex tile, Owner old_owner, Owner new_owner)
1372 {
1373  if (!IsTileOwner(tile, old_owner)) return;
1374 
1375  bool is_lock_middle = IsLock(tile) && GetLockPart(tile) == LOCK_PART_MIDDLE;
1376 
1377  /* No need to dirty company windows here, we'll redraw the whole screen anyway. */
1378  if (is_lock_middle) Company::Get(old_owner)->infrastructure.water -= 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1379  if (new_owner != INVALID_OWNER) {
1380  if (is_lock_middle) Company::Get(new_owner)->infrastructure.water += 3 * LOCK_DEPOT_TILE_FACTOR; // Lock has three parts.
1381  /* Only subtract from the old owner here if the new owner is valid,
1382  * otherwise we clear ship depots and canal water below. */
1383  if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) {
1384  Company::Get(old_owner)->infrastructure.water--;
1385  Company::Get(new_owner)->infrastructure.water++;
1386  }
1387  if (IsShipDepot(tile)) {
1388  Company::Get(old_owner)->infrastructure.water -= LOCK_DEPOT_TILE_FACTOR;
1389  Company::Get(new_owner)->infrastructure.water += LOCK_DEPOT_TILE_FACTOR;
1390  }
1391 
1392  SetTileOwner(tile, new_owner);
1393  return;
1394  }
1395 
1396  /* Remove depot */
1398 
1399  /* Set owner of canals and locks ... and also canal under dock there was before.
1400  * Check if the new owner after removing depot isn't OWNER_WATER. */
1401  if (IsTileOwner(tile, old_owner)) {
1402  if (GetWaterClass(tile) == WATER_CLASS_CANAL && !is_lock_middle) Company::Get(old_owner)->infrastructure.water--;
1403  SetTileOwner(tile, OWNER_NONE);
1404  }
1405 }
1406 
1407 static VehicleEnterTileStatus VehicleEnter_Water(Vehicle *, TileIndex, int, int)
1408 {
1409  return VETSB_CONTINUE;
1410 }
1411 
1412 static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlag flags, int, Slope)
1413 {
1414  /* Canals can't be terraformed */
1415  if (IsWaterTile(tile) && IsCanal(tile)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_CANAL_FIRST);
1416 
1417  return Command<CMD_LANDSCAPE_CLEAR>::Do(flags, tile);
1418 }
1419 
1420 
1421 extern const TileTypeProcs _tile_type_water_procs = {
1422  DrawTile_Water, // draw_tile_proc
1423  GetSlopePixelZ_Water, // get_slope_z_proc
1424  ClearTile_Water, // clear_tile_proc
1425  nullptr, // add_accepted_cargo_proc
1426  GetTileDesc_Water, // get_tile_desc_proc
1427  GetTileTrackStatus_Water, // get_tile_track_status_proc
1428  ClickTile_Water, // click_tile_proc
1429  nullptr, // animate_tile_proc
1430  TileLoop_Water, // tile_loop_proc
1431  ChangeTileOwner_Water, // change_tile_owner_proc
1432  nullptr, // add_produced_cargo_proc
1433  VehicleEnter_Water, // vehicle_enter_tile_proc
1434  GetFoundation_Water, // get_foundation_proc
1435  TerraformTile_Water, // terraform_tile_proc
1436 };
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 debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
void DrawBridgeMiddle(const TileInfo *ti)
Draw the middle bits of a bridge.
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
Definition: bridge_map.cpp:59
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:243
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:63
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:146
static std::unique_ptr< TileIterator > Create(TileIndex corner1, TileIndex corner2, bool diagonal)
Create either an OrthogonalTileIterator or DiagonalTileIterator given the diagonal parameter.
Definition: tilearea.cpp:291
Wrapper class to abstract away the way the tiles are stored.
Definition: map_func.h:25
static Date date
Current date in days (day counter).
Map accessors for 'clear' tiles.
@ CLEAR_GRASS
0-3
Definition: clear_map.h:20
void MakeClear(Tile t, ClearGround g, uint density)
Make a clear tile.
Definition: clear_map.h:259
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_AUTO
don't allow building on structures
Definition: command_type.h:377
@ DC_FORCE_CLEAR_TILE
do not only remove the object on the tile, but also clear any water left on it
Definition: command_type.h:387
@ DC_NO_WATER
don't allow building on water
Definition: command_type.h:379
@ DC_BANKRUPT
company bankrupts, skip money check, skip vehicle on tile check in some cases
Definition: command_type.h:382
@ DC_EXEC
execute the given command
Definition: command_type.h:376
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.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:52
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
void DirtyCompanyInfrastructureWindows(CompanyID company)
Redraw all windows with company infrastructure counts.
GUI Functions related to companies.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ INVALID_OWNER
An invalid owner.
Definition: company_type.h:29
@ OWNER_NONE
The tile has no ownership.
Definition: company_type.h:25
@ OWNER_WATER
The tile/execution is done by "water".
Definition: company_type.h:26
Base for all depots (except hangars)
Functions related to depots.
void ShowDepotWindow(TileIndex tile, VehicleType type)
Opens a depot window.
Definition: depot_gui.cpp:1164
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.
Axis
Allow incrementing of DiagDirDiff variables.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
static const uint LOCK_DEPOT_TILE_FACTOR
Multiplier for how many regular tiles a lock counts.
Definition: economy_type.h:249
@ EXPENSES_CONSTRUCTION
Construction costs.
Definition: economy_type.h:173
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.
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:988
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:18
uint32_t PaletteID
The number of the palette.
Definition: gfx_type.h:19
static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
Marks the tiles around a tile as dirty, if they are canals or rivers.
Definition: water_cmd.cpp:86
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition: viewport.cpp:2057
Base of all industries.
Accessors for industries.
IndustryID GetIndustryIndex(Tile t)
Get the industry ID of the given tile.
Definition: industry_map.h:63
uint GetPartialPixelZ(int x, int y, Slope corners)
Determines height at given coordinate of a slope.
Definition: landscape.cpp:228
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
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,...
Definition: landscape.cpp:382
Functions related to OTTD's landscape.
Command definitions related to landscape (slopes etc.).
bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, void *user_data)
Function performing a search around a center tile and going outward, thus in circle.
Definition: map.cpp:247
TileIndex TileAddXY(TileIndex tile, int x, int y)
Adds a given offset to a tile.
Definition: map_func.h:467
TileIndex AddTileIndexDiffCWrap(TileIndex tile, TileIndexDiffC diff)
Add a TileIndexDiffC to a TileIndex and returns the new one.
Definition: map_func.h:512
TileIndex TileAddByDir(TileIndex tile, Direction dir)
Adds a Direction to a tile.
Definition: map_func.h:596
TileIndexDiff ToTileIndexDiff(TileIndexDiffC tidc)
Return the offset between two tiles from a TileIndexDiffC struct.
Definition: map_func.h:440
TileIndexDiff TileOffsByAxis(Axis axis)
Convert an Axis to a TileIndexDiff.
Definition: map_func.h:552
TileIndexDiffC TileIndexDiffCByDir(Direction dir)
Returns the TileIndexDiffC offset from a Direction.
Definition: map_func.h:494
TileIndexDiff TileOffsByDir(Direction dir)
Convert a Direction to a TileIndexDiff.
Definition: map_func.h:581
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
int32_t TileIndexDiff
An offset value between two tiles.
Definition: map_type.h:23
constexpr bool IsInsideMM(const T x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition: math_func.hpp:268
CanalFeature
List of different canal 'features'.
Definition: newgrf.h:26
uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
Get the new sprite offset for a water tile.
WaterFeature _water_feature[CF_END]
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.
Definition: newgrf_canal.h:18
Functions related to generic callbacks.
void AmbientSoundEffect(TileIndex tile)
Play an ambient sound effect for an empty tile.
Functions related to news.
@ NT_ACCIDENT
An accident or disaster has occurred.
Definition: news_type.h:26
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:762
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:485
@ RAIL_GROUND_FENCE_HORIZ1
Grass with a fence at the southern side.
Definition: rail_map.h:496
@ RAIL_GROUND_FENCE_VERT1
Grass with a fence at the eastern side.
Definition: rail_map.h:494
@ RAIL_GROUND_FENCE_HORIZ2
Grass with a fence at the northern side.
Definition: rail_map.h:497
@ RAIL_GROUND_WATER
Grass with a fence and shore or water on the free halftile.
Definition: rail_map.h:499
@ RAIL_GROUND_FENCE_VERT2
Grass with a fence at the western side.
Definition: rail_map.h:495
static debug_inline bool IsPlainRail(Tile t)
Returns whether this is plain rails, with or without signals.
Definition: rail_map.h:49
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:57
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:56
static SigSegState UpdateSignalsInBuffer(Owner owner)
Updates blocks in _globset buffer.
Definition: signal.cpp:482
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:48
@ SLOPE_W
the west corner of the tile is raised
Definition: slope_type.h:50
@ SLOPE_HALFTILE_MASK
three bits used for halftile slopes
Definition: slope_type.h:72
@ SLOPE_NS
north and south corner are raised
Definition: slope_type.h:60
@ SLOPE_E
the east corner of the tile is raised
Definition: slope_type.h:52
@ SLOPE_S
the south corner of the tile is raised
Definition: slope_type.h:51
@ SLOPE_N
the north corner of the tile is raised
Definition: slope_type.h:53
@ SLOPE_SW
south and west corner are raised
Definition: slope_type.h:56
@ SLOPE_FLAT
a flat tile
Definition: slope_type.h:49
@ SLOPE_NE
north and east corner are raised
Definition: slope_type.h:58
@ SLOPE_SE
south and east corner are raised
Definition: slope_type.h:57
@ SLOPE_NW
north and west corner are raised
Definition: slope_type.h:55
@ SLOPE_EW
east and west corner are raised
Definition: slope_type.h:59
@ SLOPE_STEEP
indicates the slope is steep
Definition: slope_type.h:54
Foundation
Enumeration for Foundations.
Definition: slope_type.h:93
@ FOUNDATION_NONE
The tile has no foundation, the slope remains unchanged.
Definition: slope_type.h:94
Functions related to sound.
@ SND_12_EXPLOSION
16 == 0x10 Destruction, crashes, disasters, ...
Definition: sound_type.h:55
void DrawOrigTileSeqInGUI(int x, int y, const DrawTileSprites *dts, PaletteID default_palette)
Draw TTD sprite sequence in GUI.
Definition: sprite.h:115
static const SpriteID SPR_SHORE_BASE
shore tiles - action 05-0D
Definition: sprites.h:224
Base classes/functions for stations.
bool IsAirportTile(Tile t)
Is this tile a station tile and an airport tile?
Definition: station_map.h:167
bool IsBuoy(Tile t)
Is tile t a buoy tile?
Definition: station_map.h:400
bool IsDockTile(Tile t)
Is tile t a dock tile?
Definition: station_map.h:389
bool IsOilRig(Tile t)
Is tile t part of an oilrig?
Definition: station_map.h:368
bool IsDockWaterPart(Tile t)
Check whether a dock tile is the tile on water.
Definition: station_map.h:605
bool IsDock(Tile t)
Is tile t a dock tile?
Definition: station_map.h:379
Definition of base types and functions in a cross-platform compatible way.
void SetDParam(size_t n, uint64_t v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings.cpp:104
Functions related to OTTD's strings.
Finite sTate mAchine (FTA) of an airport.
Definition: airport.h:143
uint8_t delta_z
Z adjustment for helicopter pads.
Definition: airport.h:183
const AirportFTAClass * GetFTA() const
Get the finite-state machine for this airport or the finite-state machine for the dummy airport in ca...
Definition: station_base.h:317
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:21
void Restore()
Restore the variable.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
SoundSettings sound
sound effect settings
uint32_t water
Count of company owned track bits for canals.
Definition: company_base.h:36
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:147
bool freeform_edges
allow terraforming the tiles at the map edges
TimerGameCalendar::Date build_date
Date of construction.
Definition: depot_base.h:26
A tile child sprite and palette to draw for stations etc, with 3D bounding box.
Definition: sprite.h:25
int8_t delta_z
0x80 identifies child sprites
Definition: sprite.h:28
bool IsTerminator() const
Check whether this is a sequence terminator.
Definition: sprite.h:41
int8_t delta_x
0x80 is sequence terminator
Definition: sprite.h:26
Ground palette sprite of a tile, together with its sprite layout.
Definition: sprite.h:58
const DrawTileSeqStruct * seq
Array of child sprites. Terminated with a terminator entry.
Definition: sprite.h:60
PalSpriteID ground
Palette and sprite for the ground.
Definition: sprite.h:59
ConstructionSettings construction
construction of things in-game
static Industry * GetByTile(TileIndex tile)
Get the industry of the given tile.
Definition: industry.h:238
Station * neutral_station
Associated neutral station.
Definition: industry.h:96
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:306
static debug_inline uint Size()
Get the size of the map.
Definition: map_func.h:288
static debug_inline uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:297
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:24
PaletteID pal
The palette (use PAL_NONE) if not needed)
Definition: gfx_type.h:25
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
Iterable ensemble of each set bit in a value.
bool disaster
Play disaster and accident sounds.
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
Station data structure.
Definition: station_base.h:439
TileArea docking_station
Tile area the docking tiles cover.
Definition: station_base.h:455
Airport airport
Tile area the airport covers.
Definition: station_base.h:453
Tile description for the 'land area information' tool.
Definition: tile_cmd.h:52
StringID str
Description of the tile.
Definition: tile_cmd.h:53
TimerGameCalendar::Date build_date
Date of construction of tile contents.
Definition: tile_cmd.h:57
Owner owner[4]
Name of the owner(s)
Definition: tile_cmd.h:55
A pair-construct of a TileIndexDiff.
Definition: map_type.h:31
Tile information, used while rendering the tile.
Definition: tile_cmd.h:43
int z
Height.
Definition: tile_cmd.h:48
int x
X position of the tile in unit coordinates.
Definition: tile_cmd.h:44
Slope tileh
Slope of the tile.
Definition: tile_cmd.h:46
TileIndex tile
Tile index.
Definition: tile_cmd.h:47
int y
Y position of the tile in unit coordinates.
Definition: tile_cmd.h:45
Set of callback functions for performing tile operations of a given tile type.
Definition: tile_cmd.h:158
Vehicle data structure.
Definition: vehicle_base.h:244
int32_t z_pos
z coordinate.
Definition: vehicle_base.h:306
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition: vehicle.cpp:280
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
uint8_t subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:355
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:309
VehicleEnterTileStatus
The returned bits of VehicleEnterTile.
Definition: tile_cmd.h:21
@ VETSB_CONTINUE
Bit sets of the above specified bits.
Definition: tile_cmd.h:35
bool IsTileFlat(TileIndex tile, int *h)
Check if a given tile is flat.
Definition: tile_map.cpp:95
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:136
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
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition: tile_map.h:96
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
std::tuple< Slope, int > GetTilePixelSlope(TileIndex tile)
Return the slope of a given tile.
Definition: tile_map.h:289
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
Slope GetTileSlope(TileIndex tile)
Return the slope of a given tile inside the map.
Definition: tile_map.h:279
void SetTropicZone(Tile tile, TropicZone type)
Set the tropic zone.
Definition: tile_map.h:225
static debug_inline uint TileHeight(Tile tile)
Returns the height of a tile.
Definition: tile_map.h:29
@ TROPICZONE_DESERT
Tile is desert.
Definition: tile_type.h:78
@ TROPICZONE_NORMAL
Normal tropiczone.
Definition: tile_type.h:77
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
@ MP_TREES
Tile got trees.
Definition: tile_type.h:52
@ MP_STATION
A tile of a station.
Definition: tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
@ MP_CLEAR
A tile without any structures, i.e. grass, rocks, farm fields etc.
Definition: tile_type.h:48
@ MP_WATER
Water tile.
Definition: tile_type.h:54
@ MP_RAILWAY
A railway.
Definition: tile_type.h:49
@ MP_INDUSTRY
Part of an industry.
Definition: tile_type.h:56
@ MP_VOID
Invisible tiles at the SW and SE border.
Definition: tile_type.h:55
@ MP_OBJECT
Contains objects such as transmitters and owned land.
Definition: tile_type.h:58
Definition of the game-calendar-timer.
Base of the town class.
void MakeDefaultName(T *obj)
Set the default name for a depot/waypoint.
Definition: town.h:253
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:388
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:524
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition: track_func.h:363
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:99
@ TO_BUILDINGS
company buildings - depots, stations, HQ, ...
Definition: transparency.h:27
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...
Definition: transparency.h:48
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...
Definition: transparency.h:59
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
@ TREE_GROUND_GRASS
normal grass
Definition: tree_map.h:53
@ TREE_GROUND_SHORE
shore
Definition: tree_map.h:56
void SetTreeGroundDensity(Tile t, TreeGround g, uint d)
Set the density and ground type of a tile with trees.
Definition: tree_map.h:144
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:546
void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Find a vehicle from a specific location.
Definition: vehicle.cpp:505
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
Functions related to vehicles.
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, int h, int dz, int z, bool transparent, int bb_offset_x, int bb_offset_y, int bb_offset_z, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition: viewport.cpp:671
void DrawGroundSprite(SpriteID image, PaletteID pal, const SubSprite *sub, int extra_offs_x, int extra_offs_y)
Draws a ground sprite for the current tile.
Definition: viewport.cpp:587
Functions related to (drawing on) viewports.
Functions related to water (management)
static const uint RIVER_OFFSET_DESERT_DISTANCE
Circular tile search radius to create non-desert around a river tile.
Definition: water.h:42
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
void TileLoop_Water(TileIndex tile)
Let a water tile floods its diagonal adjoining tiles called from tunnelbridge_cmd,...
Definition: water_cmd.cpp:1245
static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlag flags)
Builds a lock.
Definition: water_cmd.cpp:312
static void DrawWaterDepot(const TileInfo *ti)
Draw a ship depot tile.
Definition: water_cmd.cpp:861
static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
Remove a lock.
Definition: water_cmd.cpp:390
static void DrawWaterSprite(SpriteID base, uint offset, CanalFeature feature, TileIndex tile)
Draw a water sprite, potentially with a NewGRF-modified sprite offset.
Definition: water_cmd.cpp:707
static void DrawWaterLock(const TileInfo *ti)
Draw a lock tile.
Definition: water_cmd.cpp:822
static bool RiverModifyDesertZone(TileIndex tile, void *)
Callback to create non-desert around a river tile.
Definition: water_cmd.cpp:444
static void FloodVehicle(Vehicle *v)
Handle the flooding of a vehicle.
Definition: water_cmd.cpp:1005
static void FloodVehicles(TileIndex tile)
Finds a vehicle to flood.
Definition: water_cmd.cpp:1061
static void DrawWaterEdges(bool canal, uint offset, TileIndex tile)
Draw canal or river edges.
Definition: water_cmd.cpp:722
void ClearNeighbourNonFloodingStates(TileIndex tile)
Clear non-flooding state of the tiles around a tile.
Definition: water_cmd.cpp:97
static void DoDryUp(TileIndex tile)
Drys a tile up.
Definition: water_cmd.cpp:1198
static Vehicle * FloodVehicleProc(Vehicle *v, void *data)
Flood a vehicle if we are allowed to flood it, i.e.
Definition: water_cmd.cpp:1023
CommandCost CmdBuildLock(DoCommandFlag flags, TileIndex tile)
Builds a lock.
Definition: water_cmd.cpp:435
static void MarkTileDirtyIfCanalOrRiver(TileIndex tile)
Marks tile dirty if it is a canal or river tile.
Definition: water_cmd.cpp:75
FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
Returns the behaviour of a tile during flooding.
Definition: water_cmd.cpp:1092
void CheckForDockingTile(TileIndex t)
Mark the supplied tile as a docking tile if it is suitable for docking.
Definition: water_cmd.cpp:195
static void DrawSeaWater(TileIndex)
Draw a plain sea water tile with no edges.
Definition: water_cmd.cpp:775
static void DrawWaterTileStruct(const TileInfo *ti, const DrawTileSeqStruct *dtss, SpriteID base, uint offset, PaletteID palette, CanalFeature feature)
Draw a build sprite sequence for water tiles.
Definition: water_cmd.cpp:805
static const uint8_t _flood_from_dirs[]
Describes from which directions a specific slope can be flooded (if the tile is floodable at all).
Definition: water_cmd.cpp:51
static void DrawCanalWater(TileIndex tile)
draw a canal styled water tile with dikes around
Definition: water_cmd.cpp:781
CommandCost CmdBuildShipDepot(DoCommandFlag flags, TileIndex tile, Axis axis)
Build a ship depot.
Definition: water_cmd.cpp:112
void MakeRiverAndModifyDesertZoneAround(TileIndex tile)
Make a river tile and remove desert directly around it.
Definition: water_cmd.cpp:454
static void DoFloodTile(TileIndex target)
Floods a tile.
Definition: water_cmd.cpp:1131
bool IsWateredTile(TileIndex tile, Direction from)
return true if a tile is a water tile wrt.
Definition: water_cmd.cpp:636
CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
Build a piece of canal.
Definition: water_cmd.cpp:472
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:381
bool HasTileWaterGround(Tile t)
Checks whether the tile has water at the ground.
Definition: water_map.h:350
TileIndex GetShipDepotNorthTile(Tile t)
Get the most northern tile of a ship depot.
Definition: water_map.h:289
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:506
DepotPart GetShipDepotPart(Tile t)
Get the part of a ship depot.
Definition: water_map.h:255
bool IsTileOnWater(Tile t)
Tests if the tile was built on water.
Definition: water_map.h:136
DepotPart
Sections of the water depot.
Definition: water_map.h:58
@ DEPOT_PART_NORTH
Northern part of a depot.
Definition: water_map.h:59
@ DEPOT_PART_SOUTH
Southern part of a depot.
Definition: water_map.h:60
bool IsShipDepot(Tile t)
Is it a water tile with a ship depot on it?
Definition: water_map.h:222
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:180
DiagDirection GetLockDirection(Tile t)
Get the direction of the water lock.
Definition: water_map.h:314
WaterClass
classes of water (for WATER_TILE_CLEAR water tile type).
Definition: water_map.h:39
@ WATER_CLASS_SEA
Sea.
Definition: water_map.h:40
@ WATER_CLASS_CANAL
Canal.
Definition: water_map.h:41
@ WATER_CLASS_INVALID
Used for industry tiles on land (also for oilrig if newgrf says so).
Definition: water_map.h:43
@ WATER_CLASS_RIVER
River.
Definition: water_map.h:42
bool HasTileWaterClass(Tile t)
Checks whether the tile has an waterclass associated.
Definition: water_map.h:101
bool IsCanal(Tile t)
Is it a canal tile?
Definition: water_map.h:169
bool IsCoast(Tile t)
Is it a coast tile?
Definition: water_map.h:201
void MakeRiver(Tile t, uint8_t random_bits)
Make a river tile.
Definition: water_map.h:432
WaterTileType GetWaterTileType(Tile t)
Get the water tile type of a tile.
Definition: water_map.h:78
void SetNonFloodingWaterTile(Tile t, bool b)
Set the non-flooding water tile state of a tile.
Definition: water_map.h:524
@ WATER_TILE_COAST
Coast.
Definition: water_map.h:33
@ WATER_TILE_LOCK
Water lock.
Definition: water_map.h:34
@ WATER_TILE_DEPOT
Water Depot.
Definition: water_map.h:35
@ WATER_TILE_CLEAR
Plain water.
Definition: water_map.h:32
WaterClass GetWaterClass(Tile t)
Get the water class at a tile.
Definition: water_map.h:112
void MakeCanal(Tile t, Owner o, uint8_t random_bits)
Make a canal tile.
Definition: water_map.h:443
uint8_t GetLockPart(Tile t)
Get the part of a lock.
Definition: water_map.h:326
TileIndex GetOtherShipDepotTile(Tile t)
Get the other tile of the ship depot.
Definition: water_map.h:278
bool IsNonFloodingWaterTile(Tile t)
Checks whether the tile is marked as a non-flooding water tile.
Definition: water_map.h:533
void SetDockingTile(Tile t, bool b)
Set the docking tile state of a tile.
Definition: water_map.h:361
bool IsWaterTile(Tile t)
Is it a water tile with plain water?
Definition: water_map.h:190
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition: water_map.h:303
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:458
void MakeSea(Tile t)
Make a sea tile.
Definition: water_map.h:422
@ LOCK_PART_UPPER
Upper part of a lock.
Definition: water_map.h:68
@ LOCK_PART_MIDDLE
Middle part of a lock.
Definition: water_map.h:66
Axis GetShipDepotAxis(Tile t)
Get the axis of the ship depot.
Definition: water_map.h:243
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.