286 if ((f_new == FOUNDATION_INVALID) || |
286 if ((f_new == FOUNDATION_INVALID) || |
287 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) |
287 ((f_new != FOUNDATION_NONE) && (!_patches.build_on_slopes || _is_old_ai_player)) |
288 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
288 ) return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION); |
289 |
289 |
290 Foundation f_old = GetRailFoundation(tileh, existing); |
290 Foundation f_old = GetRailFoundation(tileh, existing); |
291 return CommandCost(f_new != f_old ? _price.terraform : (Money)0); |
291 return CommandCost(EXPENSES_CONSTRUCTION, f_new != f_old ? _price.terraform : (Money)0); |
292 } |
292 } |
293 |
293 |
294 /* Validate functions for rail building */ |
294 /* Validate functions for rail building */ |
295 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
295 static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(track);} |
296 |
296 |
304 { |
304 { |
305 Slope tileh; |
305 Slope tileh; |
306 RailType railtype; |
306 RailType railtype; |
307 Track track; |
307 Track track; |
308 TrackBits trackbit; |
308 TrackBits trackbit; |
309 CommandCost cost; |
309 CommandCost cost(EXPENSES_CONSTRUCTION); |
310 CommandCost ret; |
310 CommandCost ret; |
311 |
311 |
312 if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
312 if (!ValParamRailtype(p1) || !ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
313 railtype = (RailType)p1; |
313 railtype = (RailType)p1; |
314 track = (Track)p2; |
314 track = (Track)p2; |
315 |
315 |
316 tileh = GetTileSlope(tile, NULL); |
316 tileh = GetTileSlope(tile, NULL); |
317 trackbit = TrackToTrackBits(track); |
317 trackbit = TrackToTrackBits(track); |
318 |
|
319 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
320 |
318 |
321 switch (GetTileType(tile)) { |
319 switch (GetTileType(tile)) { |
322 case MP_RAILWAY: |
320 case MP_RAILWAY: |
323 if (!CheckTrackCombination(tile, trackbit, flags) || |
321 if (!CheckTrackCombination(tile, trackbit, flags) || |
324 !EnsureNoTrainOnTrack(tile, track)) { |
322 !EnsureNoTrainOnTrack(tile, track)) { |
436 */ |
434 */ |
437 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
435 CommandCost CmdRemoveSingleRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
438 { |
436 { |
439 Track track = (Track)p2; |
437 Track track = (Track)p2; |
440 TrackBits trackbit; |
438 TrackBits trackbit; |
441 CommandCost cost(_price.remove_rail); |
439 CommandCost cost(EXPENSES_CONSTRUCTION, _price.remove_rail ); |
442 bool crossing = false; |
440 bool crossing = false; |
443 |
441 |
444 if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
442 if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; |
445 trackbit = TrackToTrackBits(track); |
443 trackbit = TrackToTrackBits(track); |
446 |
|
447 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
448 |
444 |
449 switch (GetTileType(tile)) { |
445 switch (GetTileType(tile)) { |
450 case MP_ROAD: { |
446 case MP_ROAD: { |
451 if (!IsLevelCrossing(tile) || |
447 if (!IsLevelCrossing(tile) || |
452 GetCrossingRailBits(tile) != trackbit || |
448 GetCrossingRailBits(tile) != trackbit || |
622 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) |
618 * - p2 = (bit 4-6) - track-orientation, valid values: 0-5 (Track enum) |
623 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
619 * - p2 = (bit 7) - 0 = build, 1 = remove tracks |
624 */ |
620 */ |
625 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
621 static CommandCost CmdRailTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
626 { |
622 { |
627 CommandCost ret, total_cost; |
623 CommandCost ret, total_cost(EXPENSES_CONSTRUCTION); |
628 Track track = (Track)GB(p2, 4, 3); |
624 Track track = (Track)GB(p2, 4, 3); |
629 Trackdir trackdir; |
625 Trackdir trackdir; |
630 byte mode = HasBit(p2, 7); |
626 byte mode = HasBit(p2, 7); |
631 RailType railtype = (RailType)GB(p2, 0, 4); |
627 RailType railtype = (RailType)GB(p2, 0, 4); |
632 TileIndex end_tile; |
628 TileIndex end_tile; |
633 |
629 |
634 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
630 if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
635 if (p1 >= MapSize()) return CMD_ERROR; |
631 if (p1 >= MapSize()) return CMD_ERROR; |
636 end_tile = p1; |
632 end_tile = p1; |
637 trackdir = TrackToTrackdir(track); |
633 trackdir = TrackToTrackdir(track); |
638 |
|
639 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
640 |
634 |
641 if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR; |
635 if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR; |
642 |
636 |
643 if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile); |
637 if (flags & DC_EXEC) SndPlayTileFx(SND_20_SPLAT_2, tile); |
644 |
638 |
704 * @todo When checking for the tile slope, |
698 * @todo When checking for the tile slope, |
705 * distingush between "Flat land required" and "land sloped in wrong direction" |
699 * distingush between "Flat land required" and "land sloped in wrong direction" |
706 */ |
700 */ |
707 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
701 CommandCost CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
708 { |
702 { |
709 CommandCost cost; |
|
710 Slope tileh; |
703 Slope tileh; |
711 |
|
712 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
713 |
704 |
714 /* check railtype and valid direction for depot (0 through 3), 4 in total */ |
705 /* check railtype and valid direction for depot (0 through 3), 4 in total */ |
715 if (!ValParamRailtype(p1)) return CMD_ERROR; |
706 if (!ValParamRailtype(p1)) return CMD_ERROR; |
716 |
707 |
717 tileh = GetTileSlope(tile, NULL); |
708 tileh = GetTileSlope(tile, NULL); |
733 !CanBuildDepotByTileh(dir, tileh) |
724 !CanBuildDepotByTileh(dir, tileh) |
734 )) { |
725 )) { |
735 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
726 return_cmd_error(STR_0007_FLAT_LAND_REQUIRED); |
736 } |
727 } |
737 |
728 |
738 cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
729 CommandCost cost = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); |
739 if (CmdFailed(cost)) return CMD_ERROR; |
730 if (CmdFailed(cost)) return CMD_ERROR; |
740 |
731 |
741 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
732 if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST); |
742 |
733 |
743 Depot *d = new Depot(tile); |
734 Depot *d = new Depot(tile); |
804 } |
795 } |
805 |
796 |
806 /* you can not convert a signal if no signal is on track */ |
797 /* you can not convert a signal if no signal is on track */ |
807 if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR; |
798 if (convert_signal && !HasSignalOnTrack(tile, track)) return CMD_ERROR; |
808 |
799 |
809 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
810 |
|
811 if (!HasSignalOnTrack(tile, track)) { |
800 if (!HasSignalOnTrack(tile, track)) { |
812 /* build new signals */ |
801 /* build new signals */ |
813 cost = CommandCost(_price.build_signals); |
802 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals); |
814 } else { |
803 } else { |
815 if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) { |
804 if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) { |
816 /* convert signals <-> semaphores */ |
805 /* convert signals <-> semaphores */ |
817 cost = CommandCost(_price.build_signals + _price.remove_signals); |
806 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals); |
818 |
807 |
819 } else if (convert_signal) { |
808 } else if (convert_signal) { |
820 /* convert button pressed */ |
809 /* convert button pressed */ |
821 if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) { |
810 if (ctrl_pressed || GetSignalVariant(tile, track) != sigvar) { |
822 /* convert electric <-> semaphore */ |
811 /* convert electric <-> semaphore */ |
823 cost = CommandCost(_price.build_signals + _price.remove_signals); |
812 cost = CommandCost(EXPENSES_CONSTRUCTION, _price.build_signals + _price.remove_signals); |
824 } else { |
813 } else { |
825 /* it is free to change signal type: normal-pre-exit-combo */ |
814 /* it is free to change signal type: normal-pre-exit-combo */ |
826 cost = CommandCost(); |
815 cost = CommandCost(); |
827 } |
816 } |
828 |
817 |
954 * - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill |
943 * - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill |
955 * - p2 = (bit 24-31) - user defined signals_density |
944 * - p2 = (bit 24-31) - user defined signals_density |
956 */ |
945 */ |
957 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
946 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
958 { |
947 { |
959 CommandCost ret, total_cost; |
948 CommandCost ret, total_cost(EXPENSES_CONSTRUCTION); |
960 int signal_ctr; |
949 int signal_ctr; |
961 byte signals; |
950 byte signals; |
962 bool error = true; |
951 bool error = true; |
963 TileIndex end_tile; |
952 TileIndex end_tile; |
964 TileIndex start_tile = tile; |
953 TileIndex start_tile = tile; |
974 if (p1 >= MapSize()) return CMD_ERROR; |
963 if (p1 >= MapSize()) return CMD_ERROR; |
975 end_tile = p1; |
964 end_tile = p1; |
976 if (signal_density == 0 || signal_density > 20) return CMD_ERROR; |
965 if (signal_density == 0 || signal_density > 20) return CMD_ERROR; |
977 |
966 |
978 if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR; |
967 if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR; |
979 |
|
980 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
981 |
968 |
982 /* for vertical/horizontal tracks, double the given signals density |
969 /* for vertical/horizontal tracks, double the given signals density |
983 * since the original amount will be too dense (shorter tracks) */ |
970 * since the original amount will be too dense (shorter tracks) */ |
984 signal_density *= 2; |
971 signal_density *= 2; |
985 |
972 |
1099 } |
1086 } |
1100 |
1087 |
1101 /* Only water can remove signals from anyone */ |
1088 /* Only water can remove signals from anyone */ |
1102 if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR; |
1089 if (_current_player != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR; |
1103 |
1090 |
1104 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
1105 |
|
1106 /* Do it? */ |
1091 /* Do it? */ |
1107 if (flags & DC_EXEC) { |
1092 if (flags & DC_EXEC) { |
1108 SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track)); |
1093 SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track)); |
1109 |
1094 |
1110 /* removed last signal from tile? */ |
1095 /* removed last signal from tile? */ |
1118 YapfNotifyTrackLayoutChange(tile, track); |
1103 YapfNotifyTrackLayoutChange(tile, track); |
1119 |
1104 |
1120 MarkTileDirtyByTile(tile); |
1105 MarkTileDirtyByTile(tile); |
1121 } |
1106 } |
1122 |
1107 |
1123 return CommandCost(_price.remove_signals); |
1108 return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_signals); |
1124 } |
1109 } |
1125 |
1110 |
1126 /** Remove signals on a stretch of track. |
1111 /** Remove signals on a stretch of track. |
1127 * Stub for the unified signal builder/remover |
1112 * Stub for the unified signal builder/remover |
1128 * @param tile start tile of drag |
1113 * @param tile start tile of drag |
1162 * @param p1 start tile of drag |
1147 * @param p1 start tile of drag |
1163 * @param p2 new railtype to convert to |
1148 * @param p2 new railtype to convert to |
1164 */ |
1149 */ |
1165 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1150 CommandCost CmdConvertRail(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) |
1166 { |
1151 { |
1167 CommandCost cost; |
1152 CommandCost cost(EXPENSES_CONSTRUCTION); |
1168 |
1153 |
1169 if (!ValParamRailtype(p2)) return CMD_ERROR; |
1154 if (!ValParamRailtype(p2)) return CMD_ERROR; |
1170 if (p1 >= MapSize()) return CMD_ERROR; |
1155 if (p1 >= MapSize()) return CMD_ERROR; |
1171 |
1156 |
1172 RailType totype = (RailType)p2; |
1157 RailType totype = (RailType)p2; |
1177 uint sy = TileY(p1); |
1162 uint sy = TileY(p1); |
1178 |
1163 |
1179 /* make sure sx,sy are smaller than ex,ey */ |
1164 /* make sure sx,sy are smaller than ex,ey */ |
1180 if (ex < sx) Swap(ex, sx); |
1165 if (ex < sx) Swap(ex, sx); |
1181 if (ey < sy) Swap(ey, sy); |
1166 if (ey < sy) Swap(ey, sy); |
1182 |
|
1183 SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION); |
|
1184 |
1167 |
1185 _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert |
1168 _error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK; // by default, there is no track to convert |
1186 |
1169 |
1187 for (uint x = sx; x <= ex; ++x) { |
1170 for (uint x = sx; x <= ex; ++x) { |
1188 for (uint y = sy; y <= ey; ++y) { |
1171 for (uint y = sy; y <= ey; ++y) { |
1329 delete GetDepotByTile(tile); |
1312 delete GetDepotByTile(tile); |
1330 UpdateSignalsOnSegment(tile, dir); |
1313 UpdateSignalsOnSegment(tile, dir); |
1331 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
1314 YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir))); |
1332 } |
1315 } |
1333 |
1316 |
1334 return CommandCost(_price.remove_train_depot); |
1317 return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot); |
1335 } |
1318 } |
1336 |
1319 |
1337 static CommandCost ClearTile_Track(TileIndex tile, byte flags) |
1320 static CommandCost ClearTile_Track(TileIndex tile, byte flags) |
1338 { |
1321 { |
1339 CommandCost cost; |
1322 CommandCost cost(EXPENSES_CONSTRUCTION); |
1340 CommandCost ret; |
1323 CommandCost ret; |
1341 |
1324 |
1342 if (flags & DC_AUTO) { |
1325 if (flags & DC_AUTO) { |
1343 if (!IsTileOwner(tile, _current_player)) |
1326 if (!IsTileOwner(tile, _current_player)) |
1344 return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER); |
1327 return_cmd_error(STR_1024_AREA_IS_OWNED_BY_ANOTHER); |
2431 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
2414 case TRACK_BIT_LOWER: track_corner = CORNER_S; break; |
2432 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
2415 case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; |
2433 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
2416 case TRACK_BIT_UPPER: track_corner = CORNER_N; break; |
2434 |
2417 |
2435 /* Surface slope must not be changed */ |
2418 /* Surface slope must not be changed */ |
2436 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : _price.terraform); |
2419 default: return (((z_old != z_new) || (tileh_old != tileh_new)) ? CMD_ERROR : CommandCost(EXPENSES_CONSTRUCTION, _price.terraform)); |
2437 } |
2420 } |
2438 |
2421 |
2439 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2422 /* The height of the track_corner must not be changed. The rest ensures GetRailFoundation() already. */ |
2440 z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner); |
2423 z_old += GetSlopeZInCorner((Slope)(tileh_old & ~SLOPE_HALFTILE_MASK), track_corner); |
2441 z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner); |
2424 z_new += GetSlopeZInCorner((Slope)(tileh_new & ~SLOPE_HALFTILE_MASK), track_corner); |
2442 if (z_old != z_new) return CMD_ERROR; |
2425 if (z_old != z_new) return CMD_ERROR; |
2443 |
2426 |
2444 CommandCost cost = CommandCost(_price.terraform); |
2427 CommandCost cost = CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
2445 /* Make the ground dirty, if surface slope has changed */ |
2428 /* Make the ground dirty, if surface slope has changed */ |
2446 if (tileh_old != tileh_new) { |
2429 if (tileh_old != tileh_new) { |
2447 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water); |
2430 if (GetRailGroundType(tile) == RAIL_GROUND_WATER) cost.AddCost(_price.clear_water); |
2448 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2431 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2449 } |
2432 } |
2486 |
2469 |
2487 /* Make the ground dirty */ |
2470 /* Make the ground dirty */ |
2488 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2471 if ((flags & DC_EXEC) != 0) SetRailGroundType(tile, RAIL_GROUND_BARREN); |
2489 |
2472 |
2490 /* allow terraforming */ |
2473 /* allow terraforming */ |
2491 return (was_water ? CommandCost(_price.clear_water) : CommandCost()); |
2474 return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0); |
2492 } else { |
2475 } else { |
2493 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2476 if (_patches.build_on_slopes && AutoslopeEnabled()) { |
2494 switch (GetRailTileType(tile)) { |
2477 switch (GetRailTileType(tile)) { |
2495 case RAIL_TILE_WAYPOINT: { |
2478 case RAIL_TILE_WAYPOINT: { |
2496 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |
2479 CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile)); |
2497 if (!CmdFailed(cost)) return cost; // allow autoslope |
2480 if (!CmdFailed(cost)) return cost; // allow autoslope |
2498 break; |
2481 break; |
2499 } |
2482 } |
2500 |
2483 |
2501 case RAIL_TILE_DEPOT: |
2484 case RAIL_TILE_DEPOT: |
2502 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return _price.terraform; |
2485 if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform); |
2503 break; |
2486 break; |
2504 |
2487 |
2505 default: NOT_REACHED(); |
2488 default: NOT_REACHED(); |
2506 } |
2489 } |
2507 } |
2490 } |