|
|
|
@ -1198,6 +1198,7 @@ static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal
|
|
|
|
|
* - p2 = (bit 5) - 0 = build, 1 = remove signals
|
|
|
|
|
* - p2 = (bit 6) - 0 = selected stretch, 1 = auto fill
|
|
|
|
|
* - p2 = (bit 7- 9) - default signal type
|
|
|
|
|
* - p2 = (bit 10) - 0 = keep fixed distance, 1 = minimise gaps between signals
|
|
|
|
|
* - p2 = (bit 24-31) - user defined signals_density
|
|
|
|
|
* @param text unused
|
|
|
|
|
* @return the cost of this operation or an error
|
|
|
|
@ -1212,6 +1213,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
|
|
|
|
|
bool semaphores = HasBit(p2, 4);
|
|
|
|
|
bool remove = HasBit(p2, 5);
|
|
|
|
|
bool autofill = HasBit(p2, 6);
|
|
|
|
|
bool minimise_gaps = HasBit(p2, 10);
|
|
|
|
|
byte signal_density = GB(p2, 24, 8);
|
|
|
|
|
|
|
|
|
|
if (p1 >= MapSize() || !ValParamTrackOrientation(track)) return CMD_ERROR;
|
|
|
|
@ -1258,7 +1260,11 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
|
|
|
|
|
if (signals & SignalAgainstTrackdir(trackdir)) SetBit(signal_dir, 1);
|
|
|
|
|
|
|
|
|
|
/* signal_ctr - amount of tiles already processed
|
|
|
|
|
* last_used_ctr - amount of tiles before previously placed signal
|
|
|
|
|
* signals_density - setting to put signal on every Nth tile (double space on |, -- tracks)
|
|
|
|
|
* last_suitable_ctr - amount of tiles before last possible signal place
|
|
|
|
|
* last_suitable_tile - last tile where it is possible to place a signal
|
|
|
|
|
* last_suitable_trackdir - trackdir of the last tile
|
|
|
|
|
**********
|
|
|
|
|
* trackdir - trackdir to build with autorail
|
|
|
|
|
* semaphores - semaphores or signals
|
|
|
|
@ -1266,11 +1272,15 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
|
|
|
|
|
* and convert all others to semaphore/signal
|
|
|
|
|
* remove - 1 remove signals, 0 build signals */
|
|
|
|
|
int signal_ctr = 0;
|
|
|
|
|
int last_used_ctr = INT_MIN; // initially INT_MIN to force building/removing at the first tile
|
|
|
|
|
int last_suitable_ctr = 0;
|
|
|
|
|
TileIndex last_suitable_tile = INVALID_TILE;
|
|
|
|
|
Trackdir last_suitable_trackdir = INVALID_TRACKDIR;
|
|
|
|
|
CommandCost last_error = CMD_ERROR;
|
|
|
|
|
bool had_success = false;
|
|
|
|
|
for (;;) {
|
|
|
|
|
/* only build/remove signals with the specified density */
|
|
|
|
|
if (remove || signal_ctr % signal_density == 0) {
|
|
|
|
|
if (remove || minimise_gaps || signal_ctr % signal_density == 0) {
|
|
|
|
|
uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
|
|
|
|
|
SB(p1, 3, 1, mode);
|
|
|
|
|
SB(p1, 4, 1, semaphores);
|
|
|
|
@ -1282,17 +1292,42 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin
|
|
|
|
|
if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir);
|
|
|
|
|
if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir);
|
|
|
|
|
|
|
|
|
|
CommandCost ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
|
|
|
|
/* Test tiles in between for suitability as well if minimising gaps. */
|
|
|
|
|
bool test_only = minimise_gaps && signal_ctr < (last_used_ctr + signal_density);
|
|
|
|
|
CommandCost ret = DoCommand(tile, p1, signals, test_only ? flags & ~DC_EXEC : flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
|
|
|
|
|
|
|
|
|
/* Be user-friendly and try placing signals as much as possible */
|
|
|
|
|
if (ret.Succeeded()) {
|
|
|
|
|
had_success = true;
|
|
|
|
|
total_cost.AddCost(ret);
|
|
|
|
|
} else {
|
|
|
|
|
/* The "No railway" error is the least important one. */
|
|
|
|
|
if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK ||
|
|
|
|
|
last_error.GetErrorMessage() == INVALID_STRING_ID) {
|
|
|
|
|
last_error = ret;
|
|
|
|
|
/* Remember last track piece where we can place a signal. */
|
|
|
|
|
last_suitable_ctr = signal_ctr;
|
|
|
|
|
last_suitable_tile = tile;
|
|
|
|
|
last_suitable_trackdir = trackdir;
|
|
|
|
|
} else if (!test_only && last_suitable_tile != INVALID_TILE) {
|
|
|
|
|
/* If a signal can't be placed, place it at the last possible position. */
|
|
|
|
|
SB(p1, 0, 3, TrackdirToTrack(last_suitable_trackdir));
|
|
|
|
|
ClrBit(p1, 17);
|
|
|
|
|
|
|
|
|
|
/* Pick the correct orientation for the track direction. */
|
|
|
|
|
signals = 0;
|
|
|
|
|
if (HasBit(signal_dir, 0)) signals |= SignalAlongTrackdir(last_suitable_trackdir);
|
|
|
|
|
if (HasBit(signal_dir, 1)) signals |= SignalAgainstTrackdir(last_suitable_trackdir);
|
|
|
|
|
|
|
|
|
|
ret = DoCommand(last_suitable_tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Collect cost. */
|
|
|
|
|
if (!test_only) {
|
|
|
|
|
/* Be user-friendly and try placing signals as much as possible */
|
|
|
|
|
if (ret.Succeeded()) {
|
|
|
|
|
had_success = true;
|
|
|
|
|
total_cost.AddCost(ret);
|
|
|
|
|
last_used_ctr = last_suitable_ctr;
|
|
|
|
|
last_suitable_tile = INVALID_TILE;
|
|
|
|
|
} else {
|
|
|
|
|
/* The "No railway" error is the least important one. */
|
|
|
|
|
if (ret.GetErrorMessage() != STR_ERROR_THERE_IS_NO_RAILROAD_TRACK ||
|
|
|
|
|
last_error.GetErrorMessage() == INVALID_STRING_ID) {
|
|
|
|
|
last_error = ret;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|