97 /** Delete a piece of road. |
98 /** Delete a piece of road. |
98 * @param tile tile where to remove road from |
99 * @param tile tile where to remove road from |
99 * @param flags operation to perform |
100 * @param flags operation to perform |
100 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
101 * @param p1 bit 0..3 road pieces to remove (RoadBits) |
101 * bit 4..5 road type |
102 * bit 4..5 road type |
|
103 * bit 6 ignore the fact that the tram track has not been removed |
|
104 * yet when removing the road bits when not actually doing |
|
105 * it. Makes it possible to test whether the road bits can |
|
106 * be removed from a level crossing without physically |
|
107 * removing the tram bits before the test. |
102 * @param p2 unused |
108 * @param p2 unused |
103 */ |
109 */ |
104 int32 CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
110 CommandCost CmdRemoveRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
105 { |
111 { |
106 /* cost for removing inner/edge -roads */ |
112 /* cost for removing inner/edge -roads */ |
107 static const uint16 road_remove_cost[2] = {50, 18}; |
113 static const uint16 road_remove_cost[2] = {50, 18}; |
108 |
114 |
109 Town *t; |
|
110 /* true if the roadpiece was always removeable, |
115 /* true if the roadpiece was always removeable, |
111 * false if it was a center piece. Affects town ratings drop */ |
116 * false if it was a center piece. Affects town ratings drop */ |
112 bool edge_road; |
117 bool edge_road; |
113 |
118 |
114 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
119 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
115 |
120 |
116 RoadType rt = (RoadType)GB(p1, 4, 2); |
121 RoadType rt = (RoadType)GB(p1, 4, 2); |
117 if (!IsValidRoadType(rt)) return CMD_ERROR; |
122 if (!IsValidRoadType(rt)) return CMD_ERROR; |
118 |
123 |
119 Owner owner; |
124 Town *t = NULL; |
120 switch (GetTileType(tile)) { |
125 switch (GetTileType(tile)) { |
121 case MP_STREET: |
126 case MP_STREET: |
122 owner = GetRoadOwner(tile, rt); |
127 if (_game_mode != GM_EDITOR && GetRoadOwner(tile, rt) == OWNER_TOWN) t = GetTownByTile(tile); |
123 break; |
128 break; |
124 |
129 |
125 case MP_STATION: |
130 case MP_STATION: |
126 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
131 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
127 owner = GetTileOwner(tile); |
|
128 break; |
132 break; |
129 |
133 |
130 case MP_TUNNELBRIDGE: |
134 case MP_TUNNELBRIDGE: |
131 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
135 if ((IsTunnel(tile) && GetTunnelTransportType(tile) != TRANSPORT_ROAD) || |
132 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
136 (IsBridge(tile) && GetBridgeTransportType(tile) != TRANSPORT_ROAD)) return CMD_ERROR; |
133 owner = GetTileOwner(tile); |
|
134 break; |
137 break; |
135 |
138 |
136 default: |
139 default: |
137 return CMD_ERROR; |
140 return CMD_ERROR; |
138 } |
|
139 |
|
140 if (owner == OWNER_TOWN && _game_mode != GM_EDITOR) { |
|
141 t = GetTownByTile(tile); |
|
142 } else { |
|
143 t = NULL; |
|
144 } |
141 } |
145 |
142 |
146 RoadBits pieces = Extract<RoadBits, 0>(p1); |
143 RoadBits pieces = Extract<RoadBits, 0>(p1); |
147 RoadTypes rts = GetRoadTypes(tile); |
144 RoadTypes rts = GetRoadTypes(tile); |
148 /* The tile doesn't have the given road type */ |
145 /* The tile doesn't have the given road type */ |
158 |
155 |
159 if (!IsTileType(tile, MP_STREET)) { |
156 if (!IsTileType(tile, MP_STREET)) { |
160 /* If it's the last roadtype, just clear the whole tile */ |
157 /* If it's the last roadtype, just clear the whole tile */ |
161 if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
158 if (rts == RoadTypeToRoadTypes(rt)) return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
162 |
159 |
163 int32 cost; |
160 CommandCost cost; |
164 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
161 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
165 TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile); |
162 TileIndex other_end = IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile); |
166 /* Pay for *every* tile of the bridge or tunnel */ |
163 /* Pay for *every* tile of the bridge or tunnel */ |
167 cost = (DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road; |
164 cost.AddCost((DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile) + 1) * _price.remove_road); |
168 if (flags & DC_EXEC) { |
165 if (flags & DC_EXEC) { |
169 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
166 SetRoadTypes(other_end, GetRoadTypes(other_end) & ~RoadTypeToRoadTypes(rt)); |
170 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
167 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
171 |
168 |
172 /* Mark tiles diry that have been repaved */ |
169 /* Mark tiles diry that have been repaved */ |
177 |
174 |
178 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
175 for (TileIndex t = tile + delta; t != other_end; t += delta) MarkTileDirtyByTile(t); |
179 } |
176 } |
180 } |
177 } |
181 } else { |
178 } else { |
182 cost = _price.remove_road; |
179 cost.AddCost(_price.remove_road); |
183 if (flags & DC_EXEC) { |
180 if (flags & DC_EXEC) { |
184 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
181 SetRoadTypes(tile, GetRoadTypes(tile) & ~RoadTypeToRoadTypes(rt)); |
185 MarkTileDirtyByTile(tile); |
182 MarkTileDirtyByTile(tile); |
186 } |
183 } |
187 } |
184 } |
188 return cost; |
185 return CommandCost(cost); |
189 } |
186 } |
190 |
187 |
191 switch (GetRoadTileType(tile)) { |
188 switch (GetRoadTileType(tile)) { |
192 case ROAD_TILE_NORMAL: { |
189 case ROAD_TILE_NORMAL: { |
193 RoadBits present = GetRoadBits(tile, rt); |
190 RoadBits present = GetRoadBits(tile, rt); |
224 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
221 if (rt != ROADTYPE_TRAM) SetDisallowedRoadDirections(tile, DRD_NONE); |
225 SetRoadBits(tile, present, rt); |
222 SetRoadBits(tile, present, rt); |
226 MarkTileDirtyByTile(tile); |
223 MarkTileDirtyByTile(tile); |
227 } |
224 } |
228 } |
225 } |
229 return CountRoadBits(c) * _price.remove_road; |
226 return CommandCost(CountRoadBits(c) * _price.remove_road); |
230 } |
227 } |
231 |
228 |
232 case ROAD_TILE_CROSSING: { |
229 case ROAD_TILE_CROSSING: { |
233 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
230 if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { |
234 return CMD_ERROR; |
231 return CMD_ERROR; |
235 } |
232 } |
236 |
233 |
237 /* Don't allow road to be removed from the crossing when there is tram; |
234 /* Don't allow road to be removed from the crossing when there is tram; |
238 * we can't draw the crossing without trambits ;) */ |
235 * we can't draw the crossing without trambits ;) */ |
239 if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM)) return CMD_ERROR; |
236 if (rt == ROADTYPE_ROAD && HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) && ((flags & DC_EXEC) || !HASBIT(p1, 6))) return CMD_ERROR; |
240 |
237 |
241 if (flags & DC_EXEC) { |
238 if (flags & DC_EXEC) { |
242 if (rt == ROADTYPE_ROAD) { |
239 if (rt == ROADTYPE_ROAD) { |
243 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
240 ChangeTownRating(t, -road_remove_cost[(byte)edge_road], RATING_ROAD_MINIMUM); |
244 } |
241 } |
312 |
309 |
313 /* no special foundation */ |
310 /* no special foundation */ |
314 if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) { |
311 if ((~_valid_tileh_slopes_road[0][tileh] & road_bits) == 0) { |
315 /* force that all bits are set when we have slopes */ |
312 /* force that all bits are set when we have slopes */ |
316 if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh]; |
313 if (tileh != SLOPE_FLAT) *pieces |= _valid_tileh_slopes_road[0][tileh]; |
317 return 0; // no extra cost |
314 return CommandCost(); // no extra cost |
318 } |
315 } |
319 |
316 |
320 /* foundation is used. Whole tile is leveled up */ |
317 /* foundation is used. Whole tile is leveled up */ |
321 if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) { |
318 if ((~_valid_tileh_slopes_road[1][tileh] & road_bits) == 0) { |
322 return existing != 0 ? 0 : _price.terraform; |
319 return CommandCost(existing != 0 ? 0 : _price.terraform); |
323 } |
320 } |
324 |
321 |
325 /* partly leveled up tile, only if there's no road on that tile */ |
322 /* partly leveled up tile, only if there's no road on that tile */ |
326 if (existing == 0 && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { |
323 if (existing == 0 && (tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)) { |
327 /* force full pieces. */ |
324 /* force full pieces. */ |
338 * @param p1 bit 0..3 road pieces to build (RoadBits) |
335 * @param p1 bit 0..3 road pieces to build (RoadBits) |
339 * bit 4..5 road type |
336 * bit 4..5 road type |
340 * bit 6..7 disallowed directions to toggle |
337 * bit 6..7 disallowed directions to toggle |
341 * @param p2 the town that is building the road (0 if not applicable) |
338 * @param p2 the town that is building the road (0 if not applicable) |
342 */ |
339 */ |
343 int32 CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
340 CommandCost CmdBuildRoad(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
344 { |
341 { |
345 int32 cost = 0; |
342 CommandCost cost; |
346 int32 ret; |
343 CommandCost ret; |
347 RoadBits existing = ROAD_NONE; |
344 RoadBits existing = ROAD_NONE; |
348 RoadBits all_bits = ROAD_NONE; |
345 RoadBits all_bits = ROAD_NONE; |
349 Slope tileh; |
346 Slope tileh; |
350 |
347 |
351 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
348 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
443 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
440 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetTrackBits(tile))); |
444 /* Always add road to the roadtypes (can't draw without it) */ |
441 /* Always add road to the roadtypes (can't draw without it) */ |
445 MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); |
442 MakeRoadCrossing(tile, _current_player, _current_player, _current_player, GetTileOwner(tile), roaddir, GetRailType(tile), RoadTypeToRoadTypes(rt) | ROADTYPES_ROAD, p2); |
446 MarkTileDirtyByTile(tile); |
443 MarkTileDirtyByTile(tile); |
447 } |
444 } |
448 return _price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4); |
445 return CommandCost(_price.build_road * (rt == ROADTYPE_ROAD ? 2 : 4)); |
449 } |
446 } |
450 |
447 |
451 case MP_STATION: |
448 case MP_STATION: |
452 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
449 if (!IsDriveThroughStopTile(tile)) return CMD_ERROR; |
453 if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
450 if (HASBIT(GetRoadTypes(tile), rt)) return_cmd_error(STR_1007_ALREADY_BUILT); |
465 |
462 |
466 default: |
463 default: |
467 do_clear:; |
464 do_clear:; |
468 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
465 ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
469 if (CmdFailed(ret)) return ret; |
466 if (CmdFailed(ret)) return ret; |
470 cost += ret; |
467 cost.AddCost(ret); |
471 } |
468 } |
472 |
469 |
473 if (all_bits != pieces) { |
470 if (all_bits != pieces) { |
474 /* Check the foundation/slopes when adding road/tram bits */ |
471 /* Check the foundation/slopes when adding road/tram bits */ |
475 ret = CheckRoadSlope(tileh, &pieces, all_bits | existing); |
472 ret = CheckRoadSlope(tileh, &pieces, all_bits | existing); |
476 /* Return an error if we need to build a foundation (ret != 0) but the |
473 /* Return an error if we need to build a foundation (ret != 0) but the |
477 * current patch-setting is turned off (or stupid AI@work) */ |
474 * current patch-setting is turned off (or stupid AI@work) */ |
478 if (CmdFailed(ret) || (ret != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) { |
475 if (CmdFailed(ret) || (ret.GetCost() != 0 && (!_patches.build_on_slopes || _is_old_ai_player))) { |
479 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
476 return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
480 } |
477 } |
481 cost += ret; |
478 cost.AddCost(ret); |
482 } |
479 } |
483 |
480 |
484 if (IsTileType(tile, MP_STREET)) { |
481 if (IsTileType(tile, MP_STREET)) { |
485 /* Don't put the pieces that already exist */ |
482 /* Don't put the pieces that already exist */ |
486 pieces &= ComplementRoadBits(existing); |
483 pieces &= ComplementRoadBits(existing); |
487 } |
484 } |
488 |
485 |
489 cost += CountRoadBits(pieces) * _price.build_road; |
486 cost.AddCost(CountRoadBits(pieces) * _price.build_road); |
490 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
487 if (IsTileType(tile, MP_TUNNELBRIDGE)) { |
491 /* Pay for *every* tile of the bridge or tunnel */ |
488 /* Pay for *every* tile of the bridge or tunnel */ |
492 cost *= DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile); |
489 cost.MultiplyCost(DistanceManhattan(IsTunnel(tile) ? GetOtherTunnelEnd(tile) : GetOtherBridgeEnd(tile), tile)); |
493 } |
490 } |
494 |
491 |
495 if (flags & DC_EXEC) { |
492 if (flags & DC_EXEC) { |
496 switch (GetTileType(tile)) { |
493 switch (GetTileType(tile)) { |
497 case MP_STREET: { |
494 case MP_STREET: { |
498 RoadTileType rtt = GetRoadTileType(tile); |
495 RoadTileType rtt = GetRoadTileType(tile); |
499 if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) { |
496 if (existing == ROAD_NONE || rtt == ROAD_TILE_CROSSING) { |
500 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); |
497 SetRoadTypes(tile, GetRoadTypes(tile) | RoadTypeToRoadTypes(rt)); |
501 SetRoadOwner(tile, rt, _current_player); |
498 SetRoadOwner(tile, rt, _current_player); |
|
499 if (_current_player == OWNER_TOWN && rt == ROADTYPE_ROAD) SetTownIndex(tile, p2); |
502 } |
500 } |
503 if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt); |
501 if (rtt != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rt); |
504 } break; |
502 } break; |
505 |
503 |
506 case MP_TUNNELBRIDGE: { |
504 case MP_TUNNELBRIDGE: { |
545 * @param totype The railtype we want to convert to |
543 * @param totype The railtype we want to convert to |
546 * @param exec Switches between test and execute mode |
544 * @param exec Switches between test and execute mode |
547 * @return The cost and state of the operation |
545 * @return The cost and state of the operation |
548 * @retval CMD_ERROR An error occured during the operation. |
546 * @retval CMD_ERROR An error occured during the operation. |
549 */ |
547 */ |
550 int32 DoConvertStreetRail(TileIndex tile, RailType totype, bool exec) |
548 CommandCost DoConvertStreetRail(TileIndex tile, RailType totype, bool exec) |
551 { |
549 { |
552 /* not a railroad crossing? */ |
550 /* not a railroad crossing? */ |
553 if (!IsLevelCrossing(tile)) return CMD_ERROR; |
551 if (!IsLevelCrossing(tile)) return CMD_ERROR; |
554 |
552 |
555 /* not owned by me? */ |
553 /* not owned by me? */ |
564 SetRailType(tile, totype); |
562 SetRailType(tile, totype); |
565 MarkTileDirtyByTile(tile); |
563 MarkTileDirtyByTile(tile); |
566 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile))); |
564 YapfNotifyTrackLayoutChange(tile, FindFirstTrack(GetCrossingRailBits(tile))); |
567 } |
565 } |
568 |
566 |
569 return _price.build_rail / 2; |
567 return CommandCost(_price.build_rail / 2); |
570 } |
568 } |
571 |
569 |
572 |
570 |
573 /** Build a long piece of road. |
571 /** Build a long piece of road. |
574 * @param end_tile end tile of drag |
572 * @param end_tile end tile of drag |
579 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
577 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
580 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
578 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
581 * - p2 = (bit 3 + 4) - road type |
579 * - p2 = (bit 3 + 4) - road type |
582 * - p2 = (bit 5) - set road direction |
580 * - p2 = (bit 5) - set road direction |
583 */ |
581 */ |
584 int32 CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
582 CommandCost CmdBuildLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
585 { |
583 { |
586 TileIndex start_tile, tile; |
584 TileIndex start_tile, tile; |
587 int32 cost, ret; |
585 CommandCost cost, ret; |
588 bool had_bridge = false; |
586 bool had_bridge = false; |
589 bool had_success = false; |
587 bool had_success = false; |
590 DisallowedRoadDirections drd = DRD_NORTHBOUND; |
588 DisallowedRoadDirections drd = DRD_NORTHBOUND; |
591 |
589 |
592 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
590 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
615 * when you just 'click' on one tile to build them. */ |
613 * when you just 'click' on one tile to build them. */ |
616 if (HASBIT(p2, 2) == (start_tile == end_tile)) drd ^= DRD_BOTH; |
614 if (HASBIT(p2, 2) == (start_tile == end_tile)) drd ^= DRD_BOTH; |
617 /* No disallowed direction bits have to be toggled */ |
615 /* No disallowed direction bits have to be toggled */ |
618 if (!HASBIT(p2, 5)) drd = DRD_NONE; |
616 if (!HASBIT(p2, 5)) drd = DRD_NONE; |
619 |
617 |
620 cost = 0; |
|
621 tile = start_tile; |
618 tile = start_tile; |
622 /* Start tile is the small number. */ |
619 /* Start tile is the small number. */ |
623 for (;;) { |
620 for (;;) { |
624 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
621 RoadBits bits = HASBIT(p2, 2) ? ROAD_Y : ROAD_X; |
625 |
622 |
659 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
656 * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) |
660 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
657 * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) |
661 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
658 * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) |
662 * - p2 = (bit 3 + 4) - road type |
659 * - p2 = (bit 3 + 4) - road type |
663 */ |
660 */ |
664 int32 CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
661 CommandCost CmdRemoveLongRoad(TileIndex end_tile, uint32 flags, uint32 p1, uint32 p2) |
665 { |
662 { |
666 TileIndex start_tile, tile; |
663 TileIndex start_tile, tile; |
667 int32 cost, ret; |
664 CommandCost cost, ret; |
668 |
665 |
669 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
666 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
670 |
667 |
671 if (p1 >= MapSize()) return CMD_ERROR; |
668 if (p1 >= MapSize()) return CMD_ERROR; |
672 |
669 |
696 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
692 if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW; |
697 |
693 |
698 /* try to remove the halves. */ |
694 /* try to remove the halves. */ |
699 if (bits != 0) { |
695 if (bits != 0) { |
700 ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
696 ret = DoCommand(tile, rt << 4 | bits, 0, flags, CMD_REMOVE_ROAD); |
701 if (!CmdFailed(ret)) cost += ret; |
697 if (CmdSucceeded(ret)) cost.AddCost(ret); |
702 } |
698 } |
703 |
699 |
704 if (tile == end_tile) break; |
700 if (tile == end_tile) break; |
705 |
701 |
706 tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0); |
702 tile += HASBIT(p2, 2) ? TileDiffXY(0, 1) : TileDiffXY(1, 0); |
707 } |
703 } |
708 |
704 |
709 return (cost == 0) ? CMD_ERROR : cost; |
705 return (cost.GetCost() == 0) ? CMD_ERROR : cost; |
710 } |
706 } |
711 |
707 |
712 /** Build a road depot. |
708 /** Build a road depot. |
713 * @param tile tile where to build the depot |
709 * @param tile tile where to build the depot |
714 * @param flags operation to perform |
710 * @param flags operation to perform |
754 dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; |
750 dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index; |
755 |
751 |
756 MakeRoadDepot(tile, _current_player, dir, rt); |
752 MakeRoadDepot(tile, _current_player, dir, rt); |
757 MarkTileDirtyByTile(tile); |
753 MarkTileDirtyByTile(tile); |
758 } |
754 } |
759 return cost + _price.build_road_depot; |
755 return cost.AddCost(_price.build_road_depot); |
760 } |
756 } |
761 |
757 |
762 static int32 RemoveRoadDepot(TileIndex tile, uint32 flags) |
758 static CommandCost RemoveRoadDepot(TileIndex tile, uint32 flags) |
763 { |
759 { |
764 if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) |
760 if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER) |
765 return CMD_ERROR; |
761 return CMD_ERROR; |
766 |
762 |
767 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
763 if (!EnsureNoVehicle(tile)) return CMD_ERROR; |
768 |
764 |
769 if (flags & DC_EXEC) DeleteDepot(GetDepotByTile(tile)); |
765 if (flags & DC_EXEC) DeleteDepot(GetDepotByTile(tile)); |
770 |
766 |
771 return _price.remove_road_depot; |
767 return CommandCost(_price.remove_road_depot); |
772 } |
768 } |
773 |
769 |
774 static int32 ClearTile_Road(TileIndex tile, byte flags) |
770 static CommandCost ClearTile_Road(TileIndex tile, byte flags) |
775 { |
771 { |
776 switch (GetRoadTileType(tile)) { |
772 switch (GetRoadTileType(tile)) { |
777 case ROAD_TILE_NORMAL: { |
773 case ROAD_TILE_NORMAL: { |
778 RoadBits b = GetAllRoadBits(tile); |
774 RoadBits b = GetAllRoadBits(tile); |
779 |
775 |
783 if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || |
779 if ((M(b) & (M(ROAD_NW) | M(ROAD_SW) | M(ROAD_SE) | M(ROAD_NE))) || |
784 ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) || |
780 ((flags & DC_AI_BUILDING) && IsTileOwner(tile, OWNER_TOWN)) || |
785 !(flags & DC_AUTO) |
781 !(flags & DC_AUTO) |
786 ) { |
782 ) { |
787 RoadTypes rts = GetRoadTypes(tile); |
783 RoadTypes rts = GetRoadTypes(tile); |
788 int32 ret = 0; |
784 CommandCost ret; |
789 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
785 for (RoadType rt = ROADTYPE_ROAD; rt < ROADTYPE_END; rt++) { |
790 if (HASBIT(rts, rt)) { |
786 if (HASBIT(rts, rt)) { |
791 int32 tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
787 CommandCost tmp_ret = DoCommand(tile, rt << 4 | GetRoadBits(tile, rt), 0, flags, CMD_REMOVE_ROAD); |
792 if (CmdFailed(tmp_ret)) return tmp_ret; |
788 if (CmdFailed(tmp_ret)) return tmp_ret; |
793 ret += tmp_ret; |
789 ret.AddCost(tmp_ret); |
794 } |
790 } |
795 } |
791 } |
796 return ret; |
792 return ret; |
797 } |
793 } |
798 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
794 return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
799 } |
795 } |
800 #undef M |
796 #undef M |
801 |
797 |
802 case ROAD_TILE_CROSSING: { |
798 case ROAD_TILE_CROSSING: { |
803 int32 ret; |
799 RoadTypes rts = GetRoadTypes(tile); |
|
800 CommandCost ret; |
804 |
801 |
805 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
802 if (flags & DC_AUTO) return_cmd_error(STR_1801_MUST_REMOVE_ROAD_FIRST); |
806 |
803 |
807 ret = DoCommand(tile, GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
804 /* Must iterate over the roadtypes in a reverse manner because |
808 if (CmdFailed(ret)) return CMD_ERROR; |
805 * tram tracks must be removed before the road bits. */ |
|
806 for (RoadType rt = ROADTYPE_HWAY; rt >= ROADTYPE_ROAD; rt--) { |
|
807 if (HASBIT(rts, rt)) { |
|
808 CommandCost tmp_ret = DoCommand(tile, 1 << 6 | rt << 4 | GetCrossingRoadBits(tile), 0, flags, CMD_REMOVE_ROAD); |
|
809 if (CmdFailed(tmp_ret)) return tmp_ret; |
|
810 ret.AddCost(tmp_ret); |
|
811 } |
|
812 } |
809 |
813 |
810 if (flags & DC_EXEC) { |
814 if (flags & DC_EXEC) { |
811 DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
815 DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
812 } |
816 } |
813 return ret; |
817 return ret; |
978 } |
982 } |
979 } |
983 } |
980 |
984 |
981 DrawGroundSprite(image, pal); |
985 DrawGroundSprite(image, pal); |
982 |
986 |
983 if (road != ROAD_NONE) { |
|
984 DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile); |
|
985 if (drd != DRD_NONE) { |
|
986 DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0); |
|
987 } |
|
988 } |
|
989 |
|
990 /* For tram we overlay the road graphics with either tram tracks only |
987 /* For tram we overlay the road graphics with either tram tracks only |
991 * (when there is actual road beneath the trams) or with tram tracks |
988 * (when there is actual road beneath the trams) or with tram tracks |
992 * and some dirts which hides the road graphics */ |
989 * and some dirts which hides the road graphics */ |
993 if (tram != ROAD_NONE) { |
990 if (tram != ROAD_NONE) { |
994 if (ti->tileh != SLOPE_FLAT) { |
991 if (ti->tileh != SLOPE_FLAT) { |
996 } else { |
993 } else { |
997 image = _road_tile_sprites_1[tram] - SPR_ROAD_Y; |
994 image = _road_tile_sprites_1[tram] - SPR_ROAD_Y; |
998 } |
995 } |
999 image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY; |
996 image += (road == ROAD_NONE) ? SPR_TRAMWAY_TRAM : SPR_TRAMWAY_OVERLAY; |
1000 DrawGroundSprite(image, pal); |
997 DrawGroundSprite(image, pal); |
|
998 } |
|
999 |
|
1000 if (road != ROAD_NONE) { |
|
1001 DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile); |
|
1002 if (drd != DRD_NONE) { |
|
1003 DrawRoadDetail(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), ti, 8, 8, 0); |
|
1004 } |
1001 } |
1005 } |
1002 |
1006 |
1003 if (HasRoadWorks(ti->tile)) { |
1007 if (HasRoadWorks(ti->tile)) { |
1004 /* Road works */ |
1008 /* Road works */ |
1005 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); |
1009 DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); |
1344 |
1348 |
1345 case ROAD_TILE_DEPOT: |
1349 case ROAD_TILE_DEPOT: |
1346 if (v->type == VEH_ROAD && |
1350 if (v->type == VEH_ROAD && |
1347 v->u.road.frame == 11 && |
1351 v->u.road.frame == 11 && |
1348 _roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) { |
1352 _roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == v->u.road.state) { |
1349 VehicleEnterDepot(v); |
1353 v->u.road.state = RVSB_IN_DEPOT; |
|
1354 v->vehstatus |= VS_HIDDEN; |
|
1355 v->direction = ReverseDir(v->direction); |
|
1356 if (v->next == NULL) VehicleEnterDepot(v); |
|
1357 v->tile = tile; |
|
1358 |
|
1359 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); |
1350 return VETSB_ENTERED_WORMHOLE; |
1360 return VETSB_ENTERED_WORMHOLE; |
1351 } |
1361 } |
1352 break; |
1362 break; |
1353 |
1363 |
1354 default: break; |
1364 default: break; |