Changeset - r8471:0c8cd6eb92d6
[Not reviewed]
master
0 12 0
peter1138 - 17 years ago 2008-02-02 09:28:43
peter1138@openttd.org
(svn r12042) -Fix [FS#1676]: Reimplement how rivers and canals are stored in the map, allowing the sea/river/canal status to also be
stored for buoys, docks, locks and depots. All these are now allowed on rivers and removal of them will revert to the
original water type.
12 files changed with 161 insertions and 107 deletions:
0 comments (0 inline, 0 general)
docs/landscape.html
Show inline comments
 
@@ -791,12 +791,13 @@
 
    <ul>
 
     <li>m1: <a href="#OwnershipInfo">owner</a> of the station</li>
 
     <li>m2: index into the array of stations</li>
 
     <li>m3 bits 7..4: persistent random data for newstations</li>
 
     <li>m3 bits 3..0: <a href="#TrackType">track type</a> for railway stations</li>
 
     <li>m3 bits 2..0: present road types for road stops</li>
 
     <li>m3 bits 1..0: water class for buoys and water part of docks</li>
 
     <li>m4: custom station id; 0 means standard graphics</li>
 
     <li>m5: graphics index (range from 0..255 for each station type):
 
      <table>
 
       <tr>
 
        <td nowrap valign=top><tt>00</tt>..<tt>07</tt>&nbsp; </td>
 
        <td align=left>railway station
 
@@ -903,32 +904,28 @@
 
  </tr>
 
  <tr>
 
   <td valign=top nowrap>&nbsp;</td>
 
   <td>
 
    <ul>
 
     <li>m1: <a href="#OwnershipInfo">owner</a> (for sea, rivers, and coasts normally <tt>11</tt>)</li>
 
     <li>m3 bits 1..0 : Water class (sea, canal or river)
 
     <li>m4: Owner of the water when ship depot</li>
 
     <li>m4: Random data for canal or river tiles</li>
 
     <li>m5: tile type:
 
      <table>
 
       <tr>
 
        <td nowrap valign=top><tt>00</tt>&nbsp; </td>
 
        <td align=left>water</td>
 
        <td align=left>water, canal or river</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>01</tt>&nbsp; </td>
 
        <td align=left>coast or riverbank</td>
 
       </tr>
 

	
 
       <tr>
 
        <td noswap valign=top><tt>02</tt>&nbsp; </td>
 
        <td align=left>river</td>
 
       </tr>
 

	
 
       <tr>
 
        <td nowrap valign=top><tt>10</tt>..<tt>1B</tt>&nbsp; </td>
 
        <td align=left>canal locks
 
         <table>
 
          <tr>
 
           <td nowrap valign=top><tt>10</tt>&nbsp; </td>
 
           <td align=left>middle part, (SW-NE direction)</td>
docs/landscape_grid.html
Show inline comments
 
@@ -213,13 +213,13 @@ the array so you can quickly see what is
 
    </tr>
 
    <tr>
 
      <td class="caption">dock</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits"><span class="option">~~~~ ~~~~</span></td>
 
      <td class="bits"><span class="option">~~~~ ~</span>XXX</td>
 
      <td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
@@ -235,13 +235,13 @@ the array so you can quickly see what is
 
    </tr>
 
    <tr>
 
      <td class="caption">buoy</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits"><span class="option">~~~~ ~~~~</span></td>
 
      <td class="bits"><span class="option">~~~~ ~~~~</span></td>
 
      <td class="bits"><span class="free">OO</span>XX X<span class="free">O</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
@@ -258,35 +258,35 @@ the array so you can quickly see what is
 
    <tr>
 
      <td rowspan=3>6</td>
 
      <td class="caption">sea, shore</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits"><span class="option">~~~</span>X XXXX</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits">X<span class="option">~~</span>X XXXX</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">canal, river</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
 
      <td class="caption">shipdepot</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits"><span class="free">OOOO OOOO OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
      <td class="bits"><span class="free">OOOO OO</span>XX</td>
 
      <td class="bits">XXXX XXXX</td>
 
      <td class="bits">-inherit-</td>
 
      <td class="bits">XX<span class="free">OO OO</span>XX</td>
 
      <td class="bits"><span class="free">OOOO OOOO</span></td>
 
    </tr>
 
    <tr>
src/industry_cmd.cpp
Show inline comments
 
@@ -1223,13 +1223,13 @@ static bool CheckIfIndustryTilesAreFree(
 

	
 
			const IndustryTileSpec *its = GetIndustryTileSpec(gfx);
 

	
 
			IndustryBehaviour ind_behav = GetIndustrySpec(type)->behaviour;
 

	
 
			/* Perform land/water check if not disabled */
 
			if (!HasBit(its->slopes_refused, 5) && ((IsWaterTile(cur_tile) || IsRiverTile(cur_tile)) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return false;
 
			if (!HasBit(its->slopes_refused, 5) && (IsWaterTile(cur_tile) == !(ind_behav & INDUSTRYBEH_BUILT_ONWATER))) return false;
 

	
 
			if (HasBit(its->callback_flags, CBM_INDT_SHAPE_CHECK)) {
 
				custom_shape = true;
 
				if (!PerformIndustryTileSlopeCheck(tile, cur_tile, its, type, gfx, itspec_index)) return false;
 
			} else {
 
				Slope tileh = GetTileSlope(cur_tile, NULL);
src/newgrf_canal.cpp
Show inline comments
 
@@ -19,13 +19,14 @@ WaterFeature _water_feature[CF_END];
 

	
 

	
 
/* Random bits and triggers are not supported for canals, so the following
 
 * three functions are stubs. */
 
static uint32 CanalGetRandomBits(const ResolverObject *object)
 
{
 
	return GetWaterTileRandomBits(object->u.canal.tile);
 
	/* Return random bits only for water tiles, not station tiles */
 
	return IsTileType(object->u.canal.tile, MP_WATER) ? GetWaterTileRandomBits(object->u.canal.tile) : 0;
 
}
 

	
 

	
 
static uint32 CanalGetTriggers(const ResolverObject *object)
 
{
 
	return 0;
src/openttd.cpp
Show inline comments
 
@@ -74,12 +74,13 @@
 
#include "water_map.h"
 
#include "industry_map.h"
 
#include "unmovable_map.h"
 
#include "tree_map.h"
 
#include "tunnelbridge_map.h"
 
#include "void_map.h"
 
#include "water.h"
 

	
 
#include <stdarg.h>
 

	
 
#include "table/strings.h"
 

	
 
void CallLandscapeTick();
 
@@ -2320,15 +2321,37 @@ bool AfterLoadGame()
 
				}
 
			}
 
		}
 
	}
 

	
 
	if (CheckSavegameVersion(86)) {
 
		/* Now all crossings should be in correct state */
 
		for (TileIndex t = 0; t < map_size; t++) {
 
			/* Now all crossings should be in correct state */
 
			if (IsLevelCrossingTile(t)) UpdateLevelCrossing(t, false);
 

	
 
			/* Move river flag and update canals to use water class */
 
			if (IsTileType(t, MP_WATER)) {
 
				if (_m[t].m5 == 2) {
 
					MakeRiver(t, Random());
 
				} else {
 
					Owner o = GetTileOwner(t);
 
					if (IsWater(t) && o != OWNER_WATER) {
 
						MakeCanal(t, o, Random());
 
					}
 
				}
 
			}
 
		}
 

	
 
		/* Update locks, depots, docks and buoys to have a water class based
 
		 * on its neighbouring tiles. Done after river and canal updates to
 
		 * ensure neighbours are correct. */
 
		for (TileIndex t = 0; t < map_size; t++) {
 
			if (GetTileSlope(t, NULL) != SLOPE_FLAT) continue;
 

	
 
			if (IsTileType(t, MP_WATER) && (GetWaterTileType(t) == WATER_TILE_LOCK || IsShipDepot(t))) SetWaterClassDependingOnSurroundings(t);
 
			if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t);
 
		}
 
	}
 

	
 
	return InitializeWindowsAndCaches();
 
}
 

	
src/saveload.cpp
Show inline comments
 
@@ -31,13 +31,13 @@
 
#include "vehicle_base.h"
 
#include "autoreplace_base.h"
 
#include <list>
 

	
 
#include "table/strings.h"
 

	
 
extern const uint16 SAVEGAME_VERSION = 85;
 
extern const uint16 SAVEGAME_VERSION = 86;
 
uint16 _sl_version;       ///< the major savegame version identifier
 
byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
 

	
 
typedef void WriterProc(uint len);
 
typedef uint ReaderProc();
 

	
src/station_cmd.cpp
Show inline comments
 
@@ -1834,12 +1834,14 @@ static CommandCost RemoveAirport(Station
 
 */
 
CommandCost CmdBuildBuoy(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	if (!IsWaterTile(tile) || tile == 0) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 

	
 
	/* allocate and initialize new station */
 
	Station *st = new Station(tile);
 
	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 

	
 
	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
 
	AutoPtrT<Station> st_auto_delete(st);
 
@@ -1856,13 +1858,13 @@ CommandCost CmdBuildBuoy(TileIndex tile,
 
		 * braindead.. */
 
		st->had_vehicle_of_type |= HVOT_BUOY;
 
		st->owner = OWNER_NONE;
 

	
 
		st->build_date = _date;
 

	
 
		MakeBuoy(tile, st->index);
 
		MakeBuoy(tile, st->index, GetWaterClass(tile));
 

	
 
		UpdateStationVirtCoordDirty(st);
 
		UpdateStationAcceptance(st, false);
 
		RebuildStationLists();
 
		InvalidateWindow(WC_STATION_LIST, st->owner);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
@@ -1914,13 +1916,13 @@ static CommandCost RemoveBuoy(Station *s
 

	
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 

	
 
		/* We have to set the water tile's state to the same state as before the
 
		 * buoy was placed. Otherwise one could plant a buoy on a canal edge,
 
		 * remove it and flood the land (if the canal edge is at level 0) */
 
		MakeWaterOrCanalDependingOnOwner(tile, GetTileOwner(tile));
 
		MakeWaterKeepingClass(tile, GetTileOwner(tile));
 
		MarkTileDirtyByTile(tile);
 

	
 
		UpdateStationVirtCoordDirty(st);
 
		DeleteStationIfEmpty(st);
 
	}
 

	
 
@@ -1948,13 +1950,13 @@ CommandCost CmdBuildDock(TileIndex tile,
 

	
 
	DiagDirection direction = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
 
	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	direction = ReverseDiagDir(direction);
 

	
 
	/* Docks cannot be placed on rapids */
 
	if (IsRiverTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	if (IsWaterTile(tile)) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 

	
 
	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile)) return CMD_ERROR;
 

	
 
	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
@@ -1965,12 +1967,15 @@ CommandCost CmdBuildDock(TileIndex tile,
 
	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
	}
 

	
 
	if (MayHaveBridgeAbove(tile_cur) && IsBridgeAbove(tile_cur)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	/* Get the water class of the water tile before it is cleared.*/
 
	WaterClass wc = GetWaterClass(tile_cur);
 

	
 
	cost = DoCommand(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(cost)) return CMD_ERROR;
 

	
 
	tile_cur += TileOffsByDiagDir(direction);
 
	if (!IsTileType(tile_cur, MP_WATER) || GetTileSlope(tile_cur, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
@@ -2022,13 +2027,13 @@ CommandCost CmdBuildDock(TileIndex tile,
 
	if (flags & DC_EXEC) {
 
		st->dock_tile = tile;
 
		st->AddFacility(FACIL_DOCK, tile);
 

	
 
		st->rect.BeforeAddRect(tile, _dock_w_chk[direction], _dock_h_chk[direction], StationRect::ADD_TRY);
 

	
 
		MakeDock(tile, st->owner, st->index, direction);
 
		MakeDock(tile, st->owner, st->index, direction, wc);
 

	
 
		UpdateStationVirtCoordDirty(st);
 
		UpdateStationAcceptance(st, false);
 
		RebuildStationLists();
 
		InvalidateWindow(WC_STATION_LIST, st->owner);
 
		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
 
@@ -2047,13 +2052,13 @@ static CommandCost RemoveDock(Station *s
 

	
 
	if (!EnsureNoVehicleOnGround(tile1)) return CMD_ERROR;
 
	if (!EnsureNoVehicleOnGround(tile2)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DoClearSquare(tile1);
 
		MakeWaterOrCanalDependingOnSurroundings(tile2, st->owner);
 
		MakeWaterKeepingClass(tile2, st->owner);
 

	
 
		st->rect.AfterRemoveTile(st, tile1);
 
		st->rect.AfterRemoveTile(st, tile2);
 

	
 
		MarkTileDirtyByTile(tile2);
 

	
 
@@ -2152,13 +2157,20 @@ static void DrawTile_Station(TileInfo *t
 
	if (HasBit(roadtypes, ROADTYPE_TRAM)) {
 
		Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
 
		DrawGroundSprite((HasBit(roadtypes, ROADTYPE_ROAD) ? SPR_TRAMWAY_OVERLAY : SPR_TRAMWAY_TRAM) + (axis ^ 1), PAL_NONE);
 
		DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
 
	}
 

	
 
	if (IsCanalBuoyTile(ti->tile)) DrawCanalWater(ti->tile);
 
	if (IsBuoy(ti->tile)) {
 
		/* Draw appropriate water edges */
 
		switch (GetWaterClass(ti->tile)) {
 
			case WATER_CLASS_SEA: break;
 
			case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, false); break;
 
			case WATER_CLASS_RIVER: DrawRiverWater(ti, false); break;
 
		}
 
	}
 

	
 
	const DrawTileSeqStruct *dtss;
 
	foreach_draw_tile_seq(dtss, t->seq) {
 
		image = dtss->image;
 
		if (relocation == 0 || HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
 
			image += total_offset;
src/station_map.h
Show inline comments
 
@@ -4,12 +4,13 @@
 

	
 
#ifndef STATION_MAP_H
 
#define STATION_MAP_H
 

	
 
#include "rail_map.h"
 
#include "road_map.h"
 
#include "water_map.h"
 
#include "station.h"
 
#include "rail.h"
 

	
 
typedef byte StationGfx;
 

	
 
static inline StationID GetStationIndex(TileIndex t)
 
@@ -152,22 +153,12 @@ static inline bool IsBuoy(TileIndex t)
 

	
 
static inline bool IsBuoyTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_STATION) && IsBuoy(t);
 
}
 

	
 
static inline bool IsCanalBuoyTile(TileIndex t)
 
{
 
	return IsBuoyTile(t) && !IsTileOwner(t, OWNER_WATER);
 
}
 

	
 
static inline bool IsSeaBuoyTile(TileIndex t)
 
{
 
	return IsBuoyTile(t) && IsTileOwner(t, OWNER_WATER);
 
}
 

	
 
static inline bool IsHangarTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_STATION) && IsHangar(t);
 
}
 

	
 

	
 
@@ -284,24 +275,26 @@ static inline void MakeDriveThroughRoadS
 

	
 
static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section)
 
{
 
	MakeStation(t, o, sid, STATION_AIRPORT, section);
 
}
 

	
 
static inline void MakeBuoy(TileIndex t, StationID sid)
 
static inline void MakeBuoy(TileIndex t, StationID sid, WaterClass wc)
 
{
 
	/* Make the owner of the buoy tile the same as the current owner of the
 
	 * water tile. In this way, we can reset the owner of the water to its
 
	 * original state when the buoy gets removed. */
 
	MakeStation(t, GetTileOwner(t), sid, STATION_BUOY, 0);
 
	SetWaterClass(t, wc);
 
}
 

	
 
static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d)
 
static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d, WaterClass wc)
 
{
 
	MakeStation(t, o, sid, STATION_DOCK, d);
 
	MakeStation(t + TileOffsByDiagDir(d), o, sid, STATION_DOCK, GFX_DOCK_BASE_WATER_PART + DiagDirToAxis(d));
 
	SetWaterClass(t + TileOffsByDiagDir(d), wc);
 
}
 

	
 
static inline void MakeOilrig(TileIndex t, StationID sid)
 
{
 
	MakeStation(t, OWNER_NONE, sid, STATION_OILRIG, 0);
 
}
src/tunnelbridge_cmd.cpp
Show inline comments
 
@@ -245,13 +245,13 @@ CommandCost CmdBuildBridge(TileIndex end
 
	bridge_len = sx + sy - x - y - 1;
 
	if (!CheckBridge_Stuff(bridge_type, bridge_len)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE);
 

	
 
	/* retrieve landscape height and ensure it's on land */
 
	tile_start = TileXY(x, y);
 
	tile_end = TileXY(sx, sy);
 
	if (IsWaterTile(tile_start) || IsRiverTile(tile_start) || IsWaterTile(tile_end) || IsRiverTile(tile_end)) {
 
	if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) {
 
		return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH);
 
	}
 

	
 
	tileh_start = GetTileSlope(tile_start, &z_start);
 
	tileh_end = GetTileSlope(tile_end, &z_end);
 

	
 
@@ -370,13 +370,13 @@ CommandCost CmdBuildBridge(TileIndex end
 
			return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
		}
 

	
 
		switch (GetTileType(tile)) {
 
			case MP_WATER:
 
				if (!EnsureNoVehicleOnGround(tile)) return_cmd_error(STR_980E_SHIP_IN_THE_WAY);
 
				if (!IsWater(tile) && !IsCoast(tile) && !IsRiver(tile)) goto not_valid_below;
 
				if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below;
 
				break;
 

	
 
			case MP_RAILWAY:
 
				if (!IsPlainRailTile(tile)) goto not_valid_below;
 
				break;
 

	
 
@@ -465,13 +465,13 @@ CommandCost CmdBuildTunnel(TileIndex sta
 
	}
 

	
 
	start_tileh = GetTileSlope(start_tile, &start_z);
 
	direction = GetInclinedSlopeDirection(start_tileh);
 
	if (direction == INVALID_DIAGDIR) return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL);
 

	
 
	if (IsRiverTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 
	if (IsWaterTile(start_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 

	
 
	ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return ret;
 

	
 
	/* XXX - do NOT change 'ret' in the loop, as it is used as the price
 
	 * for the clearing of the entrance of the tunnel. Assigning it to
 
@@ -519,13 +519,13 @@ CommandCost CmdBuildTunnel(TileIndex sta
 
	cost.AddCost(_price.build_tunnel);
 
	cost.AddCost(ret);
 

	
 
	/* if the command fails from here on we want the end tile to be highlighted */
 
	_build_tunnel_endtile = end_tile;
 

	
 
	if (IsRiverTile(end_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 
	if (IsWaterTile(end_tile)) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 

	
 
	/* slope of end tile must be complementary to the slope of the start tile */
 
	if (end_tileh != ComplementSlope(start_tileh)) {
 
		/* Check if there is a structure on the terraformed tile. Do not add the cost, that will be done by the terraforming */
 
		ret = DoCommand(end_tile, 0, 0, DC_AUTO, CMD_LANDSCAPE_CLEAR);
 
		if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND);
src/water.h
Show inline comments
 
@@ -8,13 +8,14 @@
 
void TileLoop_Water(TileIndex tile);
 
bool FloodHalftile(TileIndex t);
 

	
 
void ConvertGroundTilesIntoWaterTiles();
 

	
 
void DrawShipDepotSprite(int x, int y, int image);
 
void DrawCanalWater(TileIndex tile);
 
void DrawCanalWater(TileIndex tile, bool draw_base);
 
void DrawRiverWater(const struct TileInfo *ti, bool draw_base);
 
void DrawShoreTile(Slope tileh);
 

	
 
void MakeWaterOrCanalDependingOnOwner(TileIndex tile, Owner o);
 
void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o);
 
void MakeWaterKeepingClass(TileIndex tile, Owner o);
 
void SetWaterClassDependingOnSurroundings(TileIndex t);
 

	
 
#endif /* WATER_H */
src/water_cmd.cpp
Show inline comments
 
@@ -98,34 +98,30 @@ static void MarkCanalsAndRiversAroundDir
 
 * Makes a tile canal or water depending on the surroundings.
 
 * This as for example docks and shipdepots do not store
 
 * whether the tile used to be canal or 'normal' water.
 
 * @param t the tile to change.
 
 * @param o the owner of the new tile.
 
 */
 
void MakeWaterOrCanalDependingOnSurroundings(TileIndex t, Owner o)
 
void SetWaterClassDependingOnSurroundings(TileIndex t)
 
{
 
	assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
 

	
 
	/* Mark tile dirty in all cases */
 
	MarkTileDirtyByTile(t);
 

	
 
	/* Non-sealevel -> canal */
 
	if (TileHeight(t) != 0) {
 
		MakeCanal(t, o, Random());
 
		return;
 
	}
 

	
 
	bool has_water = false;
 
	bool has_canal = false;
 
	bool has_river = false;
 

	
 
	for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
 
		TileIndex neighbour = TileAddByDiagDir(t, dir);
 
		switch (GetTileType(neighbour)) {
 
			case MP_WATER:
 
				has_water |= IsSea(neighbour) || IsCoast(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) == OWNER_WATER);
 
				has_canal |= IsCanal(neighbour) || (IsShipDepot(neighbour) && GetShipDepotWaterOwner(neighbour) != OWNER_WATER);
 
				has_river |= IsRiver(neighbour);
 
				break;
 

	
 
			case MP_RAILWAY:
 
				/* Shore or flooded halftile */
 
				has_water |= (GetRailGroundType(neighbour) == RAIL_GROUND_WATER);
 
				break;
 
@@ -135,16 +131,19 @@ void MakeWaterOrCanalDependingOnSurround
 
				has_water |= (GetTreeGround(neighbour) == TREE_GROUND_SHORE);
 
				break;
 

	
 
			default: break;
 
		}
 
	}
 
	if (has_canal || !has_water) {
 
		MakeCanal(t, o, Random());
 

	
 
	if (has_river && !has_canal) {
 
		SetWaterClass(t, WATER_CLASS_RIVER);
 
	} else if (has_canal || !has_water) {
 
		SetWaterClass(t, WATER_CLASS_CANAL);
 
	} else {
 
		MakeWater(t);
 
		SetWaterClass(t, WATER_CLASS_SEA);
 
	}
 
}
 

	
 

	
 
/** Build a ship depot.
 
 * @param tile tile where ship depot is built
 
@@ -159,17 +158,25 @@ CommandCost CmdBuildShipDepot(TileIndex 
 
	CommandCost ret;
 

	
 
	Axis axis = Extract<Axis, 0>(p1);
 

	
 
	tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
 

	
 
	if (!IsWaterTile(tile) || !IsWaterTile(tile2))
 
	if (!IsWaterTile(tile) || !IsWaterTile(tile2)) {
 
		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
 
	}
 

	
 
	if (IsBridgeAbove(tile) || IsBridgeAbove(tile2)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 

	
 
	if (GetTileSlope(tile, NULL) != SLOPE_FLAT || GetTileSlope(tile2, NULL) != SLOPE_FLAT) {
 
		/* Prevent depots on rapids */
 
		return_cmd_error(STR_0239_SITE_UNSUITABLE);
 
	}
 

	
 
	WaterClass wc1 = GetWaterClass(tile);
 
	WaterClass wc2 = GetWaterClass(tile2);
 
	Owner o1 = GetTileOwner(tile);
 
	Owner o2 = GetTileOwner(tile2);
 
	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return CMD_ERROR;
 
	ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return CMD_ERROR;
 
@@ -178,28 +185,30 @@ CommandCost CmdBuildShipDepot(TileIndex 
 
	if (depot == NULL) return CMD_ERROR;
 
	AutoPtrT<Depot> d_auto_delete = depot;
 

	
 
	if (flags & DC_EXEC) {
 
		depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 

	
 
		MakeShipDepot(tile,  _current_player, DEPOT_NORTH, axis, o1);
 
		MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, o2);
 
		MakeShipDepot(tile,  _current_player, DEPOT_NORTH, axis, wc1, o1);
 
		MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, wc2, o2);
 
		MarkTileDirtyByTile(tile);
 
		MarkTileDirtyByTile(tile2);
 
		d_auto_delete.Detach();
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot);
 
}
 

	
 
void MakeWaterOrCanalDependingOnOwner(TileIndex tile, Owner o)
 
void MakeWaterKeepingClass(TileIndex tile, Owner o)
 
{
 
	if (o == OWNER_WATER) {
 
		MakeWater(tile);
 
	} else {
 
		MakeCanal(tile, o, Random());
 
	assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile))));
 

	
 
	switch (GetWaterClass(tile)) {
 
		case WATER_CLASS_SEA:   MakeWater(tile);              break;
 
		case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
 
		case WATER_CLASS_RIVER: MakeRiver(tile, Random());    break;
 
	}
 
}
 

	
 
static CommandCost RemoveShipDepot(TileIndex tile, uint32 flags)
 
{
 
	TileIndex tile2;
 
@@ -213,14 +222,14 @@ static CommandCost RemoveShipDepot(TileI
 
	if (!EnsureNoVehicleOnGround(tile2)) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		/* Kill the depot, which is registered at the northernmost tile. Use that one */
 
		delete GetDepotByTile(tile2 < tile ? tile2 : tile);
 

	
 
		MakeWaterOrCanalDependingOnOwner(tile,  GetShipDepotWaterOwner(tile));
 
		MakeWaterOrCanalDependingOnOwner(tile2, GetShipDepotWaterOwner(tile2));
 
		MakeWaterKeepingClass(tile,  GetShipDepotWaterOwner(tile));
 
		MakeWaterKeepingClass(tile2, GetShipDepotWaterOwner(tile2));
 
		MarkTileDirtyByTile(tile);
 
		MarkTileDirtyByTile(tile2);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_ship_depot);
 
}
 
@@ -234,19 +243,23 @@ static CommandCost DoBuildShiplift(TileI
 
	/* middle tile */
 
	ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return CMD_ERROR;
 

	
 
	delta = TileOffsByDiagDir(dir);
 
	/* lower tile */
 
	WaterClass wc_lower = IsWaterTile(tile - delta) ? GetWaterClass(tile - delta) : WATER_CLASS_CANAL;
 

	
 
	ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return CMD_ERROR;
 
	if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
	}
 

	
 
	/* upper tile */
 
	WaterClass wc_upper = IsWaterTile(tile + delta) ? GetWaterClass(tile + delta) : WATER_CLASS_CANAL;
 

	
 
	ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 
	if (CmdFailed(ret)) return CMD_ERROR;
 
	if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) {
 
		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 
	}
 

	
 
@@ -254,13 +267,13 @@ static CommandCost DoBuildShiplift(TileI
 
	    (MayHaveBridgeAbove(tile - delta) && IsBridgeAbove(tile - delta)) ||
 
	    (MayHaveBridgeAbove(tile + delta) && IsBridgeAbove(tile + delta))) {
 
		return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		MakeLock(tile, _current_player, dir);
 
		MakeLock(tile, _current_player, dir, wc_lower, wc_upper);
 
		MarkTileDirtyByTile(tile);
 
		MarkTileDirtyByTile(tile - delta);
 
		MarkTileDirtyByTile(tile + delta);
 
		MarkCanalsAndRiversAroundDirty(tile - delta);
 
		MarkCanalsAndRiversAroundDirty(tile + delta);
 
	}
 
@@ -277,14 +290,16 @@ static CommandCost RemoveShiplift(TileIn
 
	/* make sure no vehicle is on the tile. */
 
	if (!EnsureNoVehicleOnGround(tile) || !EnsureNoVehicleOnGround(tile + delta) || !EnsureNoVehicleOnGround(tile - delta))
 
		return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		DoClearSquare(tile);
 
		MakeWaterOrCanalDependingOnSurroundings(tile + delta, _current_player);
 
		MakeWaterOrCanalDependingOnSurroundings(tile - delta, _current_player);
 
		MakeWaterKeepingClass(tile + delta, GetTileOwner(tile));
 
		MakeWaterKeepingClass(tile - delta, GetTileOwner(tile));
 
		MarkTileDirtyByTile(tile - delta);
 
		MarkTileDirtyByTile(tile + delta);
 
		MarkCanalsAndRiversAroundDirty(tile - delta);
 
		MarkCanalsAndRiversAroundDirty(tile + delta);
 
	}
 

	
 
	return CommandCost(EXPENSES_CONSTRUCTION, _price.clear_water * 2);
 
}
 
@@ -298,13 +313,13 @@ static CommandCost RemoveShiplift(TileIn
 
CommandCost CmdBuildLock(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile, NULL));
 
	if (dir == INVALID_DIAGDIR) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
 

	
 
	/* Disallow building of locks on river rapids */
 
	if (IsRiverTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE);
 
	if (IsWaterTile(tile)) return_cmd_error(STR_0239_SITE_UNSUITABLE);
 

	
 
	return DoBuildShiplift(tile, dir, flags);
 
}
 

	
 
/** Build a piece of canal.
 
 * @param tile end tile of stretch-dragging
 
@@ -376,13 +391,12 @@ CommandCost CmdBuildCanal(TileIndex tile
 
}
 

	
 
static CommandCost ClearTile_Water(TileIndex tile, byte flags)
 
{
 
	switch (GetWaterTileType(tile)) {
 
		case WATER_TILE_CLEAR:
 
		case WATER_TILE_RIVER:
 
			if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
 

	
 
			/* Make sure it's not an edge tile. */
 
			if (!IsInsideMM(TileX(tile), 1, MapMaxX() - 1) ||
 
					!IsInsideMM(TileY(tile), 1, MapMaxY() - 1)) {
 
				return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP);
 
@@ -469,13 +483,13 @@ static bool IsWateredTile(TileIndex tile
 
					case SLOPE_N: return (from == DIR_SW) || (from == DIR_S) || (from == DIR_SE);
 
					default: return false;
 
				}
 
			}
 
			return false;
 

	
 
		case MP_STATION:  return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile);
 
		case MP_STATION:  return IsOilRig(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
 
		case MP_INDUSTRY: return (GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
 
		default:          return false;
 
	}
 
}
 

	
 
static void DrawWaterEdges(SpriteID base, TileIndex tile)
 
@@ -515,15 +529,23 @@ static void DrawWaterEdges(SpriteID base
 
	switch (wa & 0x09) {
 
		case 0: DrawGroundSprite(base + 7, PAL_NONE); break;
 
		case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)) DrawGroundSprite(base + 11, PAL_NONE); break;
 
	}
 
}
 

	
 
/** Draw a plain sea water tile with no edges */
 
void DrawSeaWater(TileIndex tile)
 
{
 
	DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
 
}
 

	
 
/** draw a canal styled water tile with dikes around */
 
void DrawCanalWater(TileIndex tile)
 
void DrawCanalWater(TileIndex tile, bool draw_base)
 
{
 
	if (draw_base) DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
 

	
 
	/* Test for custom graphics, else use the default */
 
	SpriteID dikes_base = GetCanalSprite(CF_DIKES, tile);
 
	if (dikes_base == 0) dikes_base = SPR_CANAL_DIKES_BASE;
 

	
 
	DrawWaterEdges(dikes_base, tile);
 
}
 
@@ -563,13 +585,13 @@ static void DrawWaterStuff(const TileInf
 
			wdts->width, wdts->height,
 
			wdts->unk, ti->z + wdts->delta_z,
 
			IsTransparencySet(TO_BUILDINGS));
 
	}
 
}
 

	
 
static void DrawRiverWater(const TileInfo *ti)
 
void DrawRiverWater(const TileInfo *ti, bool draw_base)
 
{
 
	SpriteID image = SPR_FLAT_WATER_TILE;
 
	SpriteID edges_base = GetCanalSprite(CF_RIVER_EDGE, ti->tile);
 

	
 
	if (ti->tileh != SLOPE_FLAT) {
 
		image = GetCanalSprite(CF_RIVER_SLOPE, ti->tile);
 
@@ -589,13 +611,13 @@ static void DrawRiverWater(const TileInf
 
				case SLOPE_SW: image += 2; edges_base += 36; break;
 
				case SLOPE_NW: image += 3; edges_base += 48; break;
 
			}
 
		}
 
	}
 

	
 
	DrawGroundSprite(image, PAL_NONE);
 
	if (draw_base) DrawGroundSprite(image, PAL_NONE);
 

	
 
	/* Draw river edges if available. */
 
	if (edges_base > 48) DrawWaterEdges(edges_base, ti->tile);
 
}
 

	
 
void DrawShoreTile(Slope tileh)
 
@@ -616,14 +638,17 @@ void DrawShoreTile(Slope tileh)
 
}
 

	
 
static void DrawTile_Water(TileInfo *ti)
 
{
 
	switch (GetWaterTileType(ti->tile)) {
 
		case WATER_TILE_CLEAR:
 
			DrawGroundSprite(SPR_FLAT_WATER_TILE, PAL_NONE);
 
			if (IsCanal(ti->tile)) DrawCanalWater(ti->tile);
 
			switch (GetWaterClass(ti->tile)) {
 
				case WATER_CLASS_SEA:   DrawSeaWater(ti->tile); break;
 
				case WATER_CLASS_CANAL: DrawCanalWater(ti->tile, true); break;
 
				case WATER_CLASS_RIVER: DrawRiverWater(ti, true); break;
 
			}
 
			DrawBridgeMiddle(ti);
 
			break;
 

	
 
		case WATER_TILE_COAST: {
 
			DrawShoreTile(ti->tileh);
 
			DrawBridgeMiddle(ti);
 
@@ -634,17 +659,12 @@ static void DrawTile_Water(TileInfo *ti)
 
			DrawWaterStuff(ti, t, 0, ti->z > t[3].delta_y ? 24 : 0);
 
		} break;
 

	
 
		case WATER_TILE_DEPOT:
 
			DrawWaterStuff(ti, _shipdepot_display_seq[GetSection(ti->tile)], PLAYER_SPRITE_COLOR(GetTileOwner(ti->tile)), 0);
 
			break;
 

	
 
		case WATER_TILE_RIVER:
 
			DrawRiverWater(ti);
 
			DrawBridgeMiddle(ti);
 
			break;
 
	}
 
}
 

	
 
void DrawShipDepotSprite(int x, int y, int image)
 
{
 
	const WaterDrawTileStruct *wdts = _shipdepot_display_seq[image];
 
@@ -677,13 +697,12 @@ static void GetAcceptedCargo_Water(TileI
 
}
 

	
 
static void GetTileDesc_Water(TileIndex tile, TileDesc *td)
 
{
 
	switch (GetWaterTileType(tile)) {
 
		case WATER_TILE_CLEAR:
 
		case WATER_TILE_RIVER:
 
			if (!IsCanal(tile)) {
 
				td->str = STR_3804_WATER;
 
			} else {
 
				td->str = STR_LANDINFO_CANAL;
 
			}
 
			break;
 
@@ -839,26 +858,26 @@ static FloodingBehaviour GetFloodingBeha
 
	switch (GetTileType(tile)) {
 
		case MP_WATER:
 
			if (IsCoast(tile)) {
 
				Slope tileh = GetTileSlope(tile, NULL);
 
				return (IsSlopeWithOneCornerRaised(tileh) ? FLOOD_ACTIVE : FLOOD_DRYUP);
 
			} else {
 
				return ((IsSea(tile) || (IsShipDepot(tile) && (GetShipDepotWaterOwner(tile) == OWNER_WATER))) ? FLOOD_ACTIVE : FLOOD_NONE);
 
				return (GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE;
 
			}
 

	
 
		case MP_RAILWAY:
 
			if (GetRailGroundType(tile) == RAIL_GROUND_WATER) {
 
				return (IsSlopeWithOneCornerRaised(GetTileSlope(tile, NULL)) ? FLOOD_ACTIVE : FLOOD_DRYUP);
 
			}
 
			return FLOOD_NONE;
 

	
 
		case MP_TREES:
 
			return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
 

	
 
		case MP_STATION:
 
			if (IsSeaBuoyTile(tile)) return FLOOD_ACTIVE;
 
			if (IsBuoy(tile) && GetWaterClass(tile) == WATER_CLASS_SEA) return FLOOD_ACTIVE;
 
			if (IsOilRig(tile) || IsDock(tile)) return FLOOD_PASSIVE;
 
			return FLOOD_NONE;
 

	
 
		case MP_INDUSTRY:
 
			return ((GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0 ? FLOOD_PASSIVE : FLOOD_NONE);
 

	
 
@@ -1070,17 +1089,16 @@ static uint32 GetTileTrackStatus_Water(T
 

	
 
	TrackBits ts;
 

	
 
	if (mode != TRANSPORT_WATER) return 0;
 

	
 
	switch (GetWaterTileType(tile)) {
 
		case WATER_TILE_CLEAR: ts = TRACK_BIT_ALL; break;
 
		case WATER_TILE_CLEAR: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
 
		case WATER_TILE_COAST: ts = (TrackBits)coast_tracks[GetTileSlope(tile, NULL) & 0xF]; break;
 
		case WATER_TILE_LOCK:  ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break;
 
		case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break;
 
		case WATER_TILE_RIVER: ts = (GetTileSlope(tile, NULL) == SLOPE_FLAT) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break;
 
		default: return 0;
 
	}
 
	if (TileX(tile) == 0) {
 
		/* NE border: remove tracks that connects NE tile edge */
 
		ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT);
 
	}
src/water_map.h
Show inline comments
 
@@ -7,13 +7,18 @@
 

	
 
enum WaterTileType {
 
	WATER_TILE_CLEAR,
 
	WATER_TILE_COAST,
 
	WATER_TILE_LOCK,
 
	WATER_TILE_DEPOT,
 
	WATER_TILE_RIVER,
 
};
 

	
 
enum WaterClass {
 
	WATER_CLASS_SEA,
 
	WATER_CLASS_CANAL,
 
	WATER_CLASS_RIVER,
 
};
 

	
 
enum DepotPart {
 
	DEPOT_NORTH = 0x80,
 
	DEPOT_SOUTH = 0x81,
 
	DEPOT_END   = 0x84,
 
@@ -29,55 +34,59 @@ enum LockPart {
 
static inline WaterTileType GetWaterTileType(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_WATER));
 

	
 
	if (_m[t].m5 == 0) return WATER_TILE_CLEAR;
 
	if (_m[t].m5 == 1) return WATER_TILE_COAST;
 
	if (_m[t].m5 == 2) return WATER_TILE_RIVER;
 
	if (IsInsideMM(_m[t].m5, LOCK_MIDDLE, LOCK_END)) return WATER_TILE_LOCK;
 

	
 
	assert(IsInsideMM(_m[t].m5, DEPOT_NORTH, DEPOT_END));
 
	return WATER_TILE_DEPOT;
 
}
 

	
 
static inline WaterClass GetWaterClass(TileIndex t)
 
{
 
	assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION));
 
	return (WaterClass)GB(_m[t].m3, 0, 2);
 
}
 

	
 
static inline void SetWaterClass(TileIndex t, WaterClass wc)
 
{
 
	assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION));
 
	SB(_m[t].m3, 0, 2, wc);
 
}
 

	
 
/** IsWater return true if any type of clear water like ocean, river, canal */
 
static inline bool IsWater(TileIndex t)
 
{
 
	return GetWaterTileType(t) == WATER_TILE_CLEAR;
 
}
 

	
 
static inline bool IsSea(TileIndex t)
 
{
 
	if (GetWaterTileType(t) != WATER_TILE_CLEAR) return false;
 
	if (!IsTileOwner(t, OWNER_WATER)) return false; // 'Human' built water = canal, not sea
 
	return true;
 
}
 

	
 
static inline bool IsCoast(TileIndex t)
 
{
 
	return GetWaterTileType(t) == WATER_TILE_COAST;
 
	return IsWater(t) && GetWaterClass(t) == WATER_CLASS_SEA;
 
}
 

	
 
static inline bool IsCanal(TileIndex t)
 
{
 
	return GetWaterTileType(t) == WATER_TILE_CLEAR && GetTileOwner(t) != OWNER_WATER;
 
	return IsWater(t) && GetWaterClass(t) == WATER_CLASS_CANAL;
 
}
 

	
 
static inline bool IsRiver(TileIndex t)
 
{
 
	return GetWaterTileType(t) == WATER_TILE_RIVER;
 
	return IsWater(t) && GetWaterClass(t) == WATER_CLASS_RIVER;
 
}
 

	
 
static inline bool IsWaterTile(TileIndex t)
 
{
 
	return IsTileType(t, MP_WATER) && IsWater(t);
 
}
 

	
 
static inline bool IsRiverTile(TileIndex t)
 
static inline bool IsCoast(TileIndex t)
 
{
 
	return IsTileType(t, MP_WATER) && IsRiver(t);
 
	return GetWaterTileType(t) == WATER_TILE_COAST;
 
}
 

	
 
static inline TileIndex GetOtherShipDepotTile(TileIndex t)
 
{
 
	return t + (HasBit(_m[t].m5, 0) ? -1 : 1) * (HasBit(_m[t].m5, 1) ? TileDiffXY(0, 1) : TileDiffXY(1, 0));
 
}
 
@@ -121,13 +130,13 @@ static inline byte GetWaterTileRandomBit
 

	
 
static inline void MakeWater(TileIndex t)
 
{
 
	SetTileType(t, MP_WATER);
 
	SetTileOwner(t, OWNER_WATER);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m3 = WATER_CLASS_SEA;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = 0;
 
}
 

	
 
static inline void MakeShore(TileIndex t)
 
{
 
@@ -141,52 +150,52 @@ static inline void MakeShore(TileIndex t
 

	
 
static inline void MakeRiver(TileIndex t, uint8 random_bits)
 
{
 
	SetTileType(t, MP_WATER);
 
	SetTileOwner(t, OWNER_WATER);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m3 = WATER_CLASS_RIVER;
 
	_m[t].m4 = random_bits;
 
	_m[t].m5 = 2;
 
	_m[t].m5 = 0;
 
}
 

	
 
static inline void MakeCanal(TileIndex t, Owner o, uint8 random_bits)
 
{
 
	assert(o != OWNER_WATER);
 
	SetTileType(t, MP_WATER);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m3 = WATER_CLASS_CANAL;
 
	_m[t].m4 = random_bits;
 
	_m[t].m5 = 0;
 
}
 

	
 
static inline void MakeShipDepot(TileIndex t, Owner o, DepotPart base, Axis a, Owner original_owner)
 
static inline void MakeShipDepot(TileIndex t, Owner o, DepotPart base, Axis a, WaterClass original_water_class, Owner original_owner)
 
{
 
	SetTileType(t, MP_WATER);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m3 = original_water_class;
 
	_m[t].m4 = original_owner;
 
	_m[t].m5 = base + a * 2;
 
}
 

	
 
static inline void MakeLockTile(TileIndex t, Owner o, byte section)
 
static inline void MakeLockTile(TileIndex t, Owner o, byte section, WaterClass original_water_class)
 
{
 
	SetTileType(t, MP_WATER);
 
	SetTileOwner(t, o);
 
	_m[t].m2 = 0;
 
	_m[t].m3 = 0;
 
	_m[t].m3 = original_water_class;
 
	_m[t].m4 = 0;
 
	_m[t].m5 = section;
 
}
 

	
 
static inline void MakeLock(TileIndex t, Owner o, DiagDirection d)
 
static inline void MakeLock(TileIndex t, Owner o, DiagDirection d, WaterClass wc_lower, WaterClass wc_upper)
 
{
 
	TileIndexDiff delta = TileOffsByDiagDir(d);
 

	
 
	MakeLockTile(t, o, LOCK_MIDDLE + d);
 
	MakeLockTile(t - delta, o, LOCK_LOWER + d);
 
	MakeLockTile(t + delta, o, LOCK_UPPER + d);
 
	MakeLockTile(t, o, LOCK_MIDDLE + d, WATER_CLASS_CANAL);
 
	MakeLockTile(t - delta, o, LOCK_LOWER + d, wc_lower);
 
	MakeLockTile(t + delta, o, LOCK_UPPER + d, wc_upper);
 
}
 

	
 
#endif /* WATER_MAP_H */
0 comments (0 inline, 0 general)