32 #include "window.h" |
32 #include "window.h" |
33 #include "rail.h" |
33 #include "rail.h" |
34 #include "railtypes.h" // include table for railtypes |
34 #include "railtypes.h" // include table for railtypes |
35 #include "newgrf.h" |
35 #include "newgrf.h" |
36 #include "yapf/yapf.h" |
36 #include "yapf/yapf.h" |
|
37 #include "newgrf_engine.h" |
37 #include "newgrf_callbacks.h" |
38 #include "newgrf_callbacks.h" |
38 #include "newgrf_station.h" |
39 #include "newgrf_station.h" |
39 #include "train.h" |
40 #include "train.h" |
40 #include "misc/autoptr.hpp" |
41 #include "misc/autoptr.hpp" |
41 |
42 |
1022 return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit |
1023 return CmdSignalTrackHelper(tile, flags, p1, SETBIT(p2, 5)); // bit 5 is remove bit |
1023 } |
1024 } |
1024 |
1025 |
1025 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); |
1026 typedef CommandCost DoConvertRailProc(TileIndex tile, RailType totype, bool exec); |
1026 |
1027 |
|
1028 void *UpdateTrainPowerProc(Vehicle *v, void *data) |
|
1029 { |
|
1030 /* Similiar checks as in TrainPowerChanged() */ |
|
1031 |
|
1032 if (v->type == VEH_TRAIN && v->tile == *(TileIndex*)data && !IsArticulatedPart(v)) { |
|
1033 const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); |
|
1034 if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First()); |
|
1035 } |
|
1036 |
|
1037 return NULL; |
|
1038 } |
|
1039 |
1027 /** |
1040 /** |
1028 * Switches the rail type. |
1041 * Switches the rail type. |
1029 * Railtypes are stored on a per-tile basis, not on a per-track basis, so |
1042 * Railtypes are stored on a per-tile basis, not on a per-track basis, so |
1030 * all the tracks in the given tile will be converted. |
1043 * all the tracks in the given tile will be converted. |
1031 * @param tile The tile on which the railtype is to be convert. |
1044 * @param tile The tile on which the railtype is to be convert. |
1034 * @return The cost and state of the operation |
1047 * @return The cost and state of the operation |
1035 * @retval CMD_ERROR An error occured during the operation. |
1048 * @retval CMD_ERROR An error occured during the operation. |
1036 */ |
1049 */ |
1037 static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec) |
1050 static CommandCost DoConvertRail(TileIndex tile, RailType totype, bool exec) |
1038 { |
1051 { |
1039 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
|
1040 |
|
1041 if (GetRailType(tile) == totype) return CMD_ERROR; |
|
1042 |
|
1043 if (!EnsureNoVehicleOnGround(tile) && (!IsCompatibleRail(GetRailType(tile), totype) || IsPlainRailTile(tile))) return CMD_ERROR; |
|
1044 |
|
1045 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
|
1046 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
|
1047 |
|
1048 /* change type. */ |
1052 /* change type. */ |
1049 if (exec) { |
1053 if (exec) { |
1050 SetRailType(tile, totype); |
1054 SetRailType(tile, totype); |
1051 MarkTileDirtyByTile(tile); |
1055 MarkTileDirtyByTile(tile); |
1052 |
1056 |
1055 while (tracks != TRACK_BIT_NONE) { |
1059 while (tracks != TRACK_BIT_NONE) { |
1056 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
1060 YapfNotifyTrackLayoutChange(tile, RemoveFirstTrack(&tracks)); |
1057 } |
1061 } |
1058 |
1062 |
1059 if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
1063 if (IsTileDepotType(tile, TRANSPORT_RAIL)) { |
1060 Vehicle *v; |
|
1061 |
|
1062 /* Update build vehicle window related to this depot */ |
1064 /* Update build vehicle window related to this depot */ |
1063 InvalidateWindowData(WC_BUILD_VEHICLE, tile); |
1065 InvalidateWindowData(WC_BUILD_VEHICLE, tile); |
1064 |
1066 } |
1065 /* update power of trains in this depot */ |
1067 |
1066 FOR_ALL_VEHICLES(v) { |
1068 /* update power of train engines on this tile */ |
1067 if (v->type == VEH_TRAIN && IsFrontEngine(v) && v->tile == tile && v->u.rail.track == 0x80) { |
1069 VehicleFromPos(tile, &tile, UpdateTrainPowerProc); |
1068 TrainPowerChanged(v); |
|
1069 } |
|
1070 } |
|
1071 } |
|
1072 } |
1070 } |
1073 |
1071 |
1074 return CommandCost(_price.build_rail / 2); |
1072 return CommandCost(_price.build_rail / 2); |
1075 } |
1073 } |
1076 |
1074 |
1109 money = GetAvailableMoneyForCommand(); |
1107 money = GetAvailableMoneyForCommand(); |
1110 |
1108 |
1111 for (x = sx; x <= ex; ++x) { |
1109 for (x = sx; x <= ex; ++x) { |
1112 for (y = sy; y <= ey; ++y) { |
1110 for (y = sy; y <= ey; ++y) { |
1113 TileIndex tile = TileXY(x, y); |
1111 TileIndex tile = TileXY(x, y); |
1114 DoConvertRailProc* proc; |
1112 DoConvertRailProc *proc; |
|
1113 RailType totype = (RailType)p2; |
1115 |
1114 |
1116 switch (GetTileType(tile)) { |
1115 switch (GetTileType(tile)) { |
1117 case MP_RAILWAY: proc = DoConvertRail; break; |
1116 case MP_RAILWAY: proc = DoConvertRail; break; |
1118 case MP_STATION: proc = DoConvertStationRail; break; |
1117 case MP_STATION: proc = DoConvertStationRail; break; |
1119 case MP_ROAD: proc = DoConvertStreetRail; break; |
1118 case MP_ROAD: proc = DoConvertStreetRail; break; |
1120 case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break; |
1119 case MP_TUNNELBRIDGE: proc = DoConvertTunnelBridgeRail; break; |
1121 default: continue; |
1120 default: continue; |
1122 } |
1121 } |
1123 |
1122 |
1124 ret = proc(tile, (RailType)p2, false); |
1123 /* It is possible that 'type' is invalid when there is no rail on the tile, |
|
1124 * but this situation will be detected in proc() |
|
1125 */ |
|
1126 RailType type = GetRailType(tile); |
|
1127 |
|
1128 /* Not own tile or track is already converted */ |
|
1129 if ((!CheckTileOwnership(tile) || type == totype) || |
|
1130 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
|
1131 (_patches.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC) || |
|
1132 /* Vehicle on a tile while not converting Rail <-> ElRail */ |
|
1133 (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile))) { |
|
1134 ret = CMD_ERROR; |
|
1135 continue; |
|
1136 } |
|
1137 |
|
1138 ret = proc(tile, totype, false); |
1125 if (CmdFailed(ret)) continue; |
1139 if (CmdFailed(ret)) continue; |
1126 |
1140 |
1127 if (flags & DC_EXEC) { |
1141 if (flags & DC_EXEC) { |
1128 money -= ret.GetCost(); |
1142 money -= ret.GetCost(); |
1129 if (money < 0) { |
1143 if (money < 0) { |
1130 _additional_cash_required = ret.GetCost(); |
1144 _additional_cash_required = ret.GetCost(); |
1131 return cost; |
1145 return cost; |
1132 } |
1146 } |
1133 proc(tile, (RailType)p2, true); |
1147 proc(tile, totype, true); |
1134 } |
1148 } |
1135 cost.AddCost(ret); |
1149 cost.AddCost(ret); |
1136 } |
1150 } |
1137 } |
1151 } |
1138 |
1152 |