7 #include "bridge_map.h" |
7 #include "bridge_map.h" |
8 #include "bridge.h" |
8 #include "bridge.h" |
9 #include "cmd_helper.h" |
9 #include "cmd_helper.h" |
10 #include "rail_map.h" |
10 #include "rail_map.h" |
11 #include "road_map.h" |
11 #include "road_map.h" |
|
12 #include "road_internal.h" |
12 #include "sprite.h" |
13 #include "sprite.h" |
13 #include "table/sprites.h" |
14 #include "table/sprites.h" |
14 #include "table/strings.h" |
15 #include "table/strings.h" |
15 #include "strings.h" |
16 #include "tile_cmd.h" |
16 #include "functions.h" |
|
17 #include "window.h" |
|
18 #include "map.h" |
|
19 #include "landscape.h" |
17 #include "landscape.h" |
20 #include "tile.h" |
|
21 #include "town_map.h" |
18 #include "town_map.h" |
22 #include "vehicle.h" |
19 #include "viewport_func.h" |
23 #include "viewport.h" |
20 #include "command_func.h" |
24 #include "command.h" |
|
25 #include "player.h" |
21 #include "player.h" |
26 #include "town.h" |
22 #include "town.h" |
27 #include "gfx.h" |
|
28 #include "sound.h" |
|
29 #include "yapf/yapf.h" |
23 #include "yapf/yapf.h" |
30 #include "depot.h" |
24 #include "depot.h" |
31 #include "newgrf.h" |
25 #include "newgrf.h" |
32 #include "station_map.h" |
26 #include "station_map.h" |
33 #include "tunnel_map.h" |
27 #include "tunnel_map.h" |
34 #include "misc/autoptr.hpp" |
28 #include "misc/autoptr.hpp" |
|
29 #include "variables.h" |
35 #include "autoslope.h" |
30 #include "autoslope.h" |
36 #include "transparency.h" |
31 #include "transparency.h" |
|
32 #include "tunnelbridge_map.h" |
|
33 #include "window_func.h" |
|
34 #include "strings_func.h" |
|
35 #include "vehicle_func.h" |
|
36 #include "vehicle_base.h" |
|
37 #include "sound_func.h" |
|
38 |
37 |
39 |
38 #define M(x) (1 << (x)) |
40 #define M(x) (1 << (x)) |
39 /* Level crossings may only be built on these slopes */ |
41 /* Level crossings may only be built on these slopes */ |
40 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)); |
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)); |
41 #undef M |
43 #undef M |
110 |
112 |
111 /* true if the roadpiece was always removeable, |
113 /* true if the roadpiece was always removeable, |
112 * false if it was a center piece. Affects town ratings drop */ |
114 * false if it was a center piece. Affects town ratings drop */ |
113 bool edge_road; |
115 bool edge_road; |
114 |
116 |
115 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
116 |
|
117 RoadType rt = (RoadType)GB(p1, 4, 2); |
117 RoadType rt = (RoadType)GB(p1, 4, 2); |
118 if (!IsValidRoadType(rt)) return CMD_ERROR; |
118 if (!IsValidRoadType(rt)) return CMD_ERROR; |
119 |
119 |
120 Town *t = NULL; |
120 Town *t = NULL; |
121 switch (GetTileType(tile)) { |
121 switch (GetTileType(tile)) { |
122 case MP_ROAD: |
122 case MP_ROAD: |
123 if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); |
123 if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); |
|
124 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
124 break; |
125 break; |
125 |
126 |
126 case MP_STATION: |
127 case MP_STATION: |
127 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
128 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
|
129 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
128 break; |
130 break; |
129 |
131 |
130 case MP_TUNNELBRIDGE: |
132 case MP_TUNNELBRIDGE: |
131 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
133 { |
132 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
134 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
133 break; |
135 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
|
136 } break; |
134 |
137 |
135 default: |
138 default: |
136 return CMD_ERROR; |
139 return CMD_ERROR; |
137 } |
140 } |
138 |
141 |
141 /* The tile doesn't have the given road type */ |
144 /* The tile doesn't have the given road type */ |
142 if (!HasBit(rts, rt)) return CMD_ERROR; |
145 if (!HasBit(rts, rt)) return CMD_ERROR; |
143 |
146 |
144 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
147 if (!CheckAllowRemoveRoad(tile, pieces, &edge_road, rt)) return CMD_ERROR; |
145 |
148 |
146 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
|
147 |
|
148 /* check if you're allowed to remove the street owned by a town |
149 /* check if you're allowed to remove the street owned by a town |
149 * removal allowance depends on difficulty setting */ |
150 * removal allowance depends on difficulty setting */ |
150 if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR; |
151 if (!CheckforTownRating(flags, t, ROAD_REMOVE)) return CMD_ERROR; |
151 |
152 |
152 if (!IsTileType(tile, MP_ROAD)) { |
153 if (!IsTileType(tile, MP_ROAD)) { |
153 /* If it's the last roadtype, just clear the whole tile */ |
154 /* If it's the last roadtype, just clear the whole tile */ |
154 if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
155 if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
155 |
156 |
156 CommandCost cost; |
157 CommandCost cost(EXPENSES_CONSTRUCTION); |
157 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
158 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
158 TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile); |
159 TileIndex other_end = GetOtherTunnelBridgeEnd(tile); |
159 /* Pay for *every* tile of the bridge or tunnel */ |
160 /* Pay for *every* tile of the bridge or tunnel */ |
160 cost.AddCost((DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road); |
161 cost.AddCost((DistanceManhattan(other_end, tile) + 1) * _price.remove_road); |
161 if (flags & DC_EXEC) { |
162 if (flags & DC_EXEC) { |
162 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
163 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
163 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
164 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
164 |
165 |
165 /* Mark tiles diry that have been repaved */ |
166 /* Mark tiles diry that have been repaved */ |
166 MarkTileDirtyByTile(tile); |
167 MarkTileDirtyByTile(tile); |
167 MarkTileDirtyByTile(other_end); |
168 MarkTileDirtyByTile(other_end); |
168 if (IsBridge(tile)) { |
169 if (IsBridge(tile)) { |
169 TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); |
170 TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile)); |
170 |
171 |
171 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
172 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
172 } |
173 } |
173 } |
174 } |
174 } else { |
175 } else { |
176 if (flags & DC_EXEC) { |
177 if (flags & DC_EXEC) { |
177 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
178 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
178 MarkTileDirtyByTile(tile); |
179 MarkTileDirtyByTile(tile); |
179 } |
180 } |
180 } |
181 } |
181 return CommandCost(cost); |
182 return cost; |
182 } |
183 } |
183 |
184 |
184 switch (GetRoadTileType(tile)) { |
185 switch (GetRoadTileType(tile)) { |
185 case ROAD_TILE_NORMAL: { |
186 case ROAD_TILE_NORMAL: { |
186 RoadBits present = GetRoadBits(tile, rt); |
187 RoadBits present = GetRoadBits(tile, rt); |
196 |
197 |
197 /* limit the bits to delete to the existing bits. */ |
198 /* limit the bits to delete to the existing bits. */ |
198 c &= present; |
199 c &= present; |
199 if (c == ROAD_NONE) return CMD_ERROR; |
200 if (c == ROAD_NONE) return CMD_ERROR; |
200 |
201 |
|
202 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
201 if (flags & DC_EXEC) { |
203 if (flags & DC_EXEC) { |
202 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
|
203 |
|
204 present ^= c; |
204 present ^= c; |
205 if (present == ROAD_NONE) { |
205 if (present == ROAD_NONE) { |
206 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
206 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
207 if (rts == ROADTYPES_NONE) { |
207 if (rts == ROADTYPES_NONE) { |
208 /* Includes MarkTileDirtyByTile() */ |
208 /* Includes MarkTileDirtyByTile() */ |
219 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
219 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
220 SetRoadBits(tile, present, rt); |
220 SetRoadBits(tile, present, rt); |
221 MarkTileDirtyByTile(tile); |
221 MarkTileDirtyByTile(tile); |
222 } |
222 } |
223 } |
223 } |
224 return CommandCost(CountBits(c) * _price.remove_road); |
224 return CommandCost(EXPENSES_CONSTRUCTION, CountBits(c) * _price.remove_road); |
225 } |
225 } |
226 |
226 |
227 case ROAD_TILE_CROSSING: { |
227 case ROAD_TILE_CROSSING: { |
228 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
228 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
229 return CMD_ERROR; |
229 return CMD_ERROR; |
231 |
231 |
232 /* Don't allow road to be removed from the crossing when there is tram; |
232 /* Don't allow road to be removed from the crossing when there is tram; |
233 * we can't draw the crossing without trambits ;) */ |
233 * 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; |
234 if (rt == ROADTYPE_ROAD && HasBit(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HasBit(p1, 6))) return CMD_ERROR; |
235 |
235 |
|
236 if (rt == ROADTYPE_ROAD) { |
|
237 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
|
238 } |
|
239 |
236 if (flags & DC_EXEC) { |
240 if (flags & DC_EXEC) { |
237 if (rt == ROADTYPE_ROAD) { |
|
238 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
|
239 } |
|
240 |
|
241 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
241 RoadTypes rts = GetRoadTypes(tile) & ComplementRoadTypes(RoadTypeToRoadTypes(rt)); |
242 if (rts == ROADTYPES_NONE) { |
242 if (rts == ROADTYPES_NONE) { |
243 MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); |
243 MakeRailNormal(tile, GetTileOwner(tile), GetCrossingRailBits(tile), GetRailType(tile)); |
244 } else { |
244 } else { |
245 SetRoadTypes(tile, rts); |
245 SetRoadTypes(tile, rts); |
246 } |
246 } |
247 MarkTileDirtyByTile(tile); |
247 MarkTileDirtyByTile(tile); |
248 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
248 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
249 } |
249 } |
250 return CommandCost(_price.remove_road * 2); |
250 return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_road * 2); |
251 } |
251 } |
252 |
252 |
253 default: |
253 default: |
254 case ROAD_TILE_DEPOT: |
254 case ROAD_TILE_DEPOT: |
255 return CMD_ERROR; |
255 return CMD_ERROR; |
353 /* Single bits on slopes. |
353 /* Single bits on slopes. |
354 * We check for the roads that need at least 2 bits */ |
354 * We check for the roads that need at least 2 bits */ |
355 if (_patches.build_on_slopes && |
355 if (_patches.build_on_slopes && |
356 existing == ROAD_NONE && CountBits(*pieces) == 1 && |
356 existing == ROAD_NONE && CountBits(*pieces) == 1 && |
357 (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { |
357 (_valid_tileh_slopes_road[2][tileh] & *pieces) == ROAD_NONE) { |
358 return CommandCost(_price.terraform); |
358 return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
359 } |
359 } |
360 |
360 |
361 /* no special foundation */ |
361 /* no special foundation */ |
362 if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == ROAD_NONE) { |
362 if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == ROAD_NONE) { |
363 /* force that all bits are set when we have slopes */ |
363 /* force that all bits are set when we have slopes */ |
365 return CommandCost(); // no extra cost |
365 return CommandCost(); // no extra cost |
366 } |
366 } |
367 |
367 |
368 /* foundation is used. Whole tile is leveled up */ |
368 /* foundation is used. Whole tile is leveled up */ |
369 if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) { |
369 if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == ROAD_NONE) { |
370 return CommandCost(existing != ROAD_NONE ? (Money)0 : _price.terraform); |
370 return CommandCost(EXPENSES_CONSTRUCTION, existing != ROAD_NONE ? (Money)0 : _price.terraform); |
371 } |
371 } |
372 |
372 |
373 /* Force straight roads. */ |
373 /* Force straight roads. */ |
374 *pieces |= MirrorRoadBits(*pieces); |
374 *pieces |= MirrorRoadBits(*pieces); |
375 |
375 |
376 /* partly leveled up tile, only if there's no road on that tile */ |
376 /* 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)) { |
377 if ((existing == ROAD_NONE || existing == *pieces) && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { |
378 if (*pieces == ROAD_X || *pieces == ROAD_Y) return _price.terraform; |
378 if (*pieces == ROAD_X || *pieces == ROAD_Y) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
379 } |
379 } |
380 return CMD_ERROR; |
380 return CMD_ERROR; |
381 } |
381 } |
382 |
382 |
383 /** Build a piece of road. |
383 /** Build a piece of road. |
388 * bit 6..7 disallowed directions to toggle |
388 * bit 6..7 disallowed directions to toggle |
389 * @param p2 the town that is building the road (0 if not applicable) |
389 * @param p2 the town that is building the road (0 if not applicable) |
390 */ |
390 */ |
391 CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
391 CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
392 { |
392 { |
393 CommandCost cost; |
393 CommandCost cost(EXPENSES_CONSTRUCTION); |
394 CommandCost ret; |
394 CommandCost ret; |
395 RoadBits existing = ROAD_NONE; |
395 RoadBits existing = ROAD_NONE; |
396 RoadBits all_bits = ROAD_NONE; |
396 RoadBits all_bits = ROAD_NONE; |
397 Slope tileh; |
397 Slope tileh; |
398 |
|
399 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
400 |
398 |
401 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
399 /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero |
402 * if a non-player is building the road */ |
400 * if a non-player is building the road */ |
403 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
401 if ((IsValidPlayer(_current_player) && p2 != 0) || (_current_player == OWNER_TOWN && !IsValidTownID(p2))) return CMD_ERROR; |
404 |
402 |
489 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
487 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
490 /* Always add road to the roadtypes (can't draw without it) */ |
488 /* Always add road to the roadtypes (can't draw without it) */ |
491 MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); |
489 MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); |
492 MarkTileDirtyByTile(tile); |
490 MarkTileDirtyByTile(tile); |
493 } |
491 } |
494 return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); |
492 return CommandCost(EXPENSES_CONSTRUCTION, _price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); |
495 } |
493 } |
496 |
494 |
497 case MP_STATION: |
495 case MP_STATION: |
498 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
496 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
499 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
497 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
500 /* Don't allow "upgrading" the roadstop when vehicles are already driving on it */ |
498 /* Don't allow "upgrading" the roadstop when vehicles are already driving on it */ |
501 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
499 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
502 break; |
500 break; |
503 |
501 |
504 case MP_TUNNELBRIDGE: |
502 case MP_TUNNELBRIDGE: |
505 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
503 { |
506 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
504 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) return CMD_ERROR; |
507 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
505 if (HasBit(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
508 /* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */ |
506 |
509 if (!EnsureNoVehicleOnGround(tile)) return CMD_ERROR; |
507 /* Don't allow "upgrading" the bridge/tunnel when vehicles are already driving on it */ |
510 break; |
508 if (GetVehicleTunnelBridge(tile, GetOtherTunnelBridgeEnd(tile)) != NULL) return CMD_ERROR; |
|
509 } break; |
511 |
510 |
512 default: |
511 default: |
513 do_clear:; |
512 do_clear:; |
514 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
513 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
515 if (CmdFailed(ret)) return ret; |
514 if (CmdFailed(ret)) return ret; |
533 } |
532 } |
534 |
533 |
535 cost.AddCost(CountBits(pieces) * _price.build_road); |
534 cost.AddCost(CountBits(pieces) * _price.build_road); |
536 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
535 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
537 /* Pay for *every* tile of the bridge or tunnel */ |
536 /* Pay for *every* tile of the bridge or tunnel */ |
538 cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile)); |
537 cost.MultiplyCost(DistanceManhattan(GetOtherTunnelBridgeEnd(tile), tile) + 1); |
539 } |
538 } |
540 |
539 |
541 if (flags & DC_EXEC) { |
540 if (flags & DC_EXEC) { |
542 switch (GetTileType(tile)) { |
541 switch (GetTileType(tile)) { |
543 case MP_ROAD: { |
542 case MP_ROAD: { |
549 } |
548 } |
550 if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt); |
549 if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt); |
551 } break; |
550 } break; |
552 |
551 |
553 case MP_TUNNELBRIDGE: { |
552 case MP_TUNNELBRIDGE: { |
554 TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile); |
553 TileIndex other_end = GetOtherTunnelBridgeEnd(tile); |
555 |
554 |
556 SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt)); |
555 SetRoadTypes(other_end, GetRoadTypes(other_end) | RoadTypeToRoadTypes(rt)); |
557 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); |
556 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); |
558 |
557 |
559 /* Mark tiles diry that have been repaved */ |
558 /* Mark tiles diry that have been repaved */ |
560 MarkTileDirtyByTile(other_end); |
559 MarkTileDirtyByTile(other_end); |
561 MarkTileDirtyByTile(tile); |
560 MarkTileDirtyByTile(tile); |
562 if (IsBridge(tile)) { |
561 if (IsBridge(tile)) { |
563 TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); |
562 TileIndexDiff delta = TileOffsByDiagDir(GetTunnelBridgeDirection(tile)); |
564 |
563 |
565 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
564 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
566 } |
565 } |
567 } break; |
566 } break; |
568 |
567 |
583 |
582 |
584 MarkTileDirtyByTile(tile); |
583 MarkTileDirtyByTile(tile); |
585 } |
584 } |
586 return cost; |
585 return cost; |
587 } |
586 } |
588 |
|
589 /** |
|
590 * Switches the rail type on a level crossing. |
|
591 * @param tile The tile on which the railtype is to be convert. |
|
592 * @param totype The railtype we want to convert to |
|
593 * @param exec Switches between test and execute mode |
|
594 * @return The cost and state of the operation |
|
595 * @retval CMD_ERROR An error occured during the operation. |
|
596 */ |
|
597 CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec) |
|
598 { |
|
599 /* not a railroad crossing? */ |
|
600 if (!IsLevelCrossing(tile)) return CMD_ERROR; |
|
601 |
|
602 if (exec) { |
|
603 SetRailType(tile, totype); |
|
604 MarkTileDirtyByTile(tile); |
|
605 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile))); |
|
606 VehicleFromPos(tile, &tile, UpdateTrainPowerProc); |
|
607 } |
|
608 |
|
609 return CommandCost(RailBuildCost(totype) / 2); |
|
610 } |
|
611 |
|
612 |
587 |
613 /** Build a long piece of road. |
588 /** Build a long piece of road. |
614 * @param end_tile end tile of drag |
589 * @param end_tile end tile of drag |
615 * @param flags operation to perform |
590 * @param flags operation to perform |
616 * @param p1 start tile of drag |
591 * @param p1 start tile of drag |
622 * - p2 = (bit 5) - set road direction |
597 * - p2 = (bit 5) - set road direction |
623 */ |
598 */ |
624 CommandCost CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
599 CommandCost CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
625 { |
600 { |
626 TileIndex start_tile, tile; |
601 TileIndex start_tile, tile; |
627 CommandCost cost, ret; |
602 CommandCost ret, cost(EXPENSES_CONSTRUCTION); |
628 bool had_bridge = false; |
603 bool had_bridge = false; |
629 bool had_tunnel = false; |
604 bool had_tunnel = false; |
630 bool had_success = false; |
605 bool had_success = false; |
631 DisallowedRoadDirections drd = DRD_NORTHBOUND; |
606 DisallowedRoadDirections drd = DRD_NORTHBOUND; |
632 |
|
633 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
634 |
607 |
635 if (p1 >= MapSize()) return CMD_ERROR; |
608 if (p1 >= MapSize()) return CMD_ERROR; |
636 |
609 |
637 start_tile = p1; |
610 start_tile = p1; |
638 RoadType rt = (RoadType)GB(p2, 3, 2); |
611 RoadType rt = (RoadType)GB(p2, 3, 2); |
645 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
618 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
646 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
619 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
647 TileIndex t = start_tile; |
620 TileIndex t = start_tile; |
648 start_tile = end_tile; |
621 start_tile = end_tile; |
649 end_tile = t; |
622 end_tile = t; |
650 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
623 p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0; |
651 drd = DRD_SOUTHBOUND; |
624 drd = DRD_SOUTHBOUND; |
652 } |
625 } |
653 |
626 |
654 /* On the X-axis, we have to swap the initial bits, so they |
627 /* On the X-axis, we have to swap the initial bits, so they |
655 * will be interpreted correctly in the GTTS. Futhermore |
628 * will be interpreted correctly in the GTTS. Futhermore |
709 * - p2 = (bit 3 + 4) - road type |
682 * - p2 = (bit 3 + 4) - road type |
710 */ |
683 */ |
711 CommandCost CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
684 CommandCost CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
712 { |
685 { |
713 TileIndex start_tile, tile; |
686 TileIndex start_tile, tile; |
714 CommandCost cost, ret, money; |
687 CommandCost ret, cost(EXPENSES_CONSTRUCTION); |
715 |
688 Money money; |
716 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
717 |
689 |
718 if (p1 >= MapSize()) return CMD_ERROR; |
690 if (p1 >= MapSize()) return CMD_ERROR; |
719 |
691 |
720 start_tile = p1; |
692 start_tile = p1; |
721 RoadType rt = (RoadType)GB(p2, 3, 2); |
693 RoadType rt = (RoadType)GB(p2, 3, 2); |
728 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
700 /* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ |
729 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
701 if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { |
730 TileIndex t = start_tile; |
702 TileIndex t = start_tile; |
731 start_tile = end_tile; |
703 start_tile = end_tile; |
732 end_tile = t; |
704 end_tile = t; |
733 p2 ^= IS_INT_INSIDE(p2 & 3, 1, 3) ? 3 : 0; |
705 p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0; |
734 } |
706 } |
735 |
707 |
736 money.AddCost(GetAvailableMoneyForCommand()); |
708 money = GetAvailableMoneyForCommand(); |
737 tile = start_tile; |
709 tile = start_tile; |
738 /* Start tile is the small number. */ |
710 /* Start tile is the small number. */ |
739 for (;;) { |
711 for (;;) { |
740 RoadBits bits = HasBit(p2, 2) ? ROAD_Y : ROAD_X; |
712 RoadBits bits = HasBit(p2, 2) ? ROAD_Y : ROAD_X; |
741 |
713 |
745 /* try to remove the halves. */ |
717 /* try to remove the halves. */ |
746 if (bits != 0) { |
718 if (bits != 0) { |
747 ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD); |
719 ret = DoCommand(tile, rt << 4 | bits, 0, flags & ~DC_EXEC, CMD_REMOVE_ROAD); |
748 if (CmdSucceeded(ret)) { |
720 if (CmdSucceeded(ret)) { |
749 if (flags & DC_EXEC) { |
721 if (flags & DC_EXEC) { |
750 money.AddCost(-ret.GetCost()); |
722 money -= ret.GetCost(); |
751 if (money.GetCost() < 0) { |
723 if (money < 0) { |
752 _additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost(); |
724 _additional_cash_required = DoCommand(end_tile, start_tile, p2, flags & ~DC_EXEC, CMD_REMOVE_LONG_ROAD).GetCost(); |
753 return cost; |
725 return cost; |
754 } |
726 } |
755 DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
727 DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
756 } |
728 } |
779 CommandCost CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
751 CommandCost CmdBuildRoadDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
780 { |
752 { |
781 CommandCost cost; |
753 CommandCost cost; |
782 Slope tileh; |
754 Slope tileh; |
783 |
755 |
784 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
785 |
|
786 DiagDirection dir = Extract<DiagDirection, 0>(p1); |
756 DiagDirection dir = Extract<DiagDirection, 0>(p1); |
787 RoadType rt = (RoadType)GB(p1, 2, 2); |
757 RoadType rt = (RoadType)GB(p1, 2, 2); |
788 |
758 |
789 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
759 if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; |
790 |
760 |
841 * to clear town road OR we are not using the DC_AUTO flag */ |
811 * to clear town road OR we are not using the DC_AUTO flag */ |
842 if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || |
812 if ((CountBits(b) == 1 && GetRoadBits(tile, ROADTYPE_TRAM) == ROAD_NONE) || |
843 IsTileOwner(tile, OWNER_TOWN) || !(flags & DC_AUTO) |
813 IsTileOwner(tile, OWNER_TOWN) || !(flags & DC_AUTO) |
844 ) { |
814 ) { |
845 RoadTypes rts = GetRoadTypes(tile); |
815 RoadTypes rts = GetRoadTypes(tile); |
846 CommandCost ret; |
816 CommandCost ret(EXPENSES_CONSTRUCTION); |
847 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
817 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
848 if (HasBit(rts, rt)) { |
818 if (HasBit(rts, rt)) { |
849 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
819 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
850 if (CmdFailed(tmp_ret)) return tmp_ret; |
820 if (CmdFailed(tmp_ret)) return tmp_ret; |
851 ret.AddCost(tmp_ret); |
821 ret.AddCost(tmp_ret); |
856 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
826 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
857 } |
827 } |
858 |
828 |
859 case ROAD_TILE_CROSSING: { |
829 case ROAD_TILE_CROSSING: { |
860 RoadTypes rts = GetRoadTypes(tile); |
830 RoadTypes rts = GetRoadTypes(tile); |
861 CommandCost ret; |
831 CommandCost ret(EXPENSES_CONSTRUCTION); |
862 |
832 |
863 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
833 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
864 |
834 |
865 /* Must iterate over the roadtypes in a reverse manner because |
835 /* Must iterate over the roadtypes in a reverse manner because |
866 * tram tracks must be removed before the road bits. */ |
836 * tram tracks must be removed before the road bits. */ |
1240 |
1210 |
1241 /* Show an animation to indicate road work */ |
1211 /* Show an animation to indicate road work */ |
1242 if (t->road_build_months != 0 && |
1212 if (t->road_build_months != 0 && |
1243 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
1213 (DistanceManhattan(t->xy, tile) < 8 || grp != 0) && |
1244 GetRoadTileType(tile) == ROAD_TILE_NORMAL && CountBits(GetAllRoadBits(tile)) > 1 ) { |
1214 GetRoadTileType(tile) == ROAD_TILE_NORMAL && CountBits(GetAllRoadBits(tile)) > 1 ) { |
1245 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && CHANCE16(1, 40)) { |
1215 if (GetTileSlope(tile, NULL) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile) && Chance16(1, 40)) { |
1246 StartRoadWorks(tile); |
1216 StartRoadWorks(tile); |
1247 |
1217 |
1248 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
1218 SndPlayTileFx(SND_21_JACKHAMMER, tile); |
1249 CreateEffectVehicleAbove( |
1219 CreateEffectVehicleAbove( |
1250 TileX(tile) * TILE_SIZE + 7, |
1220 TileX(tile) * TILE_SIZE + 7, |
1367 */ |
1337 */ |
1368 static const byte _roadveh_enter_depot_dir[4] = { |
1338 static const byte _roadveh_enter_depot_dir[4] = { |
1369 TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE |
1339 TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE |
1370 }; |
1340 }; |
1371 |
1341 |
1372 static uint32 VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y) |
1342 static VehicleEnterTileStatus VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y) |
1373 { |
1343 { |
1374 switch (GetRoadTileType(tile)) { |
1344 switch (GetRoadTileType(tile)) { |
1375 case ROAD_TILE_CROSSING: |
1345 case ROAD_TILE_CROSSING: |
1376 if (v->type == VEH_TRAIN && !IsCrossingBarred(tile)) { |
1346 if (v->type == VEH_TRAIN && !IsCrossingBarred(tile)) { |
1377 /* train crossing a road */ |
1347 /* train crossing a road */ |
1437 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1407 static CommandCost TerraformTile_Road(TileIndex tile, uint32 flags, uint z_new, Slope tileh_new) |
1438 { |
1408 { |
1439 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
1409 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
1440 switch (GetRoadTileType(tile)) { |
1410 switch (GetRoadTileType(tile)) { |
1441 case ROAD_TILE_CROSSING: |
1411 case ROAD_TILE_CROSSING: |
1442 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return _price.terraform; |
1412 if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new)) && HasBit(VALID_LEVEL_CROSSING_SLOPES, tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
1443 break; |
1413 break; |
1444 |
1414 |
1445 case ROAD_TILE_DEPOT: |
1415 case ROAD_TILE_DEPOT: |
1446 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return _price.terraform; |
1416 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRoadDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
1447 break; |
1417 break; |
1448 |
1418 |
1449 case ROAD_TILE_NORMAL: { |
1419 case ROAD_TILE_NORMAL: { |
1450 RoadBits bits = GetAllRoadBits(tile); |
1420 RoadBits bits = GetAllRoadBits(tile); |
1451 RoadBits bits_copy = bits; |
1421 RoadBits bits_copy = bits; |
1459 /* Get the slope on top of the foundation */ |
1429 /* Get the slope on top of the foundation */ |
1460 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old); |
1430 z_old += ApplyFoundationToSlope(GetRoadFoundation(tileh_old, bits), &tileh_old); |
1461 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new); |
1431 z_new += ApplyFoundationToSlope(GetRoadFoundation(tileh_new, bits), &tileh_new); |
1462 |
1432 |
1463 /* The surface slope must not be changed */ |
1433 /* The surface slope must not be changed */ |
1464 if ((z_old == z_new) && (tileh_old == tileh_new)) return _price.terraform; |
1434 if ((z_old == z_new) && (tileh_old == tileh_new)) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
1465 } |
1435 } |
1466 } |
1436 } |
1467 break; |
1437 break; |
1468 } |
1438 } |
1469 |
1439 |