75 r += n * n; |
75 r += n * n; |
76 x -= n; |
76 x -= n; |
77 } |
77 } |
78 } |
78 } |
79 |
79 |
|
80 #define M(x) (1 << (x)) |
80 enum { |
81 enum { |
81 // foundation, whole tile is leveled up (tileh's 7, 11, 13, 14) --> 3 corners raised |
82 // foundation, whole tile is leveled up --> 3 corners raised |
82 BRIDGE_FULL_LEVELED_FOUNDATION = 1 << 7 | 1 << 11 | 1 << 13 | 1 << 14, |
83 BRIDGE_FULL_LEVELED_FOUNDATION = M(SLOPE_WSE) | M(SLOPE_NWS) | M(SLOPE_ENW) | M(SLOPE_SEN), |
83 // foundation, tile is partly leveled up (tileh's 1, 2, 4, 8) --> 1 corner raised |
84 // foundation, tile is partly leveled up --> 1 corner raised |
84 BRIDGE_PARTLY_LEVELED_FOUNDATION = 1 << 1 | 1 << 2 | 1 << 4 | 1 << 8, |
85 BRIDGE_PARTLY_LEVELED_FOUNDATION = M(SLOPE_W) | M(SLOPE_S) | M(SLOPE_E) | M(SLOPE_N), |
85 // no foundations (X,Y direction) (tileh's 0, 3, 6, 9, 12) |
86 // no foundations (X,Y direction) |
86 BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12, |
87 BRIDGE_NO_FOUNDATION = M(SLOPE_FLAT) | M(SLOPE_SW) | M(SLOPE_SE) | M(SLOPE_NW) | M(SLOPE_NE), |
87 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~(1 << 0) |
88 BRIDGE_HORZ_RAMP = (BRIDGE_PARTLY_LEVELED_FOUNDATION | BRIDGE_NO_FOUNDATION) & ~M(SLOPE_FLAT) |
88 }; |
89 }; |
|
90 #undef M |
89 |
91 |
90 static inline const PalSpriteID *GetBridgeSpriteTable(int index, byte table) |
92 static inline const PalSpriteID *GetBridgeSpriteTable(int index, byte table) |
91 { |
93 { |
92 const Bridge *bridge = &_bridge[index]; |
94 const Bridge *bridge = &_bridge[index]; |
93 assert(table < 7); |
95 assert(table < 7); |
103 /** check if bridge can be built on slope |
105 /** check if bridge can be built on slope |
104 * direction 0 = X-axis, direction 1 = Y-axis |
106 * direction 0 = X-axis, direction 1 = Y-axis |
105 * is_start_tile = false <-- end tile |
107 * is_start_tile = false <-- end tile |
106 * is_start_tile = true <-- start tile |
108 * is_start_tile = true <-- start tile |
107 */ |
109 */ |
108 static uint32 CheckBridgeSlope(Axis direction, uint tileh, bool is_start_tile) |
110 static uint32 CheckBridgeSlope(Axis direction, Slope tileh, bool is_start_tile) |
109 { |
111 { |
110 if (IsSteepTileh(tileh)) return CMD_ERROR; |
112 if (IsSteepSlope(tileh)) return CMD_ERROR; |
111 |
113 |
112 if (is_start_tile) { |
114 if (is_start_tile) { |
113 /* check slope at start tile |
115 /* check slope at start tile |
114 - no extra cost |
116 - no extra cost |
115 - direction X: tiles 0, 12 |
|
116 - direction Y: tiles 0, 9 |
|
117 */ |
117 */ |
118 if ((direction == AXIS_X ? 0x1001 : 0x201) & (1 << tileh)) return 0; |
118 #define M(x) (1 << (x)) |
|
119 if (HASBIT(M(SLOPE_FLAT) | (direction == AXIS_X ? M(SLOPE_NE) : M(SLOPE_NW)), tileh)) return 0; |
119 |
120 |
120 // disallow certain start tiles to avoid certain crooked bridges |
121 // disallow certain start tiles to avoid certain crooked bridges |
121 if (tileh == 2) return CMD_ERROR; |
122 if (tileh == SLOPE_S) return CMD_ERROR; |
122 } else { |
123 } else { |
123 /* check slope at end tile |
124 /* check slope at end tile |
124 - no extra cost |
125 - no extra cost |
125 - direction X: tiles 0, 3 |
|
126 - direction Y: tiles 0, 6 |
|
127 */ |
126 */ |
128 if ((direction == AXIS_X ? 0x9 : 0x41) & (1 << tileh)) return 0; |
127 if (HASBIT(M(SLOPE_FLAT) | (direction == AXIS_X ? M(SLOPE_SW) : M(SLOPE_SE)), tileh)) return 0; |
|
128 #undef M |
129 |
129 |
130 // disallow certain end tiles to avoid certain crooked bridges |
130 // disallow certain end tiles to avoid certain crooked bridges |
131 if (tileh == 8) return CMD_ERROR; |
131 if (tileh == SLOPE_N) return CMD_ERROR; |
132 } |
132 } |
133 |
133 |
134 /* disallow common start/end tiles to avoid certain crooked bridges e.g. |
134 /* disallow common start/end tiles to avoid certain crooked bridges e.g. |
135 * start-tile: X 2,1 Y 2,4 (2 was disabled before) |
135 * start-tile: X 2,1 Y 2,4 (2 was disabled before) |
136 * end-tile: X 8,4 Y 8,1 (8 was disabled before) |
136 * end-tile: X 8,4 Y 8,1 (8 was disabled before) |
137 */ |
137 */ |
138 if ((tileh == 1 && is_start_tile != (direction != AXIS_X)) || |
138 if ((tileh == SLOPE_W && is_start_tile != (direction != AXIS_X)) || |
139 (tileh == 4 && is_start_tile == (direction != AXIS_X))) { |
139 (tileh == SLOPE_E && is_start_tile == (direction != AXIS_X))) { |
140 return CMD_ERROR; |
140 return CMD_ERROR; |
141 } |
141 } |
142 |
142 |
143 // slope foundations |
143 // slope foundations |
144 if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh) || BRIDGE_PARTLY_LEVELED_FOUNDATION & (1 << tileh)) |
144 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION | BRIDGE_PARTLY_LEVELED_FOUNDATION, tileh)) |
145 return _price.terraform; |
145 return _price.terraform; |
146 |
146 |
147 return CMD_ERROR; |
147 return CMD_ERROR; |
148 } |
148 } |
149 |
149 |
251 if (IsClearWaterTile(tile_start) || IsClearWaterTile(tile_end)) return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH); |
251 if (IsClearWaterTile(tile_start) || IsClearWaterTile(tile_end)) return_cmd_error(STR_02A0_ENDS_OF_BRIDGE_MUST_BOTH); |
252 |
252 |
253 tileh_start = GetTileSlope(tile_start, &z_start); |
253 tileh_start = GetTileSlope(tile_start, &z_start); |
254 tileh_end = GetTileSlope(tile_end, &z_end); |
254 tileh_end = GetTileSlope(tile_end, &z_end); |
255 |
255 |
256 if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh_start)) { |
256 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh_start)) { |
257 z_start += 8; |
257 z_start += 8; |
258 tileh_start = 0; |
258 tileh_start = SLOPE_FLAT; |
259 } |
259 } |
260 |
260 |
261 if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh_end)) { |
261 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh_end)) { |
262 z_end += 8; |
262 z_end += 8; |
263 tileh_end = 0; |
263 tileh_end = SLOPE_FLAT; |
264 } |
264 } |
265 |
265 |
266 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
266 if (z_start != z_end) return_cmd_error(STR_5009_LEVEL_LAND_OR_WATER_REQUIRED); |
267 |
267 |
268 // Towns are not allowed to use bridges on slopes. |
268 // Towns are not allowed to use bridges on slopes. |
449 if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; |
449 if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR; |
450 |
450 |
451 start_tileh = GetTileSlope(start_tile, &start_z); |
451 start_tileh = GetTileSlope(start_tile, &start_z); |
452 |
452 |
453 switch (start_tileh) { |
453 switch (start_tileh) { |
454 case 3: direction = DIAGDIR_SW; break; |
454 case SLOPE_SW: direction = DIAGDIR_SW; break; |
455 case 6: direction = DIAGDIR_SE; break; |
455 case SLOPE_SE: direction = DIAGDIR_SE; break; |
456 case 9: direction = DIAGDIR_NW; break; |
456 case SLOPE_NW: direction = DIAGDIR_NW; break; |
457 case 12: direction = DIAGDIR_NE; break; |
457 case SLOPE_NE: direction = DIAGDIR_NE; break; |
458 default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); |
458 default: return_cmd_error(STR_500B_SITE_UNSUITABLE_FOR_TUNNEL); |
459 } |
459 } |
460 |
460 |
461 ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
461 ret = DoCommand(start_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
462 if (CmdFailed(ret)) return ret; |
462 if (CmdFailed(ret)) return ret; |
481 |
481 |
482 // if the command fails from here on we want the end tile to be highlighted |
482 // if the command fails from here on we want the end tile to be highlighted |
483 _build_tunnel_endtile = end_tile; |
483 _build_tunnel_endtile = end_tile; |
484 |
484 |
485 // slope of end tile must be complementary to the slope of the start tile |
485 // slope of end tile must be complementary to the slope of the start tile |
486 if (end_tileh != (15 ^ start_tileh)) { |
486 if (end_tileh != ComplementSlope(start_tileh)) { |
487 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
487 ret = DoCommand(end_tile, end_tileh & start_tileh, 0, flags, CMD_TERRAFORM_LAND); |
488 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
488 if (CmdFailed(ret)) return_cmd_error(STR_5005_UNABLE_TO_EXCAVATE_LAND); |
489 } else { |
489 } else { |
490 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
490 ret = DoCommand(end_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
491 if (CmdFailed(ret)) return ret; |
491 if (CmdFailed(ret)) return ret; |
803 uint GetBridgeHeight(TileIndex t) |
803 uint GetBridgeHeight(TileIndex t) |
804 { |
804 { |
805 TileIndex tile = GetSouthernBridgeEnd(t); |
805 TileIndex tile = GetSouthernBridgeEnd(t); |
806 |
806 |
807 /* Return the height there (the height of the NORTH CORNER) |
807 /* Return the height there (the height of the NORTH CORNER) |
808 * If the end of the bridge is on a tileh 7 (all raised, except north corner), |
808 * If the end of the bridge is on a tile with all corners except the north corner raised, |
809 * the z coordinate is 1 height level too low. Compensate for that */ |
809 * the z coordinate is 1 height level too low. Compensate for that */ |
810 return TilePixelHeight(tile) + (GetTileSlope(tile, NULL) == 7 ? 8 : 0); |
810 return TilePixelHeight(tile) + (GetTileSlope(tile, NULL) == SLOPE_WSE ? 8 : 0); |
811 } |
811 } |
812 |
812 |
813 static const byte _bridge_foundations[2][16] = { |
813 static const byte _bridge_foundations[2][16] = { |
814 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
814 // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
815 {0,16,18,3,20,5,0,7,22,0,10,11,12,13,14}, |
815 {0,16,18,3,20,5,0,7,22,0,10,11,12,13,14}, |
838 |
838 |
839 p = _tileh_bits[(image & 1) * 2 + (axis == AXIS_X ? 0 : 1)]; |
839 p = _tileh_bits[(image & 1) * 2 + (axis == AXIS_X ? 0 : 1)]; |
840 front_height = ti->z + ((ti->tileh & p[0])?8:0); |
840 front_height = ti->z + ((ti->tileh & p[0])?8:0); |
841 back_height = ti->z + ((ti->tileh & p[1])?8:0); |
841 back_height = ti->z + ((ti->tileh & p[1])?8:0); |
842 |
842 |
843 if (IsSteepTileh(ti->tileh)) { |
843 if (IsSteepSlope(ti->tileh)) { |
844 if (!(ti->tileh & p[2])) front_height += 8; |
844 if (!(ti->tileh & p[2])) front_height += 8; |
845 if (!(ti->tileh & p[3])) back_height += 8; |
845 if (!(ti->tileh & p[3])) back_height += 8; |
846 } |
846 } |
847 |
847 |
848 for (; z >= front_height || z >= back_height; z = z - 8) { |
848 for (; z >= front_height || z >= back_height; z = z - 8) { |
855 } |
855 } |
856 } |
856 } |
857 } |
857 } |
858 } |
858 } |
859 |
859 |
860 uint GetBridgeFoundation(uint tileh, Axis axis) |
860 uint GetBridgeFoundation(Slope tileh, Axis axis) |
861 { |
861 { |
862 int i; |
862 int i; |
863 // normal level sloped building (7, 11, 13, 14) |
863 if (HASBIT(BRIDGE_FULL_LEVELED_FOUNDATION, tileh)) return tileh; |
864 if (BRIDGE_FULL_LEVELED_FOUNDATION & (1 << tileh)) return tileh; |
|
865 |
864 |
866 // inclined sloped building |
865 // inclined sloped building |
867 if (( |
866 if (( |
868 (i = 0, tileh == 1) || |
867 (i = 0, tileh == SLOPE_W) || |
869 (i += 2, tileh == 2) || |
868 (i += 2, tileh == SLOPE_S) || |
870 (i += 2, tileh == 4) || |
869 (i += 2, tileh == SLOPE_E) || |
871 (i += 2, tileh == 8) |
870 (i += 2, tileh == SLOPE_N) |
872 ) && ( |
871 ) && ( |
873 axis == AXIS_X || |
872 axis == AXIS_X || |
874 (i++, axis == AXIS_Y) |
873 (i++, axis == AXIS_Y) |
875 )) { |
874 )) { |
876 return i + 15; |
875 return i + 15; |
936 |
935 |
937 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
936 /* as the lower 3 bits are used for other stuff, make sure they are clear */ |
938 assert( (base_offset & 0x07) == 0x00); |
937 assert( (base_offset & 0x07) == 0x00); |
939 |
938 |
940 if (IsBridgeRamp(ti->tile)) { |
939 if (IsBridgeRamp(ti->tile)) { |
941 if (!(BRIDGE_NO_FOUNDATION & (1 << ti->tileh))) { // no foundations for 0, 3, 6, 9, 12 |
940 if (!HASBIT(BRIDGE_NO_FOUNDATION, ti->tileh)) { |
942 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
941 int f = GetBridgeFoundation(ti->tileh, DiagDirToAxis(GetBridgeRampDirection(ti->tile))); |
943 if (f) DrawFoundation(ti, f); |
942 if (f) DrawFoundation(ti, f); |
944 } |
943 } |
945 |
944 |
946 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
945 // HACK Wizardry to convert the bridge ramp direction into a sprite offset |
947 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
946 base_offset += (6 - GetBridgeRampDirection(ti->tile)) % 4; |
948 |
947 |
949 if (ti->tileh == 0) base_offset += 4; // sloped bridge head |
948 if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head |
950 |
949 |
951 /* Table number 6 always refers to the bridge heads for any bridge type */ |
950 /* Table number 6 always refers to the bridge heads for any bridge type */ |
952 image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
951 image = GetBridgeSpriteTable(GetBridgeType(ti->tile), 6)[base_offset]; |
953 |
952 |
954 if (!ice) { |
953 if (!ice) { |
974 if (f != 0) DrawFoundation(ti, f); |
973 if (f != 0) DrawFoundation(ti, f); |
975 |
974 |
976 if (GetTransportTypeUnderBridge(ti->tile) == TRANSPORT_RAIL) { |
975 if (GetTransportTypeUnderBridge(ti->tile) == TRANSPORT_RAIL) { |
977 const RailtypeInfo* rti = GetRailTypeInfo(GetRailType(ti->tile)); |
976 const RailtypeInfo* rti = GetRailTypeInfo(GetRailType(ti->tile)); |
978 |
977 |
979 if (ti->tileh == 0) { |
978 if (ti->tileh == SLOPE_FLAT) { |
980 image = (axis == AXIS_X ? SPR_RAIL_TRACK_Y : SPR_RAIL_TRACK_X); |
979 image = (axis == AXIS_X ? SPR_RAIL_TRACK_Y : SPR_RAIL_TRACK_X); |
981 } else { |
980 } else { |
982 image = SPR_RAIL_TRACK_Y + _track_sloped_sprites[ti->tileh - 1]; |
981 image = SPR_RAIL_TRACK_Y + _track_sloped_sprites[ti->tileh - 1]; |
983 } |
982 } |
984 image += rti->total_offset; |
983 image += rti->total_offset; |
985 if (ice) image += rti->snow_offset; |
984 if (ice) image += rti->snow_offset; |
986 } else { |
985 } else { |
987 if (ti->tileh == 0) { |
986 if (ti->tileh == SLOPE_FLAT) { |
988 image = (axis == AXIS_X ? SPR_ROAD_Y : SPR_ROAD_X); |
987 image = (axis == AXIS_X ? SPR_ROAD_Y : SPR_ROAD_X); |
989 } else { |
988 } else { |
990 image = _road_sloped_sprites[ti->tileh - 1] + 0x53F; |
989 image = _road_sloped_sprites[ti->tileh - 1] + 0x53F; |
991 } |
990 } |
992 if (ice) image += 19; |
991 if (ice) image += 19; |
995 } else { |
994 } else { |
996 if (IsClearUnderBridge(ti->tile)) { |
995 if (IsClearUnderBridge(ti->tile)) { |
997 image = (ice ? SPR_FLAT_SNOWY_TILE : SPR_FLAT_GRASS_TILE); |
996 image = (ice ? SPR_FLAT_SNOWY_TILE : SPR_FLAT_GRASS_TILE); |
998 DrawGroundSprite(image + _tileh_to_sprite[ti->tileh]); |
997 DrawGroundSprite(image + _tileh_to_sprite[ti->tileh]); |
999 } else { |
998 } else { |
1000 if (ti->tileh == 0) { |
999 if (ti->tileh == SLOPE_FLAT) { |
1001 DrawGroundSprite(SPR_FLAT_WATER_TILE); |
1000 DrawGroundSprite(SPR_FLAT_WATER_TILE); |
1002 if (ti->z != 0) DrawCanalWater(ti->tile); |
1001 if (ti->z != 0) DrawCanalWater(ti->tile); |
1003 } else { |
1002 } else { |
1004 DrawGroundSprite(_water_shore_sprites[ti->tileh]); |
1003 DrawGroundSprite(_water_shore_sprites[ti->tileh]); |
1005 } |
1004 } |
1059 { |
1058 { |
1060 TileIndex tile = ti->tile; |
1059 TileIndex tile = ti->tile; |
1061 uint z = ti->z; |
1060 uint z = ti->z; |
1062 uint x = ti->x & 0xF; |
1061 uint x = ti->x & 0xF; |
1063 uint y = ti->y & 0xF; |
1062 uint y = ti->y & 0xF; |
1064 uint tileh = ti->tileh; |
1063 Slope tileh = ti->tileh; |
1065 |
1064 |
1066 if (IsTunnel(tile)) { |
1065 if (IsTunnel(tile)) { |
1067 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1066 uint pos = (DiagDirToAxis(GetTunnelDirection(tile)) == AXIS_X ? y : x); |
1068 |
1067 |
1069 // In the tunnel entrance? |
1068 // In the tunnel entrance? |
1112 } |
1111 } |
1113 |
1112 |
1114 return z + GetPartialZ(x, y, tileh); |
1113 return z + GetPartialZ(x, y, tileh); |
1115 } |
1114 } |
1116 |
1115 |
1117 static uint GetSlopeTileh_TunnelBridge(TileIndex tile, uint tileh) |
1116 static Slope GetSlopeTileh_TunnelBridge(TileIndex tile, Slope tileh) |
1118 { |
1117 { |
1119 // not accurate, but good enough for slope graphics drawing |
1118 // not accurate, but good enough for slope graphics drawing |
1120 return 0; |
1119 return SLOPE_FLAT; |
1121 } |
1120 } |
1122 |
1121 |
1123 |
1122 |
1124 static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac) |
1123 static void GetAcceptedCargo_TunnelBridge(TileIndex tile, AcceptedCargo ac) |
1125 { |
1124 { |
1359 } else if (IsBridge(tile)) { // XXX is this necessary? |
1358 } else if (IsBridge(tile)) { // XXX is this necessary? |
1360 if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) { |
1359 if (v->type == VEH_Road || (v->type == VEH_Train && IsFrontEngine(v))) { |
1361 uint h; |
1360 uint h; |
1362 |
1361 |
1363 // Compensate for possible foundation |
1362 // Compensate for possible foundation |
1364 if (GetTileSlope(tile, &h) != 0) h += 8; |
1363 if (GetTileSlope(tile, &h) != SLOPE_FLAT) h += 8; |
1365 if (IsBridgeRamp(tile) || |
1364 if (IsBridgeRamp(tile) || |
1366 myabs(h - v->z_pos) > 2) { // high above the ground -> on the bridge |
1365 myabs(h - v->z_pos) > 2) { // high above the ground -> on the bridge |
1367 /* modify speed of vehicle */ |
1366 /* modify speed of vehicle */ |
1368 uint16 spd = _bridge[GetBridgeType(tile)].speed; |
1367 uint16 spd = _bridge[GetBridgeType(tile)].speed; |
1369 if (v->type == VEH_Road) spd *= 2; |
1368 if (v->type == VEH_Road) spd *= 2; |