water_cmd.c
changeset 0 29654efe3188
child 39 d177340ed556
equal deleted inserted replaced
-1:000000000000 0:29654efe3188
       
     1 #include "stdafx.h"
       
     2 #include "ttd.h"
       
     3 #include "vehicle.h"
       
     4 #include "viewport.h"
       
     5 #include "command.h"
       
     6 #include "town.h"
       
     7 
       
     8 bool IsShipDepotTile(TileIndex tile)
       
     9 {
       
    10 	return IS_TILETYPE(tile, MP_WATER) &&	(_map5[tile]&~3) == 0x80;
       
    11 }
       
    12 
       
    13 bool IsClearWaterTile(uint tile)
       
    14 {
       
    15 	TileInfo ti;
       
    16 	FindLandscapeHeightByTile(&ti, tile);
       
    17 	return (ti.type == MP_WATER && ti.tileh == 0 && ti.map5 == 0);
       
    18 }
       
    19 
       
    20 /* Build a ship depot
       
    21  * p1 - direction
       
    22  */
       
    23 
       
    24 int32 CmdBuildShipDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
       
    25 {
       
    26 	uint tile, tile2;
       
    27 	
       
    28 	int32 cost, ret;
       
    29 	Depot *dep;
       
    30 
       
    31 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
    32 
       
    33 	tile = TILE_FROM_XY(x,y);
       
    34 	if (!EnsureNoVehicle(tile))
       
    35 		return CMD_ERROR;
       
    36 
       
    37 	tile2 = tile + (p1 ? TILE_XY(0,1) : TILE_XY(1,0));
       
    38 	if (!EnsureNoVehicle(tile2))
       
    39 		return CMD_ERROR;
       
    40 
       
    41 	if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2))
       
    42 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
       
    43 
       
    44 	ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
    45 	if (ret == CMD_ERROR) return CMD_ERROR;
       
    46 	ret = DoCommandByTile(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
    47 	if (ret == CMD_ERROR)
       
    48 		return CMD_ERROR;
       
    49 	
       
    50 	// pretend that we're not making land from the water even though we actually are.
       
    51 	cost = 0;
       
    52 
       
    53 	dep = AllocateDepot();
       
    54 	if (dep == NULL)
       
    55 		return CMD_ERROR;
       
    56 
       
    57 	if (flags & DC_EXEC) {
       
    58 		dep->xy = tile;
       
    59 		_last_built_ship_depot_tile = tile;
       
    60 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
       
    61 
       
    62 		ModifyTile(tile, 
       
    63 			MP_SETTYPE(MP_WATER) | MP_MAPOWNER_CURRENT | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,
       
    64 			(0x80 + p1*2)
       
    65 		);
       
    66 	
       
    67 		ModifyTile(tile2, 
       
    68 			MP_SETTYPE(MP_WATER) | MP_MAPOWNER_CURRENT | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,
       
    69 			(0x81 + p1*2)
       
    70 		);
       
    71 	}
       
    72 
       
    73 	return cost + _price.build_ship_depot;
       
    74 }
       
    75 
       
    76 static int32 RemoveShipDepot(uint tile, uint32 flags)
       
    77 {
       
    78 	uint tile2;
       
    79 
       
    80 	if (!CheckTileOwnership(tile))
       
    81 		return CMD_ERROR;
       
    82 
       
    83 	if (!EnsureNoVehicle(tile))
       
    84 		return CMD_ERROR;
       
    85 
       
    86 	tile2 = tile + ((_map5[tile] & 2) ? TILE_XY(0,1) : TILE_XY(1,0));
       
    87 
       
    88 	if (!EnsureNoVehicle(tile2))
       
    89 		return CMD_ERROR;
       
    90 
       
    91 	if (flags & DC_EXEC) {
       
    92 		Depot *d;
       
    93 
       
    94 		// convert the cleared tiles to water
       
    95 		ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0);
       
    96 		ModifyTile(tile2, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0);
       
    97 
       
    98 		// Kill the entry from the depot table
       
    99 		for(d=_depots; d->xy != tile; d++) {}
       
   100 		d->xy = 0;
       
   101 				
       
   102 		DeleteWindowById(WC_VEHICLE_DEPOT, tile);		
       
   103 	}
       
   104 
       
   105 	return _price.remove_ship_depot;
       
   106 }
       
   107 
       
   108 // build a shiplift
       
   109 static int32 DoBuildShiplift(uint tile, int dir, uint32 flags)
       
   110 {
       
   111 	int32 ret;
       
   112 	int delta;
       
   113 
       
   114 	// middle tile
       
   115 	ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   116 	if (ret == CMD_ERROR) return CMD_ERROR;
       
   117 	
       
   118 	delta = _tileoffs_by_dir[dir];
       
   119 	// lower tile
       
   120 	ret = DoCommandByTile(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   121 	if (ret == CMD_ERROR) return CMD_ERROR;
       
   122 	if (GetTileSlope(tile - delta, NULL)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   123 
       
   124 	// upper tile
       
   125 	ret = DoCommandByTile(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   126 	if (ret == CMD_ERROR) return CMD_ERROR;
       
   127 	if (GetTileSlope(tile + delta, NULL)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   128 
       
   129 	if (flags & DC_EXEC) {
       
   130 		ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x10 + dir);
       
   131 		ModifyTile(tile - delta, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x14 + dir);
       
   132 		ModifyTile(tile + delta, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0x18 + dir);
       
   133 	}
       
   134 
       
   135 	return _price.clear_water * 22 >> 3;
       
   136 }
       
   137 
       
   138 static int32 RemoveShiplift(uint tile, uint32 flags)
       
   139 {
       
   140 	int delta = _tileoffs_by_dir[_map5[tile] & 3];
       
   141 
       
   142 	// make sure no vehicle is on the tile.
       
   143 	if (!EnsureNoVehicle(tile) || !EnsureNoVehicle(tile + delta) || !EnsureNoVehicle(tile - delta))
       
   144 		return CMD_ERROR;
       
   145 
       
   146 	if (flags & DC_EXEC) {
       
   147 		DoClearSquare(tile);
       
   148 		DoClearSquare(tile + delta);
       
   149 		DoClearSquare(tile - delta);
       
   150 	}
       
   151 	
       
   152 	return _price.clear_water * 2;
       
   153 }
       
   154 
       
   155 static void MarkTilesAroundDirty(uint tile)
       
   156 {
       
   157 	MarkTileDirtyByTile(TILE_ADDXY(tile, 0, 1));
       
   158 	MarkTileDirtyByTile(TILE_ADDXY(tile, 0, -1));
       
   159 	MarkTileDirtyByTile(TILE_ADDXY(tile, 1, 0));
       
   160 	MarkTileDirtyByTile(TILE_ADDXY(tile, -1, 0));
       
   161 }
       
   162 
       
   163 int32 CmdBuildLock(int x, int y, uint32 flags, uint32 p1, uint32 p2)
       
   164 {
       
   165 	uint tile = TILE_FROM_XY(x,y);
       
   166 	int32 ret;
       
   167 	uint th;
       
   168 	th = GetTileSlope(tile, NULL); 
       
   169 
       
   170 	if (th==3 || th==6 || th==9 || th==12) {
       
   171 		static const byte _shiplift_dirs[16] = {0,0,0,2,0,0,1,0,0,3,0,0,0};
       
   172 		ret = DoBuildShiplift(tile, _shiplift_dirs[th], flags);
       
   173 		return ret;
       
   174 		}
       
   175 	else
       
   176 		return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   177 
       
   178 	return 0;
       
   179 }
       
   180 
       
   181 int32 CmdBuildCanal(int x, int y, uint32 flags, uint32 p1, uint32 p2)
       
   182 {
       
   183 	uint tile = TILE_FROM_XY(x,y);
       
   184 	int32 ret;
       
   185 	uint th;
       
   186 	uint endtile = (uint)p1;
       
   187 	int delta;
       
   188 	int32 cost;
       
   189 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
       
   190 
       
   191 	// move in which direction?
       
   192 	delta = (GET_TILE_X(tile) == GET_TILE_X(endtile)) ? TILE_XY(0,1) : TILE_XY(1,0);
       
   193 	if (endtile < tile) delta = -delta;
       
   194 	
       
   195 	cost = 0;
       
   196 	for(;;) {
       
   197 		ret = 0;
       
   198 		th = GetTileSlope(tile, NULL);
       
   199 		if(th!=0)
       
   200 			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
       
   201 
       
   202 			// can't make water of water!
       
   203 			if (IS_TILETYPE(tile, MP_WATER)) {
       
   204 				_error_message = STR_1007_ALREADY_BUILT;
       
   205 			} else {
       
   206 
       
   207 				/* is middle piece of a bridge? */
       
   208 				if (IS_TILETYPE(tile, MP_TUNNELBRIDGE) && _map5[tile] & 0x40) { /* build under bridge */
       
   209 					if(_map5[tile] & 0x20) { // transport route under bridge
       
   210 						_error_message = STR_5800_OBJECT_IN_THE_WAY;
       
   211 						ret = CMD_ERROR;
       
   212 					}
       
   213 					else if (_map5[tile] & 0x18) { // already water under bridge
       
   214 						_error_message = STR_1007_ALREADY_BUILT;
       
   215 						ret = CMD_ERROR;
       
   216 					}
       
   217 
       
   218 				/* no bridge? then try to clear it. */
       
   219 				} else  {
       
   220 					ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
       
   221 				}
       
   222 				if (ret == CMD_ERROR) return ret;
       
   223 				cost += ret;
       
   224 
       
   225 				/* execute modifications */
       
   226 				if (flags & DC_EXEC) {
       
   227 					if(IS_TILETYPE(tile, MP_TUNNELBRIDGE)) {
       
   228 						// change owner to OWNER_WATER and set land under bridge bit to water
       
   229 						ModifyTile(tile, MP_MAP5 | MP_MAPOWNER, OWNER_WATER, _map5[tile] | 0x08);
       
   230 					} else {
       
   231 						ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR, OWNER_WATER, 0);
       
   232 					}
       
   233 					// mark the tiles around dirty too
       
   234 					MarkTilesAroundDirty(tile);
       
   235 				}
       
   236 
       
   237 				cost += _price.clear_water;
       
   238 			}
       
   239 		if (tile == endtile)
       
   240 			break;
       
   241 		tile += delta;
       
   242 	}
       
   243 	if (cost == 0) return CMD_ERROR;
       
   244 
       
   245 	return cost;
       
   246 }
       
   247 
       
   248 static int32 ClearTile_Water(uint tile, byte flags) {
       
   249 	byte m5 = _map5[tile];
       
   250 	uint slope;
       
   251 
       
   252 	if (m5 <= 1) { // water and shore
       
   253 		// Allow building on water? It's ok to build on shores.
       
   254 		if (flags & DC_NO_WATER && m5 != 1)
       
   255 			return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER);
       
   256 
       
   257 		// Make sure no vehicle is on the tile
       
   258 		if (!EnsureNoVehicle(tile))
       
   259 			return CMD_ERROR;
       
   260 
       
   261 		// Make sure it's not an edge tile.
       
   262 		if (!(IS_INT_INSIDE(GET_TILE_X(tile),1,TILE_X_MAX-1) &&
       
   263 				IS_INT_INSIDE(GET_TILE_Y(tile),1,TILE_Y_MAX-1)))
       
   264 			return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP);
       
   265 
       
   266 		if (m5 == 0) {
       
   267 			if (flags & DC_EXEC)
       
   268 				DoClearSquare(tile);
       
   269 			return _price.clear_water;
       
   270 		} else if (m5 == 1) {
       
   271 			slope = GetTileSlope(tile,NULL);
       
   272 			if (slope == 8 || slope == 4 || slope == 2 || slope == 1) {
       
   273 				if (flags & DC_EXEC)
       
   274 					DoClearSquare(tile);
       
   275 				return _price.clear_water;
       
   276 			}
       
   277 			if (flags & DC_EXEC)			
       
   278 				DoClearSquare(tile);
       
   279 			return _price.purchase_land;
       
   280 		} else
       
   281 			return CMD_ERROR;
       
   282 	} else if ((m5 & 0x10) == 0x10) {
       
   283 		// shiplift
       
   284 
       
   285 		static const TileIndexDiff _shiplift_tomiddle_offs[12] = {
       
   286 			0,0,0,0, // middle
       
   287 			TILE_XY(-1, 0),TILE_XY(0, 1),TILE_XY(1, 0),TILE_XY(0, -1), // lower
       
   288 			TILE_XY(1, 0),TILE_XY(0, -1),TILE_XY(-1, 0),TILE_XY(0, 1), // upper
       
   289 		};
       
   290 				
       
   291 		if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
       
   292 		// don't allow water to delete it.
       
   293 		if (_current_player == OWNER_WATER) return CMD_ERROR;
       
   294 		// move to the middle tile..
       
   295 		return RemoveShiplift(tile + _shiplift_tomiddle_offs[m5 & 0xF], flags);
       
   296 	} else {
       
   297 		// ship depot
       
   298 		if (flags & DC_AUTO)
       
   299 			return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED);
       
   300 
       
   301 		if (m5 == 0x80 || m5 == 0x82) {}
       
   302 		else if (m5 == 0x81) { tile -= TILE_XY(1,0); }
       
   303 		else if (m5 == 0x83) { tile -= TILE_XY(0,1); }
       
   304 		else
       
   305 			return CMD_ERROR;
       
   306 
       
   307 		return RemoveShipDepot(tile,flags);
       
   308 	}
       
   309 }
       
   310 
       
   311 // return true if a tile is a water tile.
       
   312 static bool IsWateredTile(uint tile)
       
   313 {
       
   314 	byte m5 = _map5[tile];
       
   315 	if (IS_TILETYPE(tile, MP_WATER)) {
       
   316 		return m5 != 1;	
       
   317 	} else if (IS_TILETYPE(tile, MP_STATION)) {
       
   318 		// returns true if it is a dock-station (m5 inside values is m5<75 all stations, 
       
   319 		// 83<=m5<=114 new airports
       
   320 		return !(m5 < 75 || (m5 >= 83 && m5 <= 114));
       
   321 	} else if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) {
       
   322 		return (m5 & 0xF8) == 0xC8;
       
   323 	} else
       
   324 		return false;
       
   325 }
       
   326 
       
   327 // draw a canal styled water tile with dikes around
       
   328 void DrawCanalWater(uint tile)
       
   329 {
       
   330 	uint wa;
       
   331 	
       
   332 	// determine the edges around with water.
       
   333 	wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0;
       
   334 	wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1;
       
   335 	wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2;
       
   336 	wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3;
       
   337 	
       
   338 	if (!(wa & 1)) DrawGroundSprite(SPR_CANALS_BASE + 57);
       
   339 	if (!(wa & 2)) DrawGroundSprite(SPR_CANALS_BASE + 58);
       
   340 	if (!(wa & 4)) DrawGroundSprite(SPR_CANALS_BASE + 59);
       
   341 	if (!(wa & 8)) DrawGroundSprite(SPR_CANALS_BASE + 60);
       
   342 
       
   343 	// right corner
       
   344 	if ((wa & 3) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 4);
       
   345 	else if ((wa & 3) == 3 && !IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 8);
       
   346 
       
   347 	// bottom corner
       
   348 	if ((wa & 6) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 5);
       
   349 	else if ((wa & 6) == 6 && !IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 9);
       
   350 
       
   351 	// left corner
       
   352 	if ((wa & 12) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 6);
       
   353 	else if ((wa & 12) == 12 && !IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 10);
       
   354 
       
   355 	// upper corner
       
   356 	if ((wa & 9) == 0) DrawGroundSprite(SPR_CANALS_BASE + 57 + 7);
       
   357 	else if ((wa & 9) == 9 && !IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 11);
       
   358 }
       
   359 
       
   360 typedef struct WaterDrawTileStruct {
       
   361 	int8 delta_x;
       
   362 	int8 delta_y;
       
   363 	int8 delta_z;
       
   364 	byte width;
       
   365 	byte height;
       
   366 	byte unk;
       
   367 	SpriteID image;
       
   368 } WaterDrawTileStruct;
       
   369 
       
   370 typedef struct LocksDrawTileStruct {
       
   371 	int8 delta_x, delta_y, delta_z;
       
   372 	byte width, height, depth;
       
   373 	SpriteID image;
       
   374 } LocksDrawTileStruct;
       
   375 
       
   376 #include "table/water_land.h"
       
   377 
       
   378 static void DrawWaterStuff(TileInfo *ti, const byte *t, uint32 palette, uint base)
       
   379 {
       
   380 	const WaterDrawTileStruct *wdts;
       
   381 	uint32 image;
       
   382 
       
   383 	DrawGroundSprite(*(uint16*)t);	
       
   384 	t += sizeof(uint16);
       
   385 		
       
   386 	for(wdts = (WaterDrawTileStruct *)t; (byte)wdts->delta_x != 0x80; wdts++) {
       
   387 		image =	wdts->image + base;
       
   388 		if (_display_opt & DO_TRANS_BUILDINGS) {
       
   389 			image |= palette;
       
   390 		} else {
       
   391 			image = (image & 0x3FFF) | 0x03224000;
       
   392 		}
       
   393 		AddSortableSpriteToDraw(image, ti->x + wdts->delta_x, ti->y + wdts->delta_y, wdts->width, wdts->height, wdts->unk, ti->z + wdts->delta_z);
       
   394 	}
       
   395 }
       
   396 
       
   397 static void DrawTile_Water(TileInfo *ti)
       
   398 {
       
   399 	// draw water tile
       
   400 	if (ti->map5 == 0) {
       
   401 		DrawGroundSprite(0xFDD);
       
   402 		if (ti->z != 0) DrawCanalWater(ti->tile);
       
   403 		return;
       
   404 	}
       
   405 
       
   406 	// draw shore
       
   407 	if (ti->map5 == 1) {
       
   408 		assert(ti->tileh < 16);
       
   409 		DrawGroundSprite(_water_shore_sprites[ti->tileh]);
       
   410 		return;
       
   411 	}
       
   412 
       
   413 	// draw shiplift
       
   414 	if ((ti->map5 & 0xF0) == 0x10) {
       
   415 		const byte *t = _shiplift_display_seq[ti->map5 & 0xF];
       
   416 		DrawWaterStuff(ti, t, 0, ti->z > t[19] ? 24 : 0);
       
   417 		return;
       
   418 	}
       
   419 
       
   420 	DrawWaterStuff(ti, _shipdepot_display_seq[ti->map5 & 0x7F], PLAYER_SPRITE_COLOR(_map_owner[ti->tile]), 0);
       
   421 }
       
   422 
       
   423 void DrawShipDepotSprite(int x, int y, int image)
       
   424 {
       
   425 	const byte *t;
       
   426 	const WaterDrawTileStruct *wdts;
       
   427 
       
   428 	t = _shipdepot_display_seq[image];
       
   429 	DrawSprite(*(uint16*)t, x, y);
       
   430 	t += sizeof(uint16);
       
   431 		
       
   432 	for(wdts = (WaterDrawTileStruct *)t; (byte)wdts->delta_x != 0x80; wdts++) {
       
   433 		Point pt = RemapCoords(wdts->delta_x, wdts->delta_y, wdts->delta_z);
       
   434 		DrawSprite(wdts->image + PLAYER_SPRITE_COLOR(_local_player), x + pt.x, y + pt.y);
       
   435 	}
       
   436 }
       
   437 
       
   438 
       
   439 uint GetSlopeZ_Water(TileInfo *ti)
       
   440 { 
       
   441 	return GetPartialZ(ti->x&0xF, ti->y&0xF, ti->tileh) + ti->z;
       
   442 }
       
   443 
       
   444 static void GetAcceptedCargo_Water(uint tile, AcceptedCargo *ac)
       
   445 {
       
   446 	/* not used */
       
   447 }
       
   448 
       
   449 static void GetTileDesc_Water(uint tile, TileDesc *td)
       
   450 {
       
   451 	if (_map5[tile] == 0 && GET_TILEHEIGHT(tile) == 0)
       
   452 		td->str = STR_3804_WATER;
       
   453 	else if (_map5[tile] == 0)
       
   454 		td->str = STR_LANDINFO_CANAL;
       
   455 	else if (_map5[tile] == 1)
       
   456 		td->str = STR_3805_COAST_OR_RIVERBANK;
       
   457 	else if ((_map5[tile]&0xF0) == 0x10)
       
   458 		td->str = STR_LANDINFO_LOCK;
       
   459 	else
       
   460 		td->str = STR_3806_SHIP_DEPOT;
       
   461 
       
   462 	td->owner = _map_owner[tile];
       
   463 }
       
   464 
       
   465 static void AnimateTile_Water(uint tile)
       
   466 {
       
   467 	/* not used */
       
   468 }
       
   469 
       
   470 static void TileLoopWaterHelper(uint tile, const int16 *offs)
       
   471 {
       
   472 	byte *p;
       
   473 
       
   474 	p = &_map_type_and_height[tile];
       
   475 	tile += offs[0];
       
   476 
       
   477 	// type of this tile mustn't be water already.
       
   478 	if (p[offs[0]] >> 4 == MP_WATER)
       
   479 		return;
       
   480 
       
   481 	if ( (p[offs[1]] | p[offs[2]]) & 0xF )
       
   482 		return;
       
   483 
       
   484 	if ( (p[offs[3]] | p[offs[4]]) & 0xF ) {
       
   485 		// make coast..
       
   486 		if (p[offs[0]] >> 4 == MP_CLEAR || p[offs[0]] >> 4 == MP_TREES) {
       
   487 			_current_player = OWNER_WATER;
       
   488 			if (DoCommandByTile(tile,0,0,DC_EXEC | DC_AUTO, CMD_LANDSCAPE_CLEAR) != CMD_ERROR)
       
   489 				ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,OWNER_WATER,1);
       
   490 		}
       
   491 	} else {
       
   492 		if (IS_TILETYPE(tile, MP_TUNNELBRIDGE)) {
       
   493 			byte m5 = _map5[tile];
       
   494 			if ( (m5&0xF8) == 0xC8 || (m5&0xF8) == 0xF0)
       
   495 				return;
       
   496 
       
   497 			if ( (m5&0xC0) == 0xC0) {
       
   498 				ModifyTile(tile, MP_MAPOWNER | MP_MAP5,OWNER_WATER,(m5 & ~0x38)|0x8);
       
   499 				return;
       
   500 			}
       
   501 		}
       
   502 
       
   503 		_current_player = OWNER_WATER;
       
   504 		if (DoCommandByTile(tile,0,0,DC_EXEC, CMD_LANDSCAPE_CLEAR) != CMD_ERROR)
       
   505 			ModifyTile(tile, MP_SETTYPE(MP_WATER) | MP_MAPOWNER | MP_MAP5 | MP_MAP2_CLEAR | MP_MAP3LO_CLEAR | MP_MAP3HI_CLEAR,OWNER_WATER,0);
       
   506 	}
       
   507 }
       
   508 
       
   509 // called from tunnelbridge_cmd
       
   510 void TileLoop_Water(uint tile)
       
   511 {
       
   512 	int i;
       
   513 	static const TileIndexDiff _tile_loop_offs_array[4][5] = {
       
   514 		// tile to mod																shore?				shore?
       
   515 		{TILE_XY(-1,0), TILE_XY(0,0), TILE_XY(0,1), TILE_XY(-1,0), TILE_XY(-1,1)},
       
   516 		{TILE_XY(0,1),  TILE_XY(0,1), TILE_XY(1,1), TILE_XY(0,2),  TILE_XY(1,2)},
       
   517 		{TILE_XY(1,0),  TILE_XY(1,0), TILE_XY(1,1), TILE_XY(2,0),  TILE_XY(2,1)},
       
   518 		{TILE_XY(0,-1), TILE_XY(0,0), TILE_XY(1,0), TILE_XY(0,-1), TILE_XY(1,-1)},
       
   519 	};
       
   520 
       
   521 	if ( IS_INT_INSIDE(GET_TILE_X(tile),1,TILES_X-3+1) &&
       
   522 	     IS_INT_INSIDE(GET_TILE_Y(tile),1,TILES_Y-3+1)) {
       
   523 		for(i=0; i!=4; i++)
       
   524 			TileLoopWaterHelper(tile, _tile_loop_offs_array[i]);
       
   525 	}
       
   526 }
       
   527 
       
   528 
       
   529 static const byte _coast_tracks[16] = {0, 32, 4, 0, 16, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0};
       
   530 static const byte _shipdepot_tracks[4] = {1,1,2,2};
       
   531 static const byte _shiplift_tracks[12] = {1,2,1,2,1,2,1,2,1,2,1,2};
       
   532 static uint32 GetTileTrackStatus_Water(uint tile, int mode)
       
   533 {
       
   534 	uint m5;
       
   535 	uint b;
       
   536 
       
   537 	if (mode != 4)
       
   538 		return 0;
       
   539 
       
   540 	m5 = _map5[tile];
       
   541 	if (m5 == 0)
       
   542 		return 0x3F3F;
       
   543 
       
   544 	if (m5 == 1) {
       
   545 		b = _coast_tracks[GetTileSlope(tile, NULL)&0xF];
       
   546 		return b + (b<<8);
       
   547 	}
       
   548 
       
   549 	if ( (m5 & 0x10) == 0x10) {
       
   550 		// 
       
   551 		b = _shiplift_tracks[m5 & 0xF];
       
   552 		return b + (b<<8);
       
   553 	}
       
   554 
       
   555 	if (!(m5 & 0x80))
       
   556 		return 0;
       
   557 
       
   558 	b = _shipdepot_tracks[m5 & 0x7F];
       
   559 	return b + (b<<8);
       
   560 }
       
   561 
       
   562 extern void ShowShipDepotWindow(uint tile);
       
   563 
       
   564 static void ClickTile_Water(uint tile)
       
   565 {
       
   566 	byte m5 = _map5[tile] - 0x80;
       
   567 	
       
   568 	if (IS_BYTE_INSIDE(m5, 0, 3+1)) {
       
   569 		if (m5 & 1)
       
   570 			tile += (m5==1) ? TILE_XY(-1,0) : TILE_XY(0,-1);
       
   571 		ShowShipDepotWindow(tile);
       
   572 	}
       
   573 }
       
   574 
       
   575 static void ChangeTileOwner_Water(uint tile, byte old_player, byte new_player)
       
   576 {
       
   577 	if (_map_owner[tile] != old_player)
       
   578 		return;
       
   579 
       
   580 	if (new_player != 255) {
       
   581 		_map_owner[tile] = new_player;
       
   582 	} else {
       
   583 		DoCommandByTile(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
       
   584 	}
       
   585 }
       
   586 
       
   587 static uint32 VehicleEnter_Water(Vehicle *v, uint tile, int x, int y)
       
   588 {
       
   589 	return 0;
       
   590 }
       
   591 
       
   592 void InitializeDock()
       
   593 {
       
   594 	_last_built_ship_depot_tile = 0;
       
   595 }
       
   596 
       
   597 const TileTypeProcs _tile_type_water_procs = {
       
   598 	DrawTile_Water,						/* draw_tile_proc */
       
   599 	GetSlopeZ_Water,					/* get_slope_z_proc */
       
   600 	ClearTile_Water,					/* clear_tile_proc */
       
   601 	GetAcceptedCargo_Water,		/* get_accepted_cargo_proc */
       
   602 	GetTileDesc_Water,				/* get_tile_desc_proc */
       
   603 	GetTileTrackStatus_Water,	/* get_tile_track_status_proc */
       
   604 	ClickTile_Water,					/* click_tile_proc */
       
   605 	AnimateTile_Water,				/* animate_tile_proc */
       
   606 	TileLoop_Water,						/* tile_loop_clear */
       
   607 	ChangeTileOwner_Water,		/* change_tile_owner_clear */
       
   608 	NULL,											/* get_produced_cargo_proc */
       
   609 	VehicleEnter_Water,				/* vehicle_enter_tile_proc */
       
   610 	NULL,											/* vehicle_leave_tile_proc */
       
   611 };
       
   612