OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

water_map.h
Go to the documentation of this file.
1 /* $Id: water_map.h 26878 2014-09-21 11:23:33Z rubidium $ */
2
3 /*
4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
8 */
9
12 #ifndef WATER_MAP_H
13 #define WATER_MAP_H
14
15 #include "depot_type.h"
16 #include "tile_map.h"
17
21 enum WaterTileTypeBitLayout {
22 WBL_TYPE_BEGIN = 4,
23 WBL_TYPE_COUNT = 4,
24
25 WBL_TYPE_NORMAL = 0x0,
26 WBL_TYPE_LOCK = 0x1,
27 WBL_TYPE_DEPOT = 0x8,
28
29 WBL_COAST_FLAG = 0,
30
31 WBL_LOCK_ORIENT_BEGIN = 0,
32 WBL_LOCK_ORIENT_COUNT = 2,
33 WBL_LOCK_PART_BEGIN = 2,
34 WBL_LOCK_PART_COUNT = 2,
35
36 WBL_DEPOT_PART = 0,
37 WBL_DEPOT_AXIS = 1,
38 };
39
41 enum WaterTileType {
42 WATER_TILE_CLEAR,
43 WATER_TILE_COAST,
44 WATER_TILE_LOCK,
45 WATER_TILE_DEPOT,
46 };
47
49 enum WaterClass {
50 WATER_CLASS_SEA,
51 WATER_CLASS_CANAL,
52 WATER_CLASS_RIVER,
53 WATER_CLASS_INVALID,
54 };
56 template <> struct EnumPropsT<WaterClass> : MakeEnumPropsT<WaterClass, byte, WATER_CLASS_SEA, WATER_CLASS_INVALID, WATER_CLASS_INVALID, 2> {};
57
59 enum DepotPart {
60 DEPOT_PART_NORTH = 0,
61 DEPOT_PART_SOUTH = 1,
62 DEPOT_PART_END
63 };
64
66 enum LockPart {
67 LOCK_PART_MIDDLE = 0,
68 LOCK_PART_LOWER = 1,
69 LOCK_PART_UPPER = 2,
70 };
71
77 static inline WaterTileType GetWaterTileType(TileIndex t)
78 {
79 assert(IsTileType(t, MP_WATER));
80
81 switch (GB(_m[t].m5, WBL_TYPE_BEGIN, WBL_TYPE_COUNT)) {
82 case WBL_TYPE_NORMAL: return HasBit(_m[t].m5, WBL_COAST_FLAG) ? WATER_TILE_COAST : WATER_TILE_CLEAR;
83 case WBL_TYPE_LOCK: return WATER_TILE_LOCK;
84 case WBL_TYPE_DEPOT: return WATER_TILE_DEPOT;
85 default: NOT_REACHED();
86 }
87 }
88
95 static inline bool HasTileWaterClass(TileIndex t)
96 {
97 return IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY) || IsTileType(t, MP_OBJECT);
98 }
99
106 static inline WaterClass GetWaterClass(TileIndex t)
107 {
108 assert(HasTileWaterClass(t));
109 return (WaterClass)GB(_m[t].m1, 5, 2);
110 }
111
118 static inline void SetWaterClass(TileIndex t, WaterClass wc)
119 {
120 assert(HasTileWaterClass(t));
121 SB(_m[t].m1, 5, 2, wc);
122 }
123
130 static inline bool IsTileOnWater(TileIndex t)
131 {
132 return (GetWaterClass(t) != WATER_CLASS_INVALID);
133 }
134
141 static inline bool IsWater(TileIndex t)
142 {
143 return GetWaterTileType(t) == WATER_TILE_CLEAR;
144 }
145
152 static inline bool IsSea(TileIndex t)
153 {
154 return IsWater(t) && GetWaterClass(t) == WATER_CLASS_SEA;
155 }
156
163 static inline bool IsCanal(TileIndex t)
164 {
165 return IsWater(t) && GetWaterClass(t) == WATER_CLASS_CANAL;
166 }
167
174 static inline bool IsRiver(TileIndex t)
175 {
176 return IsWater(t) && GetWaterClass(t) == WATER_CLASS_RIVER;
177 }
178
184 static inline bool IsWaterTile(TileIndex t)
185 {
186 return IsTileType(t, MP_WATER) && IsWater(t);
187 }
188
195 static inline bool IsCoast(TileIndex t)
196 {
197 return GetWaterTileType(t) == WATER_TILE_COAST;
198 }
199
205 static inline bool IsCoastTile(TileIndex t)
206 {
207 return IsTileType(t, MP_WATER) && IsCoast(t);
208 }
209
216 static inline bool IsShipDepot(TileIndex t)
217 {
218 return GetWaterTileType(t) == WATER_TILE_DEPOT;
219 }
220
226 static inline bool IsShipDepotTile(TileIndex t)
227 {
228 return IsTileType(t, MP_WATER) && IsShipDepot(t);
229 }
230
237 static inline Axis GetShipDepotAxis(TileIndex t)
238 {
239 assert(IsShipDepotTile(t));
240 return (Axis)GB(_m[t].m5, WBL_DEPOT_AXIS, 1);
241 }
242
249 static inline DepotPart GetShipDepotPart(TileIndex t)
250 {
251 assert(IsShipDepotTile(t));
252 return (DepotPart)GB(_m[t].m5, WBL_DEPOT_PART, 1);
253 }
254
261 static inline DiagDirection GetShipDepotDirection(TileIndex t)
262 {
263 return XYNSToDiagDir(GetShipDepotAxis(t), GetShipDepotPart(t));
264 }
265
272 static inline TileIndex GetOtherShipDepotTile(TileIndex t)
273 {
274 return t + (GetShipDepotPart(t) != DEPOT_PART_NORTH ? -1 : 1) * (GetShipDepotAxis(t) != AXIS_X ? TileDiffXY(0, 1) : TileDiffXY(1, 0));
275 }
276
283 static inline TileIndex GetShipDepotNorthTile(TileIndex t)
284 {
285 assert(IsShipDepot(t));
286 TileIndex tile2 = GetOtherShipDepotTile(t);
287
288 return t < tile2 ? t : tile2;
289 }
290
297 static inline bool IsLock(TileIndex t)
298 {
299 return GetWaterTileType(t) == WATER_TILE_LOCK;
300 }
301
308 static inline DiagDirection GetLockDirection(TileIndex t)
309 {
310 assert(IsLock(t));
311 return (DiagDirection)GB(_m[t].m5, WBL_LOCK_ORIENT_BEGIN, WBL_LOCK_ORIENT_COUNT);
312 }
313
320 static inline byte GetLockPart(TileIndex t)
321 {
322 assert(IsLock(t));
323 return GB(_m[t].m5, WBL_LOCK_PART_BEGIN, WBL_LOCK_PART_COUNT);
324 }
325
332 static inline byte GetWaterTileRandomBits(TileIndex t)
333 {
334 assert(IsTileType(t, MP_WATER));
335 return _m[t].m4;
336 }
337
344 static inline bool HasTileWaterGround(TileIndex t)
345 {
346 return HasTileWaterClass(t) && IsTileOnWater(t) && !IsCoastTile(t);
347 }
348
349
354 static inline void MakeShore(TileIndex t)
355 {
356 SetTileType(t, MP_WATER);
357 SetTileOwner(t, OWNER_WATER);
358 SetWaterClass(t, WATER_CLASS_SEA);
359 _m[t].m2 = 0;
360 _m[t].m3 = 0;
361 _m[t].m4 = 0;
362 _m[t].m5 = WBL_TYPE_NORMAL << WBL_TYPE_BEGIN | 1 << WBL_COAST_FLAG;
363 SB(_me[t].m6, 2, 4, 0);
364 _me[t].m7 = 0;
365 }
366
374 static inline void MakeWater(TileIndex t, Owner o, WaterClass wc, uint8 random_bits)
375 {
376 SetTileType(t, MP_WATER);
377 SetTileOwner(t, o);
378 SetWaterClass(t, wc);
379 _m[t].m2 = 0;
380 _m[t].m3 = 0;
381 _m[t].m4 = random_bits;
382 _m[t].m5 = WBL_TYPE_NORMAL << WBL_TYPE_BEGIN;
383 SB(_me[t].m6, 2, 4, 0);
384 _me[t].m7 = 0;
385 }
386
391 static inline void MakeSea(TileIndex t)
392 {
393 MakeWater(t, OWNER_WATER, WATER_CLASS_SEA, 0);
394 }
395
401 static inline void MakeRiver(TileIndex t, uint8 random_bits)
402 {
403 MakeWater(t, OWNER_WATER, WATER_CLASS_RIVER, random_bits);
404 }
405
412 static inline void MakeCanal(TileIndex t, Owner o, uint8 random_bits)
413 {
414 assert(o != OWNER_WATER);
415 MakeWater(t, o, WATER_CLASS_CANAL, random_bits);
416 }
417
427 static inline void MakeShipDepot(TileIndex t, Owner o, DepotID did, DepotPart part, Axis a, WaterClass original_water_class)
428 {
429 SetTileType(t, MP_WATER);
430 SetTileOwner(t, o);
431 SetWaterClass(t, original_water_class);
432 _m[t].m2 = did;
433 _m[t].m3 = 0;
434 _m[t].m4 = 0;
435 _m[t].m5 = WBL_TYPE_DEPOT << WBL_TYPE_BEGIN | part << WBL_DEPOT_PART | a << WBL_DEPOT_AXIS;
436 SB(_me[t].m6, 2, 4, 0);
437 _me[t].m7 = 0;
438 }
439
449 static inline void MakeLockTile(TileIndex t, Owner o, LockPart part, DiagDirection dir, WaterClass original_water_class)
450 {
451 SetTileType(t, MP_WATER);
452 SetTileOwner(t, o);
453 SetWaterClass(t, original_water_class);
454 _m[t].m2 = 0;
455 _m[t].m3 = 0;
456 _m[t].m4 = 0;
457 _m[t].m5 = WBL_TYPE_LOCK << WBL_TYPE_BEGIN | part << WBL_LOCK_PART_BEGIN | dir << WBL_LOCK_ORIENT_BEGIN;
458 SB(_me[t].m6, 2, 4, 0);
459 _me[t].m7 = 0;
460 }
461
471 static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper, WaterClass wc_middle)
472 {
473 TileIndexDiff delta = TileOffsByDiagDir(d);
474
475 /* Keep the current waterclass and owner for the tiles.
476 * It allows to restore them after the lock is deleted */
477 MakeLockTile(t, o, LOCK_PART_MIDDLE, d, wc_middle);
478 MakeLockTile(t - delta, IsWaterTile(t - delta) ? GetTileOwner(t - delta) : o, LOCK_PART_LOWER, d, wc_lower);
479 MakeLockTile(t + delta, IsWaterTile(t + delta) ? GetTileOwner(t + delta) : o, LOCK_PART_UPPER, d, wc_upper);
480 }
481
482 #endif /* WATER_MAP_H */