45 static Vehicle *FindFloodableVehicleOnTile(TileIndex tile); |
47 static Vehicle *FindFloodableVehicleOnTile(TileIndex tile); |
46 static void FloodVehicle(Vehicle *v); |
48 static void FloodVehicle(Vehicle *v); |
47 |
49 |
48 /** Build a ship depot. |
50 /** Build a ship depot. |
49 * @param tile tile where ship depot is built |
51 * @param tile tile where ship depot is built |
|
52 * @param flags type of operation |
50 * @param p1 bit 0 depot orientation (Axis) |
53 * @param p1 bit 0 depot orientation (Axis) |
51 * @param p2 unused |
54 * @param p2 unused |
52 */ |
55 */ |
53 int32 CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
56 int32 CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
54 { |
57 { |
74 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
77 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
75 if (CmdFailed(ret)) return CMD_ERROR; |
78 if (CmdFailed(ret)) return CMD_ERROR; |
76 ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
79 ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
77 if (CmdFailed(ret)) return CMD_ERROR; |
80 if (CmdFailed(ret)) return CMD_ERROR; |
78 |
81 |
79 // pretend that we're not making land from the water even though we actually are. |
82 /* pretend that we're not making land from the water even though we actually are. */ |
80 cost = 0; |
83 cost = 0; |
81 |
84 |
82 depot = AllocateDepot(); |
85 depot = AllocateDepot(); |
83 if (depot == NULL) return CMD_ERROR; |
86 if (depot == NULL) return CMD_ERROR; |
84 |
87 |
118 } |
121 } |
119 |
122 |
120 return _price.remove_ship_depot; |
123 return _price.remove_ship_depot; |
121 } |
124 } |
122 |
125 |
123 // build a shiplift |
126 /** build a shiplift */ |
124 static int32 DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 flags) |
127 static int32 DoBuildShiplift(TileIndex tile, DiagDirection dir, uint32 flags) |
125 { |
128 { |
126 int32 ret; |
129 int32 ret; |
127 int delta; |
130 int delta; |
128 |
131 |
129 // middle tile |
132 /* middle tile */ |
130 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
133 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
131 if (CmdFailed(ret)) return CMD_ERROR; |
134 if (CmdFailed(ret)) return CMD_ERROR; |
132 |
135 |
133 delta = TileOffsByDiagDir(dir); |
136 delta = TileOffsByDiagDir(dir); |
134 // lower tile |
137 /* lower tile */ |
135 ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
138 ret = DoCommand(tile - delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
136 if (CmdFailed(ret)) return CMD_ERROR; |
139 if (CmdFailed(ret)) return CMD_ERROR; |
137 if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) { |
140 if (GetTileSlope(tile - delta, NULL) != SLOPE_FLAT) { |
138 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
141 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
139 } |
142 } |
140 |
143 |
141 // upper tile |
144 /* upper tile */ |
142 ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
145 ret = DoCommand(tile + delta, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
143 if (CmdFailed(ret)) return CMD_ERROR; |
146 if (CmdFailed(ret)) return CMD_ERROR; |
144 if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) { |
147 if (GetTileSlope(tile + delta, NULL) != SLOPE_FLAT) { |
145 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
148 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
146 } |
149 } |
209 return DoBuildShiplift(tile, dir, flags); |
213 return DoBuildShiplift(tile, dir, flags); |
210 } |
214 } |
211 |
215 |
212 /** Build a piece of canal. |
216 /** Build a piece of canal. |
213 * @param tile end tile of stretch-dragging |
217 * @param tile end tile of stretch-dragging |
|
218 * @param flags type of operation |
214 * @param p1 start tile of stretch-dragging |
219 * @param p1 start tile of stretch-dragging |
215 * @param p2 ctrl pressed - toggles ocean / canals at sealevel (ocean only allowed in the scenario editor) |
220 * @param p2 ctrl pressed - toggles ocean / canals at sealevel (ocean only allowed in the scenario editor) |
216 */ |
221 */ |
217 int32 CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
222 int32 CmdBuildCanal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
218 { |
223 { |
247 |
252 |
248 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) { |
253 if (GetTileSlope(tile, NULL) != SLOPE_FLAT) { |
249 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
254 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
250 } |
255 } |
251 |
256 |
252 // can't make water of water! |
257 /* can't make water of water! */ |
253 if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || HASBIT(p2, 0))) continue; |
258 if (IsTileType(tile, MP_WATER) && (!IsTileOwner(tile, OWNER_WATER) || HASBIT(p2, 0))) continue; |
254 |
259 |
255 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
260 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
256 if (CmdFailed(ret)) return ret; |
261 if (CmdFailed(ret)) return ret; |
257 cost += ret; |
262 cost += ret; |
280 { |
285 { |
281 switch (GetWaterTileType(tile)) { |
286 switch (GetWaterTileType(tile)) { |
282 case WATER_TILE_CLEAR: |
287 case WATER_TILE_CLEAR: |
283 if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
288 if (flags & DC_NO_WATER) return_cmd_error(STR_3807_CAN_T_BUILD_ON_WATER); |
284 |
289 |
285 // Make sure no vehicle is on the tile |
290 /* Make sure no vehicle is on the tile */ |
286 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
291 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
287 |
292 |
288 // Make sure it's not an edge tile. |
293 /* Make sure it's not an edge tile. */ |
289 if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || |
294 if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || |
290 !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { |
295 !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { |
291 return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); |
296 return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); |
292 } |
297 } |
293 |
298 |
297 return _price.clear_water; |
302 return _price.clear_water; |
298 |
303 |
299 case WATER_TILE_COAST: { |
304 case WATER_TILE_COAST: { |
300 Slope slope = GetTileSlope(tile, NULL); |
305 Slope slope = GetTileSlope(tile, NULL); |
301 |
306 |
302 // Make sure no vehicle is on the tile |
307 /* Make sure no vehicle is on the tile */ |
303 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
308 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
304 |
309 |
305 // Make sure it's not an edge tile. |
310 /* Make sure it's not an edge tile. */ |
306 if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || |
311 if (!IS_INT_INSIDE(TileX(tile), 1, MapMaxX() - 1) || |
307 !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { |
312 !IS_INT_INSIDE(TileY(tile), 1, MapMaxY() - 1)) { |
308 return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); |
313 return_cmd_error(STR_0002_TOO_CLOSE_TO_EDGE_OF_MAP); |
309 } |
314 } |
310 |
315 |
323 { 1, 0}, {0, -1}, {-1, 0}, {0, 1}, // upper |
328 { 1, 0}, {0, -1}, {-1, 0}, {0, 1}, // upper |
324 }; |
329 }; |
325 |
330 |
326 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
331 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
327 if (_current_player == OWNER_WATER) return CMD_ERROR; |
332 if (_current_player == OWNER_WATER) return CMD_ERROR; |
328 // move to the middle tile.. |
333 /* move to the middle tile.. */ |
329 return RemoveShiplift(tile + ToTileIndexDiff(_shiplift_tomiddle_offs[GetSection(tile)]), flags); |
334 return RemoveShiplift(tile + ToTileIndexDiff(_shiplift_tomiddle_offs[GetSection(tile)]), flags); |
330 } |
335 } |
331 |
336 |
332 case WATER_TILE_DEPOT: |
337 case WATER_TILE_DEPOT: |
333 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
338 if (flags & DC_AUTO) return_cmd_error(STR_2004_BUILDING_MUST_BE_DEMOLISHED); |
360 case MP_STATION: return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile); |
365 case MP_STATION: return IsOilRig(tile) || IsDock(tile) || IsBuoy(tile); |
361 default: return false; |
366 default: return false; |
362 } |
367 } |
363 } |
368 } |
364 |
369 |
365 // draw a canal styled water tile with dikes around |
370 /** draw a canal styled water tile with dikes around */ |
366 void DrawCanalWater(TileIndex tile) |
371 void DrawCanalWater(TileIndex tile) |
367 { |
372 { |
368 uint wa; |
373 uint wa; |
369 |
374 |
370 // determine the edges around with water. |
375 /* determine the edges around with water. */ |
371 wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0; |
376 wa = IsWateredTile(TILE_ADDXY(tile, -1, 0)) << 0; |
372 wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1; |
377 wa += IsWateredTile(TILE_ADDXY(tile, 0, 1)) << 1; |
373 wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2; |
378 wa += IsWateredTile(TILE_ADDXY(tile, 1, 0)) << 2; |
374 wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3; |
379 wa += IsWateredTile(TILE_ADDXY(tile, 0, -1)) << 3; |
375 |
380 |
376 if (!(wa & 1)) DrawGroundSprite(SPR_CANALS_BASE + 57, PAL_NONE); |
381 if (!(wa & 1)) DrawGroundSprite(SPR_CANALS_BASE + 57, PAL_NONE); |
377 if (!(wa & 2)) DrawGroundSprite(SPR_CANALS_BASE + 58, PAL_NONE); |
382 if (!(wa & 2)) DrawGroundSprite(SPR_CANALS_BASE + 58, PAL_NONE); |
378 if (!(wa & 4)) DrawGroundSprite(SPR_CANALS_BASE + 59, PAL_NONE); |
383 if (!(wa & 4)) DrawGroundSprite(SPR_CANALS_BASE + 59, PAL_NONE); |
379 if (!(wa & 8)) DrawGroundSprite(SPR_CANALS_BASE + 60, PAL_NONE); |
384 if (!(wa & 8)) DrawGroundSprite(SPR_CANALS_BASE + 60, PAL_NONE); |
380 |
385 |
381 // right corner |
386 /* right corner */ |
382 switch (wa & 0x03) { |
387 switch (wa & 0x03) { |
383 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 4, PAL_NONE); break; |
388 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 4, PAL_NONE); break; |
384 case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 8, PAL_NONE); break; |
389 case 3: if (!IsWateredTile(TILE_ADDXY(tile, -1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 8, PAL_NONE); break; |
385 } |
390 } |
386 |
391 |
387 // bottom corner |
392 /* bottom corner */ |
388 switch (wa & 0x06) { |
393 switch (wa & 0x06) { |
389 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 5, PAL_NONE); break; |
394 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 5, PAL_NONE); break; |
390 case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 9, PAL_NONE); break; |
395 case 6: if (!IsWateredTile(TILE_ADDXY(tile, 1, 1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 9, PAL_NONE); break; |
391 } |
396 } |
392 |
397 |
393 // left corner |
398 /* left corner */ |
394 switch (wa & 0x0C) { |
399 switch (wa & 0x0C) { |
395 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 6, PAL_NONE); break; |
400 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 6, PAL_NONE); break; |
396 case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 10, PAL_NONE); break; |
401 case 12: if (!IsWateredTile(TILE_ADDXY(tile, 1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 10, PAL_NONE); break; |
397 } |
402 } |
398 |
403 |
399 // upper corner |
404 /* upper corner */ |
400 switch (wa & 0x09) { |
405 switch (wa & 0x09) { |
401 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 7, PAL_NONE); break; |
406 case 0: DrawGroundSprite(SPR_CANALS_BASE + 57 + 7, PAL_NONE); break; |
402 case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 11, PAL_NONE); break; |
407 case 9: if (!IsWateredTile(TILE_ADDXY(tile, -1, -1))) DrawGroundSprite(SPR_CANALS_BASE + 57 + 11, PAL_NONE); break; |
403 } |
408 } |
404 } |
409 } |
522 |
527 |
523 static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs) |
528 static void TileLoopWaterHelper(TileIndex tile, const TileIndexDiffC *offs) |
524 { |
529 { |
525 TileIndex target = TILE_ADD(tile, ToTileIndexDiff(offs[0])); |
530 TileIndex target = TILE_ADD(tile, ToTileIndexDiff(offs[0])); |
526 |
531 |
527 // type of this tile mustn't be water already. |
532 /* type of this tile mustn't be water already. */ |
528 if (IsTileType(target, MP_WATER)) return; |
533 if (IsTileType(target, MP_WATER)) return; |
529 |
534 |
530 if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[1]))) != 0 || |
535 if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[1]))) != 0 || |
531 TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[2]))) != 0) { |
536 TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[2]))) != 0) { |
532 return; |
537 return; |
533 } |
538 } |
534 |
539 |
535 if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[3]))) != 0 || |
540 if (TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[3]))) != 0 || |
536 TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[4]))) != 0) { |
541 TileHeight(TILE_ADD(tile, ToTileIndexDiff(offs[4]))) != 0) { |
537 // make coast.. |
542 /* make coast.. */ |
538 switch (GetTileType(target)) { |
543 switch (GetTileType(target)) { |
539 case MP_RAILWAY: { |
544 case MP_RAILWAY: { |
540 TrackBits tracks; |
545 TrackBits tracks; |
541 Slope slope; |
546 Slope slope; |
542 |
547 |
624 |
629 |
625 v = GetFirstVehicleInChain(v); |
630 v = GetFirstVehicleInChain(v); |
626 u = v; |
631 u = v; |
627 if (IsFrontEngine(v)) pass = 4; // driver |
632 if (IsFrontEngine(v)) pass = 4; // driver |
628 |
633 |
629 // crash all wagons, and count passangers |
634 /* crash all wagons, and count passangers */ |
630 BEGIN_ENUM_WAGONS(v) |
635 BEGIN_ENUM_WAGONS(v) |
631 if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count; |
636 if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo_count; |
632 v->vehstatus |= VS_CRASHED; |
637 v->vehstatus |= VS_CRASHED; |
633 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
638 MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); |
634 END_ENUM_WAGONS(v) |
639 END_ENUM_WAGONS(v) |
651 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
656 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE); |
652 SndPlayVehicleFx(SND_12_EXPLOSION, v); |
657 SndPlayVehicleFx(SND_12_EXPLOSION, v); |
653 } |
658 } |
654 } |
659 } |
655 |
660 |
656 // called from tunnelbridge_cmd, and by TileLoop_Industry() |
661 /** called from tunnelbridge_cmd, and by TileLoop_Industry() */ |
657 void TileLoop_Water(TileIndex tile) |
662 void TileLoop_Water(TileIndex tile) |
658 { |
663 { |
659 static const TileIndexDiffC _tile_loop_offs_array[][5] = { |
664 static const TileIndexDiffC _tile_loop_offs_array[][5] = { |
660 // tile to mod shore? shore? |
665 // tile to mod shore? shore? |
661 {{-1, 0}, {0, 0}, {0, 1}, {-1, 0}, {-1, 1}}, |
666 {{-1, 0}, {0, 0}, {0, 1}, {-1, 0}, {-1, 1}}, |
673 |
678 |
674 for (i = 0; i != lengthof(_tile_loop_offs_array); i++) { |
679 for (i = 0; i != lengthof(_tile_loop_offs_array); i++) { |
675 TileLoopWaterHelper(tile, _tile_loop_offs_array[i]); |
680 TileLoopWaterHelper(tile, _tile_loop_offs_array[i]); |
676 } |
681 } |
677 } |
682 } |
678 // _current_player can be changed by TileLoopWaterHelper.. reset it back |
683 /* _current_player can be changed by TileLoopWaterHelper.. reset it back here */ |
679 // here |
|
680 _current_player = OWNER_NONE; |
684 _current_player = OWNER_NONE; |
681 |
685 |
682 // edges |
686 /* edges */ |
683 if (TileX(tile) == 0 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //NE |
687 if (TileX(tile) == 0 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //NE |
684 TileLoopWaterHelper(tile, _tile_loop_offs_array[2]); |
688 TileLoopWaterHelper(tile, _tile_loop_offs_array[2]); |
685 } |
689 } |
686 |
690 |
687 if (TileX(tile) == MapSizeX() - 2 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //SW |
691 if (TileX(tile) == MapSizeX() - 2 && IS_INT_INSIDE(TileY(tile), 1, MapSizeY() - 3 + 1)) { //SW |
711 case WATER_TILE_LOCK: ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break; |
715 case WATER_TILE_LOCK: ts = AxisToTrackBits(DiagDirToAxis(GetLockDirection(tile))); break; |
712 case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break; |
716 case WATER_TILE_DEPOT: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break; |
713 default: return 0; |
717 default: return 0; |
714 } |
718 } |
715 if (TileX(tile) == 0) { |
719 if (TileX(tile) == 0) { |
716 // NE border: remove tracks that connects NE tile edge |
720 /* NE border: remove tracks that connects NE tile edge */ |
717 ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT); |
721 ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT); |
718 } |
722 } |
719 if (TileY(tile) == 0) { |
723 if (TileY(tile) == 0) { |
720 // NW border: remove tracks that connects NW tile edge |
724 /* NW border: remove tracks that connects NW tile edge */ |
721 ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER); |
725 ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER); |
722 } |
726 } |
723 return ts * 0x101; |
727 return ts * 0x101; |
724 } |
728 } |
725 |
729 |