* Build many signals by dragging; AutoSignals * @param flags operation to perform * @param tile start tile of drag * @param end_tile end tile of drag * @param track track-orientation * @param sigtype default signal type * @param sigvar signal variant to build * @param mode true = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle) * @param remove remove signals? * @param aut
| 1253 | * @return the cost of this operation or an error |
| 1254 | */ |
| 1255 | static CommandCost CmdSignalTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool remove, bool autofill, bool minimise_gaps, int signal_density) |
| 1256 | { |
| 1257 | CommandCost total_cost(EXPENSES_CONSTRUCTION); |
| 1258 | |
| 1259 | if (end_tile >= Map::Size() || !ValParamTrackOrientation(track)) return CMD_ERROR; |
| 1260 | if (signal_density == 0 || signal_density > 20) return CMD_ERROR; |
| 1261 | if (!remove && (sigtype > SIGTYPE_LAST || sigvar > SIG_SEMAPHORE)) return CMD_ERROR; |
| 1262 | |
| 1263 | if (!IsPlainRailTile(tile)) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); |
| 1264 | TileIndex start_tile = tile; |
| 1265 | |
| 1266 | /* Interpret signal_density as the logical length of said amount of tiles in X/Y direction. */ |
| 1267 | signal_density *= TILE_AXIAL_DISTANCE; |
| 1268 | |
| 1269 | Trackdir trackdir = TrackToTrackdir(track); |
| 1270 | CommandCost ret = ValidateAutoDrag(&trackdir, tile, end_tile); |
| 1271 | if (ret.Failed()) return ret; |
| 1272 | |
| 1273 | track = TrackdirToTrack(trackdir); // trackdir might have changed, keep track in sync |
| 1274 | Trackdir start_trackdir = trackdir; |
| 1275 | |
| 1276 | /* Must start on a valid track to be able to avoid loops */ |
| 1277 | if (!HasTrack(tile, track)) return CMD_ERROR; |
| 1278 | |
| 1279 | uint8_t signals; |
| 1280 | /* copy the signal-style of the first rail-piece if existing */ |
| 1281 | if (HasSignalOnTrack(tile, track)) { |
| 1282 | signals = GetPresentSignals(tile) & SignalOnTrack(track); |
| 1283 | assert(signals != 0); |
| 1284 | |
| 1285 | /* copy signal/semaphores style (independent of CTRL) */ |
| 1286 | sigvar = GetSignalVariant(tile, track); |
| 1287 | |
| 1288 | sigtype = GetSignalType(tile, track); |
| 1289 | /* Don't but copy entry or exit-signal type */ |
| 1290 | if (sigtype == SIGTYPE_ENTRY || sigtype == SIGTYPE_EXIT) sigtype = SIGTYPE_BLOCK; |
| 1291 | } else { // no signals exist, drag a two-way signal stretch |
| 1292 | signals = IsPbsSignal(sigtype) ? SignalAlongTrackdir(trackdir) : SignalOnTrack(track); |
| 1293 | } |
| 1294 | |
| 1295 | uint8_t signal_dir = 0; |
| 1296 | if (signals & SignalAlongTrackdir(trackdir)) SetBit(signal_dir, 0); |
| 1297 | if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1); |
| 1298 | |
| 1299 | /* signal_ctr - amount of tiles already processed |
| 1300 | * last_used_ctr - amount of tiles before previously placed signal |
| 1301 | * signals_density - setting to put signal on every Nth tile (double space on |, -- tracks) |
| 1302 | * last_suitable_ctr - amount of tiles before last possible signal place |
| 1303 | * last_suitable_tile - last tile where it is possible to place a signal |
| 1304 | * last_suitable_trackdir - trackdir of the last tile |
| 1305 | ********** |
| 1306 | * trackdir - trackdir to build with autorail |
| 1307 | * semaphores - semaphores or signals |
| 1308 | * signals - is there a signal/semaphore on the first tile, copy its style (two-way/single-way) |
| 1309 | * and convert all others to semaphore/signal |
| 1310 | * remove - 1 remove signals, 0 build signals */ |
| 1311 | int signal_ctr = 0; |
| 1312 | int last_used_ctr = -signal_density; // to force signal at first tile |
no test coverage detected