248 if (x > sx) Swap(x, sx); |
250 if (x > sx) Swap(x, sx); |
249 } else { |
251 } else { |
250 return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN); |
252 return_cmd_error(STR_500A_START_AND_END_MUST_BE_IN); |
251 } |
253 } |
252 |
254 |
253 /* set and test bridge length, availability */ |
|
254 bridge_len = sx + sy - x - y - 1; |
255 bridge_len = sx + sy - x - y - 1; |
255 if (!CheckBridge_Stuff(bridge_type, bridge_len)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE); |
256 if (transport_type != TRANSPORT_WATER) { |
|
257 /* set and test bridge length, availability */ |
|
258 if (!CheckBridge_Stuff(bridge_type, bridge_len)) return_cmd_error(STR_5015_CAN_T_BUILD_BRIDGE_HERE); |
|
259 } |
256 |
260 |
257 /* retrieve landscape height and ensure it's on land */ |
261 /* retrieve landscape height and ensure it's on land */ |
258 tile_start = TileXY(x, y); |
262 tile_start = TileXY(x, y); |
259 tile_end = TileXY(sx, sy); |
263 tile_end = TileXY(sx, sy); |
260 if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) { |
264 if (IsWaterTile(tile_start) || IsWaterTile(tile_end)) { |
309 /* Do not remove road types when upgrading a bridge */ |
313 /* Do not remove road types when upgrading a bridge */ |
310 roadtypes |= GetRoadTypes(tile_start); |
314 roadtypes |= GetRoadTypes(tile_start); |
311 } else { |
315 } else { |
312 /* Build a new bridge. */ |
316 /* Build a new bridge. */ |
313 |
317 |
314 bool allow_on_slopes = (!_is_old_ai_player && _settings_game.construction.build_on_slopes); |
318 bool allow_on_slopes = (!_is_old_ai_player && _settings_game.construction.build_on_slopes && transport_type != TRANSPORT_WATER); |
315 |
319 |
316 /* Try and clear the start landscape */ |
320 /* Try and clear the start landscape */ |
317 ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
321 ret = DoCommand(tile_start, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
318 if (CmdFailed(ret)) return ret; |
322 if (CmdFailed(ret)) return ret; |
319 cost = ret; |
323 cost = ret; |
329 |
333 |
330 /* false - end tile slope check */ |
334 /* false - end tile slope check */ |
331 if (CmdFailed(terraform_cost_south) || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) |
335 if (CmdFailed(terraform_cost_south) || (terraform_cost_south.GetCost() != 0 && !allow_on_slopes)) |
332 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
336 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
333 cost.AddCost(terraform_cost_south); |
337 cost.AddCost(terraform_cost_south); |
|
338 |
|
339 if (transport_type == TRANSPORT_WATER && (tileh_start == SLOPE_FLAT || tileh_end == SLOPE_FLAT)) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
334 } |
340 } |
335 |
341 |
336 if (!replace_bridge) { |
342 if (!replace_bridge) { |
337 TileIndex Heads[] = {tile_start, tile_end}; |
343 TileIndex Heads[] = {tile_start, tile_end}; |
338 int i; |
344 int i; |
364 break; |
370 break; |
365 |
371 |
366 case TRANSPORT_ROAD: |
372 case TRANSPORT_ROAD: |
367 MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes); |
373 MakeRoadBridgeRamp(tile_start, owner, bridge_type, dir, roadtypes); |
368 MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes); |
374 MakeRoadBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), roadtypes); |
|
375 break; |
|
376 |
|
377 case TRANSPORT_WATER: |
|
378 MakeAqueductBridgeRamp(tile_start, owner, dir); |
|
379 MakeAqueductBridgeRamp(tile_end, owner, ReverseDiagDir(dir)); |
369 break; |
380 break; |
370 |
381 |
371 default: |
382 default: |
372 NOT_REACHED(); |
383 NOT_REACHED(); |
373 break; |
384 break; |
722 * @param type Bridge type. |
736 * @param type Bridge type. |
723 * @param x Sprite X position of front pillar. |
737 * @param x Sprite X position of front pillar. |
724 * @param y Sprite Y position of front pillar. |
738 * @param y Sprite Y position of front pillar. |
725 * @param z_bridge Absolute height of bridge bottom. |
739 * @param z_bridge Absolute height of bridge bottom. |
726 */ |
740 */ |
727 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, BridgeType type, int x, int y, int z_bridge) |
741 static void DrawBridgePillars(const PalSpriteID *psid, const TileInfo* ti, Axis axis, bool drawfarpillar, int x, int y, int z_bridge) |
728 { |
742 { |
729 /* Do not draw bridge pillars if they are invisible */ |
743 /* Do not draw bridge pillars if they are invisible */ |
730 if (IsInvisibilitySet(TO_BRIDGES)) return; |
744 if (IsInvisibilitySet(TO_BRIDGES)) return; |
731 |
745 |
732 SpriteID image = psid->sprite; |
746 SpriteID image = psid->sprite; |
733 |
747 |
734 if (image != 0) { |
748 if (image != 0) { |
735 bool drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0); |
|
736 |
|
737 /* "side" specifies the side the pillars stand on. |
749 /* "side" specifies the side the pillars stand on. |
738 * The length of the pillars is then set to the height of the bridge over the corners of this edge. |
750 * The length of the pillars is then set to the height of the bridge over the corners of this edge. |
739 * |
751 * |
740 * axis==AXIS_X axis==AXIS_Y |
752 * axis==AXIS_X axis==AXIS_Y |
741 * side==false SW NW |
753 * side==false SW NW |
924 base_offset += (6 - tunnelbridge_direction) % 4; |
936 base_offset += (6 - tunnelbridge_direction) % 4; |
925 |
937 |
926 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
938 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
927 |
939 |
928 /* Table number 6 always refers to the bridge heads for any bridge type */ |
940 /* Table number 6 always refers to the bridge heads for any bridge type */ |
929 psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
941 if (transport_type != TRANSPORT_WATER) { |
|
942 psid = &GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
|
943 } else { |
|
944 psid = _aqueduct_sprites + base_offset; |
|
945 } |
930 |
946 |
931 if (!ice) { |
947 if (!ice) { |
932 DrawClearLandTile(ti, 3); |
948 DrawClearLandTile(ti, 3); |
933 } else { |
949 } else { |
934 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE); |
950 DrawGroundSprite(SPR_FLAT_SNOWY_TILE + _tileh_to_sprite[ti->tileh], PAL_NONE); |
1021 */ |
1037 */ |
1022 |
1038 |
1023 /* Z position of the bridge sprites relative to bridge height (downwards) */ |
1039 /* Z position of the bridge sprites relative to bridge height (downwards) */ |
1024 static const int BRIDGE_Z_START = 3; |
1040 static const int BRIDGE_Z_START = 3; |
1025 |
1041 |
1026 const PalSpriteID* psid; |
|
1027 uint base_offset; |
|
1028 TileIndex rampnorth; |
|
1029 TileIndex rampsouth; |
|
1030 TransportType transport_type; |
|
1031 Axis axis; |
|
1032 uint piece; |
|
1033 BridgeType type; |
|
1034 int x; |
|
1035 int y; |
|
1036 uint z; |
|
1037 |
|
1038 if (!IsBridgeAbove(ti->tile)) return; |
1042 if (!IsBridgeAbove(ti->tile)) return; |
1039 |
1043 |
1040 rampnorth = GetNorthernBridgeEnd(ti->tile); |
1044 TileIndex rampnorth = GetNorthernBridgeEnd(ti->tile); |
1041 rampsouth = GetSouthernBridgeEnd(ti->tile); |
1045 TileIndex rampsouth = GetSouthernBridgeEnd(ti->tile); |
1042 transport_type = GetTunnelBridgeTransportType(rampsouth); |
1046 TransportType transport_type = GetTunnelBridgeTransportType(rampsouth); |
1043 |
1047 |
1044 axis = GetBridgeAxis(ti->tile); |
1048 Axis axis = GetBridgeAxis(ti->tile); |
1045 piece = CalcBridgePiece( |
1049 uint piece = CalcBridgePiece( |
1046 GetTunnelBridgeLength(ti->tile, rampnorth) + 1, |
1050 GetTunnelBridgeLength(ti->tile, rampnorth) + 1, |
1047 GetTunnelBridgeLength(ti->tile, rampsouth) + 1 |
1051 GetTunnelBridgeLength(ti->tile, rampsouth) + 1 |
1048 ); |
1052 ); |
1049 type = GetBridgeType(rampsouth); |
1053 |
1050 |
1054 const PalSpriteID *psid; |
1051 if (transport_type == TRANSPORT_RAIL) { |
1055 bool drawfarpillar; |
1052 base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset; |
1056 if (transport_type != TRANSPORT_WATER) { |
|
1057 BridgeType type = GetBridgeType(rampsouth); |
|
1058 drawfarpillar = !HasBit(GetBridgeSpec(type)->flags, 0); |
|
1059 |
|
1060 uint base_offset; |
|
1061 if (transport_type == TRANSPORT_RAIL) { |
|
1062 base_offset = GetRailTypeInfo(GetRailType(rampsouth))->bridge_offset; |
|
1063 } else { |
|
1064 base_offset = 8; |
|
1065 } |
|
1066 |
|
1067 psid = base_offset + GetBridgeSpriteTable(type, piece); |
1053 } else { |
1068 } else { |
1054 base_offset = 8; |
1069 drawfarpillar = true; |
1055 } |
1070 psid = _aqueduct_sprites; |
1056 |
1071 } |
1057 psid = base_offset + GetBridgeSpriteTable(type, piece); |
1072 |
1058 if (axis != AXIS_X) psid += 4; |
1073 if (axis != AXIS_X) psid += 4; |
1059 |
1074 |
1060 x = ti->x; |
1075 int x = ti->x; |
1061 y = ti->y; |
1076 int y = ti->y; |
1062 uint bridge_z = GetBridgeHeight(rampsouth); |
1077 uint bridge_z = GetBridgeHeight(rampsouth); |
1063 z = bridge_z - BRIDGE_Z_START; |
1078 uint z = bridge_z - BRIDGE_Z_START; |
1064 |
1079 |
1065 /* Add a bounding box, that separates the bridge from things below it. */ |
1080 /* Add a bounding box, that separates the bridge from things below it. */ |
1066 AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR); |
1081 AddSortableSpriteToDraw(SPR_EMPTY_BOUNDING_BOX, PAL_NONE, x, y, 16, 16, 1, bridge_z - TILE_HEIGHT + BB_Z_SEPARATOR); |
1067 |
1082 |
1068 /* Draw Trambits as SpriteCombine */ |
1083 /* Draw Trambits as SpriteCombine */ |
1123 |
1138 |
1124 DrawGroundSpriteAt(image, pal, x, y, z); |
1139 DrawGroundSpriteAt(image, pal, x, y, z); |
1125 } |
1140 } |
1126 } else if (_settings_client.gui.bridge_pillars) { |
1141 } else if (_settings_client.gui.bridge_pillars) { |
1127 /* draw pillars below for high bridges */ |
1142 /* draw pillars below for high bridges */ |
1128 DrawBridgePillars(psid, ti, axis, type, x, y, z); |
1143 DrawBridgePillars(psid, ti, axis, drawfarpillar, x, y, z); |
1129 } |
1144 } |
1130 } |
1145 } |
1131 |
1146 |
1132 |
1147 |
1133 static uint GetSlopeZ_TunnelBridge(TileIndex tile, uint x, uint y) |
1148 static uint GetSlopeZ_TunnelBridge(TileIndex tile, uint x, uint y) |
1180 /* not used */ |
1195 /* not used */ |
1181 } |
1196 } |
1182 |
1197 |
1183 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td) |
1198 static void GetTileDesc_TunnelBridge(TileIndex tile, TileDesc *td) |
1184 { |
1199 { |
|
1200 TransportType tt = GetTunnelBridgeTransportType(tile); |
|
1201 |
1185 if (IsTunnel(tile)) { |
1202 if (IsTunnel(tile)) { |
1186 td->str = (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) ? |
1203 td->str = (tt == TRANSPORT_RAIL) ? STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL; |
1187 STR_5017_RAILROAD_TUNNEL : STR_5018_ROAD_TUNNEL; |
1204 } else { // IsBridge(tile) |
1188 } else { //so it must be a bridge |
1205 td->str = (tt == TRANSPORT_WATER) ? STR_AQUEDUCT : GetBridgeSpec(GetBridgeType(tile))->transport_name[tt]; |
1189 td->str = GetBridgeSpec(GetBridgeType(tile))->transport_name[GetTunnelBridgeTransportType(tile)]; |
|
1190 } |
1206 } |
1191 td->owner[0] = GetTileOwner(tile); |
1207 td->owner[0] = GetTileOwner(tile); |
1192 } |
1208 } |
1193 |
1209 |
1194 |
1210 |
1244 SetTileOwner(tile, new_player); |
1260 SetTileOwner(tile, new_player); |
1245 } else { |
1261 } else { |
1246 if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR))) { |
1262 if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR))) { |
1247 /* When clearing the bridge/tunnel failed there are still vehicles on/in |
1263 /* When clearing the bridge/tunnel failed there are still vehicles on/in |
1248 * the bridge/tunnel. As all *our* vehicles are already removed, they |
1264 * the bridge/tunnel. As all *our* vehicles are already removed, they |
1249 * must be of another owner. Therefor this must be a road bridge/tunnel. |
1265 * must be of another owner. Therefore this can't be rail tunnel/bridge. |
1250 * In that case we can safely reassign the ownership to OWNER_NONE. */ |
1266 * In that case we can safely reassign the ownership to OWNER_NONE. */ |
1251 assert(GetTunnelBridgeTransportType(tile) == TRANSPORT_ROAD); |
1267 assert(GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL); |
1252 SetTileOwner(tile, OWNER_NONE); |
1268 SetTileOwner(tile, OWNER_NONE); |
1253 } |
1269 } |
1254 } |
1270 } |
1255 } |
1271 } |
1256 |
1272 |
1340 return VETSB_ENTERED_WORMHOLE; |
1356 return VETSB_ENTERED_WORMHOLE; |
1341 } |
1357 } |
1342 } |
1358 } |
1343 } else { // IsBridge(tile) |
1359 } else { // IsBridge(tile) |
1344 |
1360 |
1345 if (v->IsPrimaryVehicle()) { |
1361 if (v->IsPrimaryVehicle() && v->type != VEH_SHIP) { |
1346 /* modify speed of vehicle */ |
1362 /* modify speed of vehicle */ |
1347 uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed; |
1363 uint16 spd = GetBridgeSpec(GetBridgeType(tile))->speed; |
1348 |
1364 |
1349 if (v->type == VEH_ROAD) spd *= 2; |
1365 if (v->type == VEH_ROAD) spd *= 2; |
1350 if (v->cur_speed > spd) v->cur_speed = spd; |
1366 if (v->cur_speed > spd) v->cur_speed = spd; |
1356 case DIAGDIR_NE: if ((x & 0xF) != 0) return VETSB_CONTINUE; break; |
1372 case DIAGDIR_NE: if ((x & 0xF) != 0) return VETSB_CONTINUE; break; |
1357 case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; |
1373 case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; |
1358 case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; |
1374 case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break; |
1359 case DIAGDIR_NW: if ((y & 0xF) != 0) return VETSB_CONTINUE; break; |
1375 case DIAGDIR_NW: if ((y & 0xF) != 0) return VETSB_CONTINUE; break; |
1360 } |
1376 } |
1361 if (v->type == VEH_TRAIN) { |
1377 switch (v->type) { |
1362 v->u.rail.track = TRACK_BIT_WORMHOLE; |
1378 case VEH_TRAIN: |
1363 ClrBit(v->u.rail.flags, VRF_GOINGUP); |
1379 v->u.rail.track = TRACK_BIT_WORMHOLE; |
1364 ClrBit(v->u.rail.flags, VRF_GOINGDOWN); |
1380 ClrBit(v->u.rail.flags, VRF_GOINGUP); |
1365 } else { |
1381 ClrBit(v->u.rail.flags, VRF_GOINGDOWN); |
1366 v->u.road.state = RVSB_WORMHOLE; |
1382 break; |
|
1383 |
|
1384 case VEH_ROAD: |
|
1385 v->u.road.state = RVSB_WORMHOLE; |
|
1386 break; |
|
1387 |
|
1388 case VEH_SHIP: |
|
1389 v->u.ship.state = TRACK_BIT_WORMHOLE; |
|
1390 break; |
|
1391 |
|
1392 default: NOT_REACHED(); |
1367 } |
1393 } |
1368 return VETSB_ENTERED_WORMHOLE; |
1394 return VETSB_ENTERED_WORMHOLE; |
1369 } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { |
1395 } else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) { |
1370 v->tile = tile; |
1396 v->tile = tile; |
1371 if (v->type == VEH_TRAIN) { |
1397 switch (v->type) { |
1372 if (v->u.rail.track == TRACK_BIT_WORMHOLE) { |
1398 case VEH_TRAIN: |
1373 v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); |
1399 if (v->u.rail.track == TRACK_BIT_WORMHOLE) { |
1374 return VETSB_ENTERED_WORMHOLE; |
1400 v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); |
1375 } |
1401 return VETSB_ENTERED_WORMHOLE; |
1376 } else { |
1402 } |
1377 if (v->u.road.state == RVSB_WORMHOLE) { |
1403 break; |
1378 v->u.road.state = _road_exit_tunnel_state[dir]; |
1404 |
1379 v->u.road.frame = 0; |
1405 case VEH_ROAD: |
1380 return VETSB_ENTERED_WORMHOLE; |
1406 if (v->u.road.state == RVSB_WORMHOLE) { |
1381 } |
1407 v->u.road.state = _road_exit_tunnel_state[dir]; |
1382 } |
1408 v->u.road.frame = 0; |
1383 return VETSB_CONTINUE; |
1409 return VETSB_ENTERED_WORMHOLE; |
|
1410 } |
|
1411 break; |
|
1412 |
|
1413 case VEH_SHIP: |
|
1414 if (v->u.ship.state == TRACK_BIT_WORMHOLE) { |
|
1415 v->u.ship.state = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y); |
|
1416 return VETSB_ENTERED_WORMHOLE; |
|
1417 } |
|
1418 break; |
|
1419 |
|
1420 default: NOT_REACHED(); |
|
1421 } |
1384 } |
1422 } |
1385 } |
1423 } |
1386 return VETSB_CONTINUE; |
1424 return VETSB_CONTINUE; |
1387 } |
1425 } |
1388 |
1426 |
1389 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1427 static CommandCost TerraformTile_TunnelBridge(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1390 { |
1428 { |
1391 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile)) { |
1429 if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() && IsBridge(tile) && GetTunnelBridgeTransportType(tile) != TRANSPORT_WATER) { |
1392 DiagDirection direction = GetTunnelBridgeDirection(tile); |
1430 DiagDirection direction = GetTunnelBridgeDirection(tile); |
1393 Axis axis = DiagDirToAxis(direction); |
1431 Axis axis = DiagDirToAxis(direction); |
1394 CommandCost res; |
1432 CommandCost res; |
1395 uint z_old; |
1433 uint z_old; |
1396 Slope tileh_old = GetTileSlope(tile, &z_old); |
1434 Slope tileh_old = GetTileSlope(tile, &z_old); |