|
@@ -541,103 +541,102 @@ static int32 CmdRailTrackHelper(TileInde
|
|
|
// toggle railbit for the non-diagonal tracks
|
|
|
if (!IsDiagonalTrackdir(trackdir)) trackdir ^= 1;
|
|
|
}
|
|
|
|
|
|
return (total_cost == 0) ? CMD_ERROR : total_cost;
|
|
|
}
|
|
|
|
|
|
/** Build rail on a stretch of track.
|
|
|
* Stub for the unified rail builder/remover
|
|
|
* @see CmdRailTrackHelper
|
|
|
*/
|
|
|
int32 CmdBuildRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
return CmdRailTrackHelper(tile, flags, p1, CLRBIT(p2, 7));
|
|
|
}
|
|
|
|
|
|
/** Build rail on a stretch of track.
|
|
|
* Stub for the unified rail builder/remover
|
|
|
* @see CmdRailTrackHelper
|
|
|
*/
|
|
|
int32 CmdRemoveRailroadTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
return CmdRailTrackHelper(tile, flags, p1, SETBIT(p2, 7));
|
|
|
}
|
|
|
|
|
|
/** Build a train depot
|
|
|
* @param tile position of the train depot
|
|
|
* @param p1 rail type
|
|
|
* @param p2 entrance direction (DiagDirection)
|
|
|
*
|
|
|
* @todo When checking for the tile slope,
|
|
|
* distingush between "Flat land required" and "land sloped in wrong direction"
|
|
|
*/
|
|
|
int32 CmdBuildTrainDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
Depot *d;
|
|
|
int32 cost, ret;
|
|
|
Slope tileh;
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
|
|
|
|
|
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
|
|
/* check railtype and valid direction for depot (0 through 3), 4 in total */
|
|
|
if (!ValParamRailtype(p1) || p2 > 3) return CMD_ERROR;
|
|
|
|
|
|
tileh = GetTileSlope(tile, NULL);
|
|
|
|
|
|
/* Prohibit construction if
|
|
|
The tile is non-flat AND
|
|
|
1) The AI is "old-school"
|
|
|
2) build-on-slopes is disabled
|
|
|
3) the tile is steep i.e. spans two height levels
|
|
|
4) the exit points in the wrong direction
|
|
|
|
|
|
*/
|
|
|
* The tile is non-flat AND
|
|
|
* 1) The AI is "old-school"
|
|
|
* 2) build-on-slopes is disabled
|
|
|
* 3) the tile is steep i.e. spans two height levels
|
|
|
* 4) the exit points in the wrong direction
|
|
|
*/
|
|
|
|
|
|
if (tileh != SLOPE_FLAT && (
|
|
|
_is_old_ai_player ||
|
|
|
!_patches.build_on_slopes ||
|
|
|
IsSteepSlope(tileh) ||
|
|
|
!CanBuildDepotByTileh(p2, tileh)
|
|
|
)) {
|
|
|
return_cmd_error(STR_0007_FLAT_LAND_REQUIRED);
|
|
|
}
|
|
|
|
|
|
ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
|
|
if (CmdFailed(ret)) return CMD_ERROR;
|
|
|
cost = ret;
|
|
|
|
|
|
d = AllocateDepot();
|
|
|
if (d == NULL) return CMD_ERROR;
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
MakeRailDepot(tile, _current_player, p2, p1);
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
|
|
|
d->xy = tile;
|
|
|
d->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
|
|
|
|
|
|
UpdateSignalsOnSegment(tile, p2);
|
|
|
YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(p2)));
|
|
|
}
|
|
|
|
|
|
return cost + _price.build_train_depot;
|
|
|
}
|
|
|
|
|
|
/** Build signals, alternate between double/single, signal/semaphore,
|
|
|
* pre/exit/combo-signals, and what-else not
|
|
|
* @param tile tile where to build the signals
|
|
|
* @param p1 various bitstuffed elements
|
|
|
* - p1 = (bit 0-2) - track-orientation, valid values: 0-5 (Track enum)
|
|
|
* - p1 = (bit 3) - choose semaphores/signals or cycle normal/pre/exit/combo depending on context
|
|
|
* @param p2 used for CmdBuildManySignals() to copy direction of first signal
|
|
|
* TODO: p2 should be replaced by two bits for "along" and "against" the track.
|
|
|
*/
|
|
|
int32 CmdBuildSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
SignalVariant sigvar;
|
|
|
bool pre_signal;
|
|
|
Track track = (Track)(p1 & 0x7);
|
|
|
int32 cost;
|
|
|
|
|
|
// Same bit, used in different contexts
|
|
@@ -708,121 +707,121 @@ int32 CmdBuildSingleSignal(TileIndex til
|
|
|
}
|
|
|
} else {
|
|
|
/* If CmdBuildManySignals is called with copying signals, just copy the
|
|
|
* direction of the first signal given as parameter by CmdBuildManySignals */
|
|
|
_m[tile].m3 &= ~SignalOnTrack(track);
|
|
|
_m[tile].m3 |= p2 & SignalOnTrack(track);
|
|
|
SetSignalVariant(tile, sigvar);
|
|
|
}
|
|
|
|
|
|
MarkTileDirtyByTile(tile);
|
|
|
SetSignalsOnBothDir(tile, track);
|
|
|
YapfNotifyTrackLayoutChange(tile, track);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
/** Build many signals by dragging; AutoSignals
|
|
|
* @param tile start tile of drag
|
|
|
* @param p1 end tile of drag
|
|
|
* @param p2 various bitstuffed elements
|
|
|
* - p2 = (bit 0) - 0 = build, 1 = remove signals
|
|
|
* - p2 = (bit 3) - 0 = signals, 1 = semaphores
|
|
|
* - p2 = (bit 4- 6) - track-orientation, valid values: 0-5 (Track enum)
|
|
|
* - p2 = (bit 24-31) - user defined signals_density
|
|
|
*/
|
|
|
static int32 CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
int32 ret, total_cost, signal_ctr;
|
|
|
byte signals;
|
|
|
bool error = true;
|
|
|
TileIndex end_tile;
|
|
|
|
|
|
int mode = p2 & 0x1;
|
|
|
Track track = GB(p2, 4, 3);
|
|
|
Trackdir trackdir = TrackToTrackdir(track);
|
|
|
byte semaphores = (HASBIT(p2, 3) ? 8 : 0);
|
|
|
byte signal_density = (p2 >> 24);
|
|
|
|
|
|
if (p1 >= MapSize()) return CMD_ERROR;
|
|
|
end_tile = p1;
|
|
|
if (signal_density == 0 || signal_density > 20) return CMD_ERROR;
|
|
|
|
|
|
if (!IsTileType(tile, MP_RAILWAY)) return CMD_ERROR;
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
|
|
|
|
|
/* for vertical/horizontal tracks, double the given signals density
|
|
|
* since the original amount will be too dense (shorter tracks) */
|
|
|
* since the original amount will be too dense (shorter tracks) */
|
|
|
if (!IsDiagonalTrack(track)) signal_density *= 2;
|
|
|
|
|
|
if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
|
|
|
|
|
|
track = TrackdirToTrack(trackdir); /* trackdir might have changed, keep track in sync */
|
|
|
|
|
|
// copy the signal-style of the first rail-piece if existing
|
|
|
if (HasSignals(tile)) {
|
|
|
signals = _m[tile].m3 & SignalOnTrack(track);
|
|
|
if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
|
|
|
|
|
|
// copy signal/semaphores style (independent of CTRL)
|
|
|
semaphores = (GetSignalVariant(tile) == SIG_ELECTRIC ? 0 : 8);
|
|
|
} else { // no signals exist, drag a two-way signal stretch
|
|
|
signals = SignalOnTrack(track);
|
|
|
}
|
|
|
|
|
|
/* signal_ctr - amount of tiles already processed
|
|
|
* signals_density - patch setting to put signal on every Nth tile (double space on |, -- tracks)
|
|
|
**********
|
|
|
* trackdir - trackdir to build with autorail
|
|
|
* semaphores - semaphores or signals
|
|
|
* signals - is there a signal/semaphore on the first tile, copy its style (two-way/single-way)
|
|
|
and convert all others to semaphore/signal
|
|
|
* and convert all others to semaphore/signal
|
|
|
* mode - 1 remove signals, 0 build signals */
|
|
|
signal_ctr = total_cost = 0;
|
|
|
for (;;) {
|
|
|
// only build/remove signals with the specified density
|
|
|
if (signal_ctr % signal_density == 0) {
|
|
|
ret = DoCommand(tile, TrackdirToTrack(trackdir) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
|
|
|
|
|
/* Abort placement for any other error than NOT_SUITABLE_TRACK
|
|
|
* This includes vehicles on track, competitor's tracks, etc. */
|
|
|
if (CmdFailed(ret)) {
|
|
|
if (_error_message != STR_1005_NO_SUITABLE_RAILROAD_TRACK && mode != 1) return CMD_ERROR;
|
|
|
_error_message = INVALID_STRING_ID;
|
|
|
} else {
|
|
|
error = false;
|
|
|
total_cost += ret;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (tile == end_tile) break;
|
|
|
|
|
|
tile += ToTileIndexDiff(_trackdelta[trackdir]);
|
|
|
signal_ctr++;
|
|
|
|
|
|
// toggle railbit for the non-diagonal tracks (|, -- tracks)
|
|
|
if (!IsDiagonalTrackdir(trackdir)) trackdir ^= 1;
|
|
|
}
|
|
|
|
|
|
return error ? CMD_ERROR : total_cost;
|
|
|
}
|
|
|
|
|
|
/** Build signals on a stretch of track.
|
|
|
* Stub for the unified signal builder/remover
|
|
|
* @see CmdSignalTrackHelper
|
|
|
*/
|
|
|
int32 CmdBuildSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
return CmdSignalTrackHelper(tile, flags, p1, p2);
|
|
|
}
|
|
|
|
|
|
/** Remove signals
|
|
|
* @param tile coordinates where signal is being deleted from
|
|
|
* @param p1 track to remove signal from (Track enum)
|
|
|
*/
|
|
|
int32 CmdRemoveSingleSignal(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
Track track = (Track)(p1 & 0x7);
|
|
|
|
|
|
if (!ValParamTrackOrientation(track) ||
|