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