|
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 |