31 #include "strings_func.h" |
31 #include "strings_func.h" |
32 #include "vehicle_func.h" |
32 #include "vehicle_func.h" |
33 #include "vehicle_base.h" |
33 #include "vehicle_base.h" |
34 #include "sound_func.h" |
34 #include "sound_func.h" |
35 #include "road_func.h" |
35 #include "road_func.h" |
|
36 #include "tunnelbridge.h" |
36 |
37 |
37 #include "table/sprites.h" |
38 #include "table/sprites.h" |
38 #include "table/strings.h" |
39 #include "table/strings.h" |
39 |
40 |
40 #define M(x) (1 << (x)) |
41 #define M(x) (1 << (x)) |
41 /* Level crossings may only be built on these slopes */ |
42 /* Level crossings may only be built on these slopes */ |
42 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT)); |
43 static const uint32 VALID_LEVEL_CROSSING_SLOPES = (M(SLOPE_SEN) | M(SLOPE_ENW) | M(SLOPE_NWS) | M(SLOPE_NS) | M(SLOPE_WSE) | M(SLOPE_EW) | M(SLOPE_FLAT)); |
43 #undef M |
44 #undef M |
|
45 |
|
46 Foundation GetRoadFoundation(Slope tileh, RoadBits bits); |
44 |
47 |
45 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) |
48 bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, bool *edge_road, RoadType rt) |
46 { |
49 { |
47 RoadBits present; |
50 RoadBits present; |
48 RoadBits n; |
51 RoadBits n; |
91 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt) |
94 static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool *edge_road, RoadType rt) |
92 { |
95 { |
93 return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt); |
96 return CheckAllowRemoveRoad(tile, remove, GetRoadOwner(tile, rt), edge_road, rt); |
94 } |
97 } |
95 |
98 |
|
99 |
96 /** Delete a piece of road. |
100 /** Delete a piece of road. |
97 * @param tile tile where to remove road from |
101 * @param tile tile where to remove road from |
98 * @param flags operation to perform |
102 * @param flags operation to perform |
99 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
103 * @param pieces roadbits to remove |
100 * bit 4..5 road type |
104 * @param rt roadtype to remove |
101 * bit 6 ignore the fact that the tram track has not been removed |
105 * @param crossing_check should we check if there is a tram track when we are removing road from crossing? |
102 * yet when removing the road bits when not actually doing |
|
103 * it. Makes it possible to test whether the road bits can |
|
104 * be removed from a level crossing without physically |
|
105 * removing the tram bits before the test. |
|
106 * @param p2 unused |
|
107 */ |
106 */ |
108 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
107 static CommandCost RemoveRoad(TileIndex tile, uint32 flags, RoadBits pieces, RoadType rt, bool crossing_check) |
109 { |
108 { |
110 /* cost for removing inner/edge -roads */ |
109 /* cost for removing inner/edge -roads */ |
111 static const uint16 road_remove_cost[2] = {50, 18}; |
110 static const uint16 road_remove_cost[2] = {50, 18}; |
112 |
111 |
113 /* true if the roadpiece was always removeable, |
112 /* true if the roadpiece was always removeable, |
114 * false if it was a center piece. Affects town ratings drop */ |
113 * false if it was a center piece. Affects town ratings drop */ |
115 bool edge_road; |
114 bool edge_road; |
116 |
|
117 RoadType rt = (RoadType)GB(p1, 4, 2); |
|
118 if (!IsValidRoadType(rt)) return CMD_ERROR; |
|
119 |
115 |
120 Town *t = NULL; |
116 Town *t = NULL; |
121 switch (GetTileType(tile)) { |
117 switch (GetTileType(tile)) { |
122 case MP_ROAD: |
118 case MP_ROAD: |
123 if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); |
119 if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); |
128 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
124 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
129 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
125 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
130 break; |
126 break; |
131 |
127 |
132 case MP_TUNNELBRIDGE: |
128 case MP_TUNNELBRIDGE: |
133 { |
129 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
134 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
130 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
135 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
131 break; |
136 } break; |
|
137 |
132 |
138 default: |
133 default: |
139 return CMD_ERROR; |
134 return CMD_ERROR; |
140 } |
135 } |
141 |
136 |
142 RoadBits pieces = Extract<RoadBits, 0>(p1); |
|
143 RoadTypes rts = GetRoadTypes(tile); |
137 RoadTypes rts = GetRoadTypes(tile); |
144 /* The tile doesn't have the given road type */ |
138 /* The tile doesn't have the given road type */ |
145 if (!HasBit(rts, rt)) return CMD_ERROR; |
139 if (!HasBit(rts, rt)) return CMD_ERROR; |
146 |
140 |
147 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
141 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
156 |
150 |
157 CommandCost cost(EXPENSES_CONSTRUCTION); |
151 CommandCost cost(EXPENSES_CONSTRUCTION); |
158 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
152 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
159 TileIndex other_end = GetOtherTunnelBridgeEnd(tile); |
153 TileIndex other_end = GetOtherTunnelBridgeEnd(tile); |
160 /* Pay for *every* tile of the bridge or tunnel */ |
154 /* Pay for *every* tile of the bridge or tunnel */ |
161 cost.AddCost((DistanceManhattan(other_end, tile) + 1) * _price.remove_road); |
155 cost.AddCost((GetTunnelBridgeLength(other_end, tile) + 2) * _price.remove_road); |
162 if (flags & DC_EXEC) { |
156 if (flags & DC_EXEC) { |
163 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
157 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
164 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
158 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
165 |
159 |
166 /* Mark tiles diry that have been repaved */ |
160 /* Mark tiles diry that have been repaved */ |
229 return CMD_ERROR; |
223 return CMD_ERROR; |
230 } |
224 } |
231 |
225 |
232 /* Don't allow road to be removed from the crossing when there is tram; |
226 /* Don't allow road to be removed from the crossing when there is tram; |
233 * we can't draw the crossing without trambits ;) */ |
227 * we can't draw the crossing without trambits ;) */ |
234 if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR; |
228 if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && (flags & DC_EXEC || crossing_check)) return CMD_ERROR; |
235 |
229 |
236 if (rt == ROADTYPE_ROAD) { |
230 if (rt == ROADTYPE_ROAD) { |
237 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
231 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
238 } |
232 } |
239 |
233 |
252 |
246 |
253 default: |
247 default: |
254 case ROAD_TILE_DEPOT: |
248 case ROAD_TILE_DEPOT: |
255 return CMD_ERROR; |
249 return CMD_ERROR; |
256 } |
250 } |
|
251 } |
|
252 |
|
253 |
|
254 /** Delete a piece of road. |
|
255 * @param tile tile where to remove road from |
|
256 * @param flags operation to perform |
|
257 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
|
258 * bit 4..5 road type |
|
259 * @param p2 unused |
|
260 */ |
|
261 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
|
262 { |
|
263 RoadType rt = (RoadType)GB(p1, 4, 2); |
|
264 if (!IsValidRoadType(rt)) return CMD_ERROR; |
|
265 |
|
266 RoadBits pieces = Extract<RoadBits, 0>(p1); |
|
267 |
|
268 return RemoveRoad(tile, flags, pieces, rt, true); |
257 } |
269 } |
258 |
270 |
259 |
271 |
260 static const RoadBits _valid_tileh_slopes_road[][15] = { |
272 static const RoadBits _valid_tileh_slopes_road[][15] = { |
261 /* set of normal ones */ |
273 /* set of normal ones */ |
372 |
384 |
373 /* Force straight roads. */ |
385 /* Force straight roads. */ |
374 *pieces |= MirrorRoadBits(*pieces); |
386 *pieces |= MirrorRoadBits(*pieces); |
375 |
387 |
376 /* partly leveled up tile, only if there's no road on that tile */ |
388 /* partly leveled up tile, only if there's no road on that tile */ |
377 if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { |
389 if ((existing == ROAD_NONE || existing == *pieces) && IsSlopeWithOneCornerRaised(tileh)) { |
378 if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
390 if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
379 } |
391 } |
380 return CMD_ERROR; |
392 return CMD_ERROR; |
381 } |
393 } |
382 |
394 |
494 } |
506 } |
495 |
507 |
496 case MP_STATION: |
508 case MP_STATION: |
497 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
509 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
498 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
510 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
499 /* Don't allow "upgrading" the roadstop when vehicles are already driving on it */ |
511 /* Don't allow adding roadtype to the roadstop when vehicles are already driving on it */ |
500 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
512 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
501 break; |
513 break; |
502 |
514 |
503 case MP_TUNNELBRIDGE: |
515 case MP_TUNNELBRIDGE: |
504 { |
516 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
505 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
517 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
506 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
518 /* Don't allow adding roadtype to the bridge/tunnel when vehicles are already driving on it */ |
507 |
519 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
508 /* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */ |
520 break; |
509 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
|
510 } break; |
|
511 |
521 |
512 default: |
522 default: |
513 do_clear:; |
523 do_clear:; |
514 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
524 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
515 if (CmdFailed(ret)) return ret; |
525 if (CmdFailed(ret)) return ret; |
528 } |
538 } |
529 |
539 |
530 if (IsTileType(tile, MP_ROAD)) { |
540 if (IsTileType(tile, MP_ROAD)) { |
531 /* Don't put the pieces that already exist */ |
541 /* Don't put the pieces that already exist */ |
532 pieces &= ComplementRoadBits(existing); |
542 pieces &= ComplementRoadBits(existing); |
|
543 |
|
544 /* Check if new road bits will have the same foundation as other existing road types */ |
|
545 if (GetRoadTileType(tile) == ROAD_TILE_NORMAL) { |
|
546 Slope slope = GetTileSlope(tile, NULL); |
|
547 Foundation found_new = GetRoadFoundation(slope, pieces | existing); |
|
548 |
|
549 /* Test if all other roadtypes can be built at that foundation */ |
|
550 for (RoadType rtest = ROADTYPE_ROAD; rtest < ROADTYPE_END; rtest++) { |
|
551 if (rtest != rt) { // check only other road types |
|
552 RoadBits bits = GetRoadBits(tile, rtest); |
|
553 /* do not check if there are not road bits of given type */ |
|
554 if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) { |
|
555 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
|
556 } |
|
557 } |
|
558 } |
|
559 } |
533 } |
560 } |
534 |
561 |
535 cost.AddCost(CountBits(pieces) * _price.build_road); |
562 cost.AddCost(CountBits(pieces) * _price.build_road); |
536 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
563 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
537 /* Pay for *every* tile of the bridge or tunnel */ |
564 /* Pay for *every* tile of the bridge or tunnel */ |
538 cost.MultiplyCost(DistanceManhattan(GetOtherTunnelBridgeEnd(tile), tile) + 1); |
565 cost.MultiplyCost(GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2); |
539 } |
566 } |
540 |
567 |
541 if (flags & DC_EXEC) { |
568 if (flags & DC_EXEC) { |
542 switch (GetTileType(tile)) { |
569 switch (GetTileType(tile)) { |
543 case MP_ROAD: { |
570 case MP_ROAD: { |
715 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
742 if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE; |
716 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
743 if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
717 |
744 |
718 /* try to remove the halves. */ |
745 /* try to remove the halves. */ |
719 if (bits != 0) { |
746 if (bits != 0) { |
720 ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD); |
747 ret = RemoveRoad(tile, flags & ~DC_EXEC, bits, rt, true); |
721 if (CmdSucceeded(ret)) { |
748 if (CmdSucceeded(ret)) { |
722 if (flags & DC_EXEC) { |
749 if (flags & DC_EXEC) { |
723 money -= ret.GetCost(); |
750 money -= ret.GetCost(); |
724 if (money < 0) { |
751 if (money < 0) { |
725 _additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost(); |
752 _additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost(); |
726 return cost; |
753 return cost; |
727 } |
754 } |
728 DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
755 RemoveRoad(tile, flags, bits, rt, true); |
729 } |
756 } |
730 cost.AddCost(ret); |
757 cost.AddCost(ret); |
731 } |
758 } |
732 } |
759 } |
733 |
760 |
816 ) { |
843 ) { |
817 RoadTypes rts = GetRoadTypes(tile); |
844 RoadTypes rts = GetRoadTypes(tile); |
818 CommandCost ret(EXPENSES_CONSTRUCTION); |
845 CommandCost ret(EXPENSES_CONSTRUCTION); |
819 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
846 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
820 if (HasBit(rts, rt)) { |
847 if (HasBit(rts, rt)) { |
821 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
848 CommandCost tmp_ret = RemoveRoad(tile, flags, GetRoadBits(tile, rt), rt, true); |
822 if (CmdFailed(tmp_ret)) return tmp_ret; |
849 if (CmdFailed(tmp_ret)) return tmp_ret; |
823 ret.AddCost(tmp_ret); |
850 ret.AddCost(tmp_ret); |
824 } |
851 } |
825 } |
852 } |
826 return ret; |
853 return ret; |
836 |
863 |
837 /* Must iterate over the roadtypes in a reverse manner because |
864 /* Must iterate over the roadtypes in a reverse manner because |
838 * tram tracks must be removed before the road bits. */ |
865 * tram tracks must be removed before the road bits. */ |
839 for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) { |
866 for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) { |
840 if (HasBit(rts, rt)) { |
867 if (HasBit(rts, rt)) { |
841 CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
868 CommandCost tmp_ret = RemoveRoad(tile, flags, GetCrossingRoadBits(tile), rt, false); |
842 if (CmdFailed(tmp_ret)) return tmp_ret; |
869 if (CmdFailed(tmp_ret)) return tmp_ret; |
843 ret.AddCost(tmp_ret); |
870 ret.AddCost(tmp_ret); |
844 } |
871 } |
845 } |
872 } |
846 |
873 |
1257 /* Generate a nicer town surface */ |
1284 /* Generate a nicer town surface */ |
1258 const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); |
1285 const RoadBits old_rb = GetAnyRoadBits(tile, ROADTYPE_ROAD); |
1259 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); |
1286 const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); |
1260 |
1287 |
1261 if (old_rb != new_rb) { |
1288 if (old_rb != new_rb) { |
1262 DoCommand(tile, (old_rb ^ new_rb), t->index, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_REMOVE_ROAD); |
1289 RemoveRoad(tile, DC_EXEC | DC_AUTO | DC_NO_WATER, (old_rb ^ new_rb), ROADTYPE_ROAD, true); |
1263 } |
1290 } |
1264 } |
1291 } |
1265 |
1292 |
1266 MarkTileDirtyByTile(tile); |
1293 MarkTileDirtyByTile(tile); |
1267 } |
1294 } |