changeset 6422 | 6679df1c05ba |
parent 6406 | 8ccf18e94c67 |
child 6427 | 7dc1012757d8 |
6421:a9b1588c13ee | 6422:6679df1c05ba |
---|---|
59 }; |
59 }; |
60 |
60 |
61 Bridge _bridge[MAX_BRIDGES]; |
61 Bridge _bridge[MAX_BRIDGES]; |
62 |
62 |
63 |
63 |
64 // calculate the price factor for building a long bridge. |
64 /** calculate the price factor for building a long bridge. |
65 // basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6, 7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8, |
65 * basically the cost delta is 1,1, 1, 2,2, 3,3,3, 4,4,4,4, 5,5,5,5,5, 6,6,6,6,6,6, 7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8, |
66 */ |
|
66 int CalcBridgeLenCostFactor(int x) |
67 int CalcBridgeLenCostFactor(int x) |
67 { |
68 { |
68 int n; |
69 int n; |
69 int r; |
70 int r; |
70 |
71 |
77 } |
78 } |
78 } |
79 } |
79 |
80 |
80 #define M(x) (1 << (x)) |
81 #define M(x) (1 << (x)) |
81 enum BridgeFoundation { |
82 enum BridgeFoundation { |
82 // foundation, whole tile is leveled up --> 3 corners raised |
83 /* foundation, whole tile is leveled up --> 3 corners raised */ |
83 BRIDGE_FULL_LEVELED_FOUNDATION = M(SLOPE_WSE) | M(SLOPE_NWS) | M(SLOPE_ENW) | M(SLOPE_SEN), |
84 BRIDGE_FULL_LEVELED_FOUNDATION = M(SLOPE_WSE) | M(SLOPE_NWS) | M(SLOPE_ENW) | M(SLOPE_SEN), |
84 // foundation, tile is partly leveled up --> 1 corner raised |
85 /* foundation, tile is partly leveled up --> 1 corner raised */ |
85 BRIDGE_PARTLY_LEVELED_FOUNDATION = M(SLOPE_W) | M(SLOPE_S) | M(SLOPE_E) | M(SLOPE_N), |
86 BRIDGE_PARTLY_LEVELED_FOUNDATION = M(SLOPE_W) | M(SLOPE_S) | M(SLOPE_E) | M(SLOPE_N), |
86 // no foundations (X,Y direction) |
87 /* no foundations (X,Y direction) */ |
87 BRIDGE_NO_FOUNDATION = M(SLOPE_FLAT) | M(SLOPE_SW) | M(SLOPE_SE) | M(SLOPE_NW) | M(SLOPE_NE), |
88 BRIDGE_NO_FOUNDATION = M(SLOPE_FLAT) | M(SLOPE_SW) | M(SLOPE_SE) | M(SLOPE_NW) | M(SLOPE_NE), |
88 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~M(SLOPE_FLAT) |
89 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~M(SLOPE_FLAT) |
89 }; |
90 }; |
90 #undef M |
91 #undef M |
91 |
92 |
165 return b->min_length <= bridge_len && bridge_len <= max; |
166 return b->min_length <= bridge_len && bridge_len <= max; |
166 } |
167 } |
167 |
168 |
168 /** Build a Bridge |
169 /** Build a Bridge |
169 * @param end_tile end tile |
170 * @param end_tile end tile |
171 * @param flags type of operation |
|
170 * @param p1 packed start tile coords (~ dx) |
172 * @param p1 packed start tile coords (~ dx) |
171 * @param p2 various bitstuffed elements |
173 * @param p2 various bitstuffed elements |
172 * - p2 = (bit 0- 7) - bridge type (hi bh) |
174 * - p2 = (bit 0- 7) - bridge type (hi bh) |
173 * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge. |
175 * - p2 = (bit 8-..) - rail type. bit15 ((x>>8)&0x80) means road bridge. |
174 */ |
176 */ |
200 /* unpack parameters */ |
202 /* unpack parameters */ |
201 bridge_type = GB(p2, 0, 8); |
203 bridge_type = GB(p2, 0, 8); |
202 |
204 |
203 if (p1 >= MapSize()) return CMD_ERROR; |
205 if (p1 >= MapSize()) return CMD_ERROR; |
204 |
206 |
205 // type of bridge |
207 /* type of bridge */ |
206 if (HASBIT(p2, 15)) { |
208 if (HASBIT(p2, 15)) { |
207 railtype = INVALID_RAILTYPE; // road bridge |
209 railtype = INVALID_RAILTYPE; // road bridge |
208 } else { |
210 } else { |
209 if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR; |
211 if (!ValParamRailtype(GB(p2, 8, 8))) return CMD_ERROR; |
210 railtype = (RailType)GB(p2, 8, 8); |
212 railtype = (RailType)GB(p2, 8, 8); |
253 tileh_end = SLOPE_FLAT; |
255 tileh_end = SLOPE_FLAT; |
254 } |
256 } |
255 |
257 |
256 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
258 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
257 |
259 |
258 // Towns are not allowed to use bridges on slopes. |
260 /* Towns are not allowed to use bridges on slopes. */ |
259 allow_on_slopes = (!_is_old_ai_player |
261 allow_on_slopes = (!_is_old_ai_player |
260 && _current_player != OWNER_TOWN && _patches.build_on_slopes); |
262 && _current_player != OWNER_TOWN && _patches.build_on_slopes); |
261 |
263 |
262 TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL; |
264 TransportType transport_type = railtype == INVALID_RAILTYPE ? TRANSPORT_ROAD : TRANSPORT_RAIL; |
263 |
265 |
313 /* Try and clear the end landscape */ |
315 /* Try and clear the end landscape */ |
314 ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
316 ret = DoCommand(tile_end, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
315 if (CmdFailed(ret)) return ret; |
317 if (CmdFailed(ret)) return ret; |
316 cost += ret; |
318 cost += ret; |
317 |
319 |
318 // false - end tile slope check |
320 /* false - end tile slope check */ |
319 terraformcost = CheckBridgeSlopeSouth(direction, tileh_end); |
321 terraformcost = CheckBridgeSlopeSouth(direction, tileh_end); |
320 if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes)) |
322 if (CmdFailed(terraformcost) || (terraformcost != 0 && !allow_on_slopes)) |
321 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
323 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
322 cost += terraformcost; |
324 cost += terraformcost; |
323 } |
325 } |
437 } |
439 } |
438 |
440 |
439 |
441 |
440 /** Build Tunnel. |
442 /** Build Tunnel. |
441 * @param tile start tile of tunnel |
443 * @param tile start tile of tunnel |
444 * @param flags type of operation |
|
442 * @param p1 railtype, 0x200 for road tunnel |
445 * @param p1 railtype, 0x200 for road tunnel |
443 * @param p2 unused |
446 * @param p2 unused |
444 */ |
447 */ |
445 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) |
448 int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) |
446 { |
449 { |
494 } |
497 } |
495 |
498 |
496 /* Add the cost of the entrance */ |
499 /* Add the cost of the entrance */ |
497 cost += _price.build_tunnel + ret; |
500 cost += _price.build_tunnel + ret; |
498 |
501 |
499 // if the command fails from here on we want the end tile to be highlighted |
502 /* if the command fails from here on we want the end tile to be highlighted */ |
500 _build_tunnel_endtile = end_tile; |
503 _build_tunnel_endtile = end_tile; |
501 |
504 |
502 // slope of end tile must be complementary to the slope of the start tile |
505 /* slope of end tile must be complementary to the slope of the start tile */ |
503 if (end_tileh != ComplementSlope(start_tileh)) { |
506 if (end_tileh != ComplementSlope(start_tileh)) { |
504 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
507 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
505 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
508 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
506 } else { |
509 } else { |
507 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
510 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
589 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
592 return_cmd_error(STR_2009_LOCAL_AUTHORITY_REFUSES); |
590 } |
593 } |
591 } |
594 } |
592 |
595 |
593 if (flags & DC_EXEC) { |
596 if (flags & DC_EXEC) { |
594 // We first need to request the direction before calling DoClearSquare |
597 /* We first need to request the direction before calling DoClearSquare |
595 // else the direction is always 0.. dah!! ;) |
598 * else the direction is always 0.. dah!! ;) */ |
596 DiagDirection dir = GetTunnelDirection(tile); |
599 DiagDirection dir = GetTunnelDirection(tile); |
597 Track track; |
600 Track track; |
598 |
601 |
599 // Adjust the town's player rating. Do this before removing the tile owner info. |
602 /* Adjust the town's player rating. Do this before removing the tile owner info. */ |
600 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
603 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
601 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
604 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
602 |
605 |
603 DoClearSquare(tile); |
606 DoClearSquare(tile); |
604 DoClearSquare(endtile); |
607 DoClearSquare(endtile); |
659 |
662 |
660 if (flags & DC_EXEC) { |
663 if (flags & DC_EXEC) { |
661 TileIndex c; |
664 TileIndex c; |
662 Track track; |
665 Track track; |
663 |
666 |
664 //checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until |
667 /* checks if the owner is town then decrease town rating by RATING_TUNNEL_BRIDGE_DOWN_STEP until |
665 // you have a "Poor" (0) town rating |
668 * you have a "Poor" (0) town rating */ |
666 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
669 if (IsTileOwner(tile, OWNER_TOWN) && _game_mode != GM_EDITOR) |
667 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
670 ChangeTownRating(t, RATING_TUNNEL_BRIDGE_DOWN_STEP, RATING_TUNNEL_BRIDGE_MINIMUM); |
668 |
671 |
669 DoClearSquare(tile); |
672 DoClearSquare(tile); |
670 DoClearSquare(endtile); |
673 DoClearSquare(endtile); |
715 |
718 |
716 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
719 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
717 |
720 |
718 if (GetRailType(tile) == totype) return CMD_ERROR; |
721 if (GetRailType(tile) == totype) return CMD_ERROR; |
719 |
722 |
720 // 'hidden' elrails can't be downgraded to normal rail when elrails are disabled |
723 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
721 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
724 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
722 |
725 |
723 endtile = CheckTunnelBusy(tile, &length); |
726 endtile = CheckTunnelBusy(tile, &length); |
724 if (endtile == INVALID_TILE) return CMD_ERROR; |
727 if (endtile == INVALID_TILE) return CMD_ERROR; |
725 |
728 |
827 { |
830 { |
828 uint i; |
831 uint i; |
829 |
832 |
830 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh; |
833 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh; |
831 |
834 |
832 // inclined sloped building |
835 /* inclined sloped building */ |
833 switch (tileh) { |
836 switch (tileh) { |
834 case SLOPE_W: |
837 case SLOPE_W: |
835 case SLOPE_STEEP_W: i = 0; break; |
838 case SLOPE_STEEP_W: i = 0; break; |
836 case SLOPE_S: |
839 case SLOPE_S: |
837 case SLOPE_STEEP_S: i = 2; break; |
840 case SLOPE_STEEP_S: i = 2; break; |
848 /** |
851 /** |
849 * Draws a tunnel of bridge tile. |
852 * Draws a tunnel of bridge tile. |
850 * For tunnels, this is rather simple, as you only needa draw the entrance. |
853 * For tunnels, this is rather simple, as you only needa draw the entrance. |
851 * Bridges are a bit more complex. base_offset is where the sprite selection comes into play |
854 * Bridges are a bit more complex. base_offset is where the sprite selection comes into play |
852 * and it works a bit like a bitmask.<p> For bridge heads: |
855 * and it works a bit like a bitmask.<p> For bridge heads: |
856 * @param ti TileInfo of the structure to draw |
|
853 * <ul><li>Bit 0: direction</li> |
857 * <ul><li>Bit 0: direction</li> |
854 * <li>Bit 1: northern or southern heads</li> |
858 * <li>Bit 1: northern or southern heads</li> |
855 * <li>Bit 2: Set if the bridge head is sloped</li> |
859 * <li>Bit 2: Set if the bridge head is sloped</li> |
856 * <li>Bit 3 and more: Railtype Specific subset</li> |
860 * <li>Bit 3 and more: Railtype Specific subset</li> |
857 * </ul> |
861 * </ul> |
882 int base_offset; |
886 int base_offset; |
883 bool ice = HasBridgeSnowOrDesert(ti->tile); |
887 bool ice = HasBridgeSnowOrDesert(ti->tile); |
884 |
888 |
885 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
889 if (GetBridgeTransportType(ti->tile) == TRANSPORT_RAIL) { |
886 base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset; |
890 base_offset = GetRailTypeInfo(GetRailType(ti->tile))->bridge_offset; |
887 assert(base_offset != 8); /* This one is used for roads */ |
891 assert(base_offset != 8); // This one is used for roads |
888 } else { |
892 } else { |
889 base_offset = 8; |
893 base_offset = 8; |
890 } |
894 } |
891 |
895 |
892 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
896 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
895 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
899 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
896 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
900 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
897 if (f != 0) DrawFoundation(ti, f); |
901 if (f != 0) DrawFoundation(ti, f); |
898 } |
902 } |
899 |
903 |
900 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
904 /* HACK Wizardry to convert the bridge ramp direction into a sprite offset */ |
901 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
905 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
902 |
906 |
903 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
907 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
904 |
908 |
905 /* Table number 6 always refers to the bridge heads for any bridge type */ |
909 /* Table number 6 always refers to the bridge heads for any bridge type */ |
913 |
917 |
914 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
918 if (GetRailType(ti->tile) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
915 |
919 |
916 image = psid->sprite; |
920 image = psid->sprite; |
917 |
921 |
918 // draw ramp |
922 /* draw ramp */ |
919 if (_display_opt & DO_TRANS_BUILDINGS) { |
923 if (_display_opt & DO_TRANS_BUILDINGS) { |
920 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
924 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
921 pal = PALETTE_TO_TRANSPARENT; |
925 pal = PALETTE_TO_TRANSPARENT; |
922 } else { |
926 } else { |
923 pal = psid->pal; |
927 pal = psid->pal; |
1028 pal = PALETTE_TO_TRANSPARENT; |
1032 pal = PALETTE_TO_TRANSPARENT; |
1029 } else { |
1033 } else { |
1030 pal = psid->pal; |
1034 pal = psid->pal; |
1031 } |
1035 } |
1032 |
1036 |
1033 // draw roof, the component of the bridge which is logically between the vehicle and the camera |
1037 /* draw roof, the component of the bridge which is logically between the vehicle and the camera */ |
1034 if (axis == AXIS_X) { |
1038 if (axis == AXIS_X) { |
1035 y += 12; |
1039 y += 12; |
1036 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 16, 1, 0x28, z); |
1040 if (image & SPRITE_MASK) AddSortableSpriteToDraw(image, pal, x, y, 16, 1, 0x28, z); |
1037 } else { |
1041 } else { |
1038 x += 12; |
1042 x += 12; |
1041 |
1045 |
1042 if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1046 if (GetRailType(rampsouth) == RAILTYPE_ELECTRIC) DrawCatenary(ti); |
1043 |
1047 |
1044 psid++; |
1048 psid++; |
1045 if (ti->z + 5 == z) { |
1049 if (ti->z + 5 == z) { |
1046 // draw poles below for small bridges |
1050 /* draw poles below for small bridges */ |
1047 if (psid->sprite != 0) { |
1051 if (psid->sprite != 0) { |
1048 image = psid->sprite; |
1052 image = psid->sprite; |
1049 if (_display_opt & DO_TRANS_BUILDINGS) { |
1053 if (_display_opt & DO_TRANS_BUILDINGS) { |
1050 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1054 SETBIT(image, PALETTE_MODIFIER_TRANSPARENT); |
1051 pal = PALETTE_TO_TRANSPARENT; |
1055 pal = PALETTE_TO_TRANSPARENT; |
1054 } |
1058 } |
1055 |
1059 |
1056 DrawGroundSpriteAt(image, pal, x, y, z); |
1060 DrawGroundSpriteAt(image, pal, x, y, z); |
1057 } |
1061 } |
1058 } else if (_patches.bridge_pillars) { |
1062 } else if (_patches.bridge_pillars) { |
1059 // draw pillars below for high bridges |
1063 /* draw pillars below for high bridges */ |
1060 DrawBridgePillars(psid, ti, axis, type, x, y, z); |
1064 DrawBridgePillars(psid, ti, axis, type, x, y, z); |
1061 } |
1065 } |
1062 } |
1066 } |
1063 |
1067 |
1064 |
1068 |
1071 y &= 0xF; |
1075 y &= 0xF; |
1072 |
1076 |
1073 if (IsTunnel(tile)) { |
1077 if (IsTunnel(tile)) { |
1074 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1078 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1075 |
1079 |
1076 // In the tunnel entrance? |
1080 /* In the tunnel entrance? */ |
1077 if (5 <= pos && pos <= 10) return z; |
1081 if (5 <= pos && pos <= 10) return z; |
1078 } else { |
1082 } else { |
1079 DiagDirection dir = GetBridgeRampDirection(tile); |
1083 DiagDirection dir = GetBridgeRampDirection(tile); |
1080 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
1084 uint pos = (DiagDirToAxis(dir) == AXIS_X ? y : x); |
1081 |
1085 |
1082 // On the bridge ramp? |
1086 /* On the bridge ramp? */ |
1083 if (5 <= pos && pos <= 10) { |
1087 if (5 <= pos && pos <= 10) { |
1084 uint delta; |
1088 uint delta; |
1085 |
1089 |
1086 if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2; |
1090 if (IsSteepSlope(tileh)) return z + TILE_HEIGHT * 2; |
1087 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
1091 if (HASBIT(BRIDGE_HORZ_RAMP, tileh)) return z + TILE_HEIGHT; |
1300 } else if (v->type == VEH_ROAD) { |
1304 } else if (v->type == VEH_ROAD) { |
1301 fc = (x & 0xF) + (y << 4); |
1305 fc = (x & 0xF) + (y << 4); |
1302 dir = GetTunnelDirection(tile); |
1306 dir = GetTunnelDirection(tile); |
1303 vdir = DirToDiagDir(v->direction); |
1307 vdir = DirToDiagDir(v->direction); |
1304 |
1308 |
1305 // Enter tunnel? |
1309 /* Enter tunnel? */ |
1306 if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) { |
1310 if (v->u.road.state != RVSB_WORMHOLE && dir == vdir) { |
1307 if (fc == _tunnel_fractcoord_4[dir] || |
1311 if (fc == _tunnel_fractcoord_4[dir] || |
1308 fc == _tunnel_fractcoord_5[dir]) { |
1312 fc == _tunnel_fractcoord_5[dir]) { |
1309 v->tile = tile; |
1313 v->tile = tile; |
1310 v->u.road.state = RVSB_WORMHOLE; |
1314 v->u.road.state = RVSB_WORMHOLE; |