mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r59) -Feature: Added Autosignals, just like Autorail. Can copy signal style, convert signal<->semaphore, etc. Big thanks to betatesters Dribbel and Testman57 (Darkvater)
This commit is contained in:
parent
69b09ef302
commit
3fe3a023e5
|
@ -160,6 +160,8 @@ DEF_COMMAND(CmdBuildLock);
|
|||
|
||||
DEF_COMMAND(CmdStartScenario);
|
||||
|
||||
DEF_COMMAND(CmdBuildManySignals);
|
||||
|
||||
/* The master command table */
|
||||
static CommandProc * const _command_proc_table[] = {
|
||||
CmdBuildRailroadTrack, /* 0 */
|
||||
|
@ -294,8 +296,8 @@ static CommandProc * const _command_proc_table[] = {
|
|||
CmdRefitRailVehicle, /* 106 */
|
||||
CmdRestoreOrderIndex, /* 107 */
|
||||
CmdBuildLock, /* 108 */
|
||||
CmdStartScenario /* 109 */
|
||||
|
||||
CmdStartScenario, /* 109 */
|
||||
CmdBuildManySignals, /* 110 */
|
||||
//CmdDestroyIndustry, /* 109 */
|
||||
};
|
||||
|
||||
|
|
|
@ -142,6 +142,7 @@ enum {
|
|||
CMD_BUILD_LOCK = 108,
|
||||
|
||||
CMD_START_SCENARIO = 109,
|
||||
CMD_BUILD_MANY_SIGNALS = 110,
|
||||
|
||||
//CMD_DESTROY_INDUSTRY = 109,
|
||||
};
|
||||
|
|
|
@ -999,6 +999,7 @@ STR_CONFIG_PATCHES_SERVINT_SHIPS_DISABLED :{LTBLUE}Default service interval fo
|
|||
STR_CONFIG_PATCHES_COLORED_NEWS_DATE :{LTBLUE}Coloured news appears in: {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_STARTING_DATE :{LTBLUE}Starting date: {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_SMOOTH_ECONOMY :{LTBLUE}Enable smooth economy (more, smaller changes)
|
||||
STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY :{LTBLUE}When dragging place signals every: {ORANGE}{STRING} tile(s)
|
||||
|
||||
STR_CONFIG_PATCHES_GUI :{BLACK}Interface
|
||||
STR_CONFIG_PATCHES_CONSTRUCTION :{BLACK}Construction
|
||||
|
|
170
rail_cmd.c
170
rail_cmd.c
|
@ -521,8 +521,8 @@ static const struct {
|
|||
|
||||
|
||||
/* Build either NE or NW sequence of tracks.
|
||||
* p1 0:15 - start pt X
|
||||
* p1 16:31 - start pt y
|
||||
* p1 0:15 - end pt X
|
||||
* p1 16:31 - end pt y
|
||||
*
|
||||
* p2 0:3 - rail type
|
||||
* p2 4:7 - rail direction
|
||||
|
@ -538,7 +538,7 @@ int32 CmdBuildRailroadTrack(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
if (flags & DC_EXEC)
|
||||
SndPlayTileFx(0x1E, TILE_FROM_XY(x,y));
|
||||
|
||||
/* unpack start point */
|
||||
/* unpack end point */
|
||||
sx = (p1 & 0xFFFF) & ~0xF;
|
||||
sy = (p1 >> 16) & ~0xF;
|
||||
|
||||
|
@ -837,7 +837,11 @@ int32 CmdRenameCheckpoint(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
}
|
||||
|
||||
|
||||
/* build signals, p1 = track */
|
||||
/* build signals, alternate between double/single, signal/semaphore, pre/exit/combo -signals
|
||||
p1 = (lower 3 bytes) - track-orientation
|
||||
p1 = (byte 4) - semaphores/signals
|
||||
p2 = used for CmdBuildManySignals() to copy style first signal
|
||||
*/
|
||||
int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
uint tile;
|
||||
|
@ -845,8 +849,7 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
int32 cost;
|
||||
int track = p1 & 0x7;
|
||||
|
||||
assert(track >= 0 && track < 6);
|
||||
assert(p2 == 0);
|
||||
assert(track >= 0 && track < 6); // only 6 possible track-combinations
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
|
@ -855,12 +858,12 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
if (!EnsureNoVehicle(tile))
|
||||
return CMD_ERROR;
|
||||
|
||||
_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
|
||||
|
||||
// must be railway, and not a depot, and it must have a track in the suggested position.
|
||||
if (!IS_TILETYPE(tile, MP_RAILWAY) || (m5=_map5[tile], m5&0x80) || !HASBIT(m5, track))
|
||||
return CMD_ERROR;
|
||||
|
||||
_error_message = STR_1005_NO_SUITABLE_RAILROAD_TRACK;
|
||||
|
||||
// check rail combination
|
||||
{
|
||||
byte m = m5 & RAIL_BIT_MASK;
|
||||
|
@ -873,40 +876,54 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
if (!CheckTileOwnership(tile))
|
||||
return CMD_ERROR;
|
||||
|
||||
// If it had signals previously it's no cost to build.
|
||||
// If it had signals previously it is free to change orientation/pre-exit-combo signals
|
||||
cost = 0;
|
||||
if (!(m5 & RAIL_TYPE_SIGNALS)) {
|
||||
cost = _price.build_signals;
|
||||
// if converting signals<->semaphores, charge the player for it
|
||||
} else if (p2 && ((HASBIT(p1, 3) && !HASBIT(_map3_hi[tile], 2)) || (!HASBIT(p1, 3) && HASBIT(_map3_hi[tile], 2)) ) ) {
|
||||
cost += _price.build_signals + _price.remove_signals;
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
|
||||
|
||||
if (!(m5 & RAIL_TYPE_SIGNALS)) {
|
||||
if (!(m5 & RAIL_TYPE_SIGNALS)) { // if there are no signals yet present on the track
|
||||
_map5[tile] |= RAIL_TYPE_SIGNALS; // change into signals
|
||||
_map2[tile] |= 0xF0; // all signals are on
|
||||
_map3_lo[tile] &= ~0xF0; // no signals built by default
|
||||
_map3_hi[tile] = (p1 & 8) ? 4 : 0;// initial presignal state, semaphores depend on ctrl key
|
||||
goto ignore_presig;
|
||||
if (!p2)
|
||||
goto ignore_presig;
|
||||
}
|
||||
|
||||
if (!(p1 & 8)) {
|
||||
byte a,b,c,d;
|
||||
ignore_presig:
|
||||
a = _signals_table[track]; // signal for this track in one direction
|
||||
b = _signals_table[track + 8]; // signal for this track in the other direction
|
||||
c = a | b;
|
||||
d = _map3_lo[tile] & c; // mask of built signals. it only affects &0xF0
|
||||
if (!p2) { // not called from CmdBuildManySignals
|
||||
if (!HASBIT(p1, 3)) { // not CTRL pressed
|
||||
byte a,b,c,d;
|
||||
ignore_presig:
|
||||
a = _signals_table[track]; // signal for this track in one direction
|
||||
b = _signals_table[track + 8]; // signal for this track in the other direction
|
||||
c = a | b;
|
||||
d = _map3_lo[tile] & c; // mask of built signals. it only affects &0xF0
|
||||
|
||||
// Alternate between a|b, b, a
|
||||
if ( d != 0 && d != a) {
|
||||
c = (d==c)?b:a;
|
||||
}
|
||||
// Alternate between a|b, b, a
|
||||
if ( d != 0 && d != a) {
|
||||
c = (d==c)?b:a;
|
||||
}
|
||||
|
||||
_map3_lo[tile] = (_map3_lo[tile]&~(a|b)) | c;
|
||||
_map3_lo[tile] = (_map3_lo[tile]&~(a|b)) | c;
|
||||
} else // CTRL pressed
|
||||
_map3_hi[tile] = (_map3_hi[tile] & ~3) | ((_map3_hi[tile] + 1) & 3);
|
||||
} else {
|
||||
// toggle between the signal types. Using low 2 bits of map3_hi.
|
||||
_map3_hi[tile] = (_map3_hi[tile] & ~3) | ((_map3_hi[tile] + 1) & 3);
|
||||
/* If CmdBuildManySignals is called with copying signals, just copy the style of the first signal
|
||||
* given as parameter by CmdBuildManySignals */
|
||||
switch (track) {
|
||||
case 2: case 4: _map3_lo[tile] = (p2&0xC0) | _map3_lo[tile]&~0xC0; break;
|
||||
case 3: case 5: _map3_lo[tile] = (p2&0x30) | _map3_lo[tile]&~0x30; break;
|
||||
default : _map3_lo[tile] = (p2&0xF0) | _map3_lo[tile]&0xF;
|
||||
}
|
||||
// convert between signal<->semaphores when dragging
|
||||
HASBIT(p1, 3) ? SETBIT(_map3_hi[tile], 2) : CLRBIT(_map3_hi[tile], 2);
|
||||
}
|
||||
|
||||
MarkTileDirtyByTile(tile);
|
||||
|
@ -916,6 +933,108 @@ ignore_presig:
|
|||
return cost;
|
||||
}
|
||||
|
||||
/* Build many signals by dragging: AutoSignals
|
||||
x,y= start tile
|
||||
p1 = end tile
|
||||
p2 = (byte 0) - 0 = build, 1 = remove signals
|
||||
p2 = (byte 3) - 0 = signals, 1 = semaphores
|
||||
p2 = (byte 7-4) - track-orientation
|
||||
p2 = (byte 8-) - track style
|
||||
*/
|
||||
int32 CmdBuildManySignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
int ex, ey, railbit;
|
||||
bool error = true;
|
||||
TileIndex tile = TILE_FROM_XY(x, y);
|
||||
int32 ret, total_cost, signal_ctr;
|
||||
byte m5, semaphores = (HASBIT(p2, 3)) ? 8 : 0;
|
||||
int mode = (p2 >> 4)&0xF;
|
||||
// for vertical/horizontal tracks, double the given signals density
|
||||
// since the original amount will be too dense (shorter tracks)
|
||||
byte signal_density = (mode == 1 || mode == 2) ? _patches.drag_signals_density : _patches.drag_signals_density * 2;
|
||||
byte signals = p2 >> 8;
|
||||
mode = p2 & 0x1; // build/remove signals
|
||||
|
||||
/* unpack end tile */
|
||||
ex = GET_TILE_X(p1)*16;
|
||||
ey = GET_TILE_Y(p1)*16;
|
||||
|
||||
railbit = _railbit.initial[((p2 >> 4)&0xF) + (x > ex ? 4 : 0) + (y > ey ? 8 : 0)];
|
||||
|
||||
// copy the signal-style of the first rail-piece if existing
|
||||
m5 = _map5[tile];
|
||||
if (!(m5 & RAIL_TYPE_SPECIAL) && (m5 & RAIL_BIT_MASK) && (m5 & RAIL_TYPE_SIGNALS)) {
|
||||
if (m5 & 0x3) // X,Y direction tracks
|
||||
signals = _map3_lo[tile]&0xC0;
|
||||
else {
|
||||
/* W-E or N-S direction, only copy the side which was chosen, leave
|
||||
* the other side alone */
|
||||
switch (signals) {
|
||||
case 0x20: case 8: /* east corner (N-S), south corner (W-E) */
|
||||
if (_map3_lo[tile]&0x30)
|
||||
signals = _map3_lo[tile]&0x30;
|
||||
else
|
||||
signals = 0x30 | _map3_lo[tile]&0xC0;
|
||||
break;
|
||||
case 0x10: case 4: /* west corner (N-S), north corner (W-E) */
|
||||
if (_map3_lo[tile]&0xC0)
|
||||
signals = _map3_lo[tile]&0xC0;
|
||||
else
|
||||
signals = 0xC0 | _map3_lo[tile]&0x30;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
semaphores = (_map3_hi[tile] & ~3) ? 8 : 0; // copy signal/semaphores style (independent of CTRL)
|
||||
} else { // no signals exist, drag a two-way signal stretch
|
||||
switch (signals) {
|
||||
case 0x20: case 8: /* east corner (N-S), south corner (W-E) */
|
||||
signals = 0x30; break;
|
||||
case 0x10: case 4: /* west corner (N-S), north corner (W-E) */
|
||||
signals = 0xC0;
|
||||
}
|
||||
}
|
||||
|
||||
/* signal_density_ctr - amount of tiles already processed
|
||||
* signals_density - patch setting to put signal on every Nth tile (double space on |, -- tracks)
|
||||
**********
|
||||
* railbit - direction of 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
|
||||
* 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(x, y, (railbit & 7) | semaphores, signals, flags, (mode == 1) ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
|
||||
|
||||
/* Abort placement for any other error then NOT_SUITEABLE_TRACK
|
||||
* This includes vehicles on track, competitor's tracks, etc. */
|
||||
if (ret == CMD_ERROR) {
|
||||
if (_error_message != STR_1005_NO_SUITABLE_RAILROAD_TRACK && mode != 1) {
|
||||
return CMD_ERROR;
|
||||
}
|
||||
} else {
|
||||
error = false;
|
||||
total_cost += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex == x && ey == y) // reached end of drag
|
||||
break;
|
||||
|
||||
x += _railbit.xinc[railbit];
|
||||
y += _railbit.yinc[railbit];
|
||||
signal_ctr++;
|
||||
|
||||
// toggle railbit for the diagonal tiles (|, -- tracks)
|
||||
if (railbit & 0x6) railbit ^= 1;
|
||||
}
|
||||
|
||||
return (error) ? CMD_ERROR : total_cost;
|
||||
}
|
||||
|
||||
/* Remove signals
|
||||
* p1 = unused
|
||||
* p2 = unused
|
||||
|
@ -952,6 +1071,7 @@ int32 CmdRemoveSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
|||
byte bits = _map5[tile];
|
||||
_map5[tile] &= ~RAIL_TYPE_SIGNALS;
|
||||
_map2[tile] &= ~0xF0;
|
||||
CLRBIT(_map3_hi[tile], 2); // remove any possible semaphores
|
||||
|
||||
/* TTDBUG: this code contains a bug, if a tile contains 2 signals
|
||||
* on separate tracks, it won't work properly for the 2nd track */
|
||||
|
|
51
rail_gui.c
51
rail_gui.c
|
@ -140,7 +140,7 @@ static void PlaceRail_Station(uint tile)
|
|||
}
|
||||
}
|
||||
|
||||
static void PlaceRail_Signals(uint tile)
|
||||
static void GenericPlaceSignals(uint tile)
|
||||
{
|
||||
uint trackstat;
|
||||
int i;
|
||||
|
@ -199,6 +199,11 @@ static void PlaceRail_ConvertRail(uint tile)
|
|||
VpStartPlaceSizing(tile, VPM_X_AND_Y | (1<<4));
|
||||
}
|
||||
|
||||
static void PlaceRail_AutoSignals(uint tile)
|
||||
{
|
||||
VpStartPlaceSizing(tile, VPM_SIGNALDIRS);
|
||||
}
|
||||
|
||||
static void BuildRailClick_AutoRail(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 3, _cur_railtype + SPR_OPENTTD_BASE + 4, 1, PlaceRail_AutoRail);
|
||||
|
@ -255,9 +260,9 @@ static void BuildRailClick_Station(Window *w)
|
|||
if (HandlePlacePushButton(w, 12, 0x514, 1, PlaceRail_Station)) ShowStationBuilder();
|
||||
}
|
||||
|
||||
static void BuildRailClick_Signals(Window *w)
|
||||
static void BuildRailClick_AutoSignals(Window *w)
|
||||
{
|
||||
HandlePlacePushButton(w, 13, ANIMCURSOR_BUILDSIGNALS, 1, PlaceRail_Signals);
|
||||
HandlePlacePushButton(w, 13, ANIMCURSOR_BUILDSIGNALS , 1, PlaceRail_AutoSignals);
|
||||
}
|
||||
|
||||
static void BuildRailClick_Bridge(Window *w)
|
||||
|
@ -508,6 +513,42 @@ static void HandleAutodirPlacement()
|
|||
}
|
||||
}
|
||||
|
||||
static void HandleAutoSignalPlacement()
|
||||
{
|
||||
TileHighlightData *thd = &_thd;
|
||||
int mode;
|
||||
uint trackstat = 0;
|
||||
|
||||
int dx = thd->selstart.x - (thd->selend.x&~0xF);
|
||||
int dy = thd->selstart.y - (thd->selend.y&~0xF);
|
||||
|
||||
if (dx == 0 && dy == 0 ) // 1x1 tile signals
|
||||
GenericPlaceSignals(TILE_FROM_XY(thd->selend.x, thd->selend.y));
|
||||
else { // signals have been dragged
|
||||
if (thd->drawstyle == HT_RECT) { // X,Y direction
|
||||
if (dx == 0)
|
||||
mode = VPM_FIX_X;
|
||||
else if (dy == 0)
|
||||
mode = VPM_FIX_Y;
|
||||
|
||||
trackstat = 0xC0;
|
||||
} else { // W-E or N-S direction
|
||||
mode = thd->drawstyle & 1 ? 0 : 3;
|
||||
|
||||
if (dx == dy || abs(dx - dy) == 16) // North<->South track |
|
||||
trackstat = (thd->drawstyle & 1) ? 0x20 : 0x10;
|
||||
else if (dx == -dy || abs(dx + dy) == 16) // East<->West track --
|
||||
trackstat = (thd->drawstyle & 1) ? 4 : 8;
|
||||
}
|
||||
|
||||
DoCommandP(TILE_FROM_XY(thd->selstart.x, thd->selstart.y), TILE_FROM_XY(thd->selend.x, thd->selend.y),
|
||||
(mode << 4) | (_remove_button_clicked + (_ctrl_pressed ? 8 : 0)) | (trackstat << 8),
|
||||
CcPlaySound1E,
|
||||
(_remove_button_clicked ? CMD_BUILD_MANY_SIGNALS | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1013_CAN_T_REMOVE_SIGNALS_FROM) :
|
||||
CMD_BUILD_MANY_SIGNALS | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1010_CAN_T_BUILD_SIGNALS_HERE) ) );
|
||||
}
|
||||
}
|
||||
|
||||
static OnButtonClick * const _build_railroad_button_proc[] = {
|
||||
BuildRailClick_AutoRail,
|
||||
BuildRailClick_N,
|
||||
|
@ -519,7 +560,7 @@ static OnButtonClick * const _build_railroad_button_proc[] = {
|
|||
BuildRailClick_Raise,
|
||||
BuildRailClick_Depot,
|
||||
BuildRailClick_Station,
|
||||
BuildRailClick_Signals,
|
||||
BuildRailClick_AutoSignals,
|
||||
BuildRailClick_Bridge,
|
||||
BuildRailClick_Tunnel,
|
||||
BuildRailClick_Remove,
|
||||
|
@ -603,6 +644,8 @@ static void BuildRailToolbWndProc(Window *w, WindowEvent *e)
|
|||
if (_ctrl_pressed) _remove_button_clicked = true;
|
||||
HandleAutodirPlacement();
|
||||
_remove_button_clicked = old;
|
||||
} else if (e->place.userdata == VPM_SIGNALDIRS) {
|
||||
HandleAutoSignalPlacement();
|
||||
} else if (e->place.userdata == VPM_X_AND_Y) {
|
||||
DoCommandP(end_tile, start_tile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
|
||||
} else if (e->place.userdata == (VPM_X_AND_Y | (1<<4))) {
|
||||
|
|
|
@ -873,6 +873,8 @@ static const SettingDesc patch_settings[] = {
|
|||
{"wait_oneway_signal", SDT_UINT8, (void*)15, (void*)offsetof(Patches, wait_oneway_signal)},
|
||||
{"wait_twoway_signal", SDT_UINT8, (void*)41, (void*)offsetof(Patches, wait_twoway_signal)},
|
||||
|
||||
{"drag_signals_density", SDT_UINT8, (void*)4, (void*)offsetof(Patches, drag_signals_density)},
|
||||
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -700,6 +700,7 @@ static const PatchEntry _patches_construction[] = {
|
|||
{PE_BOOL, 0, STR_CONFIG_PATCHES_SIGNALSIDE, &_patches.signal_side},
|
||||
{PE_BOOL, 0, STR_CONFIG_PATCHES_BUILD_IN_PAUSE, &_patches.build_in_pause},
|
||||
{PE_BOOL, 0, STR_CONFIG_PATCHES_SMALL_AIRPORTS, &_patches.always_small_airport},
|
||||
{PE_UINT8,0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY, &_patches.drag_signals_density, 1, 20, 1},
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -152,6 +152,7 @@ typedef struct Patches {
|
|||
byte wait_oneway_signal; //waitingtime in days before a oneway signal
|
||||
byte wait_twoway_signal; //waitingtime in days before a twoway signal
|
||||
|
||||
byte drag_signals_density; // many signals density
|
||||
} Patches;
|
||||
|
||||
VARDEF Patches _patches;
|
||||
|
|
|
@ -1910,7 +1910,7 @@ void VpSelectTilesWithMethod(int x, int y, int method)
|
|||
}
|
||||
|
||||
// allow drag in any rail direction
|
||||
if (method == VPM_RAILDIRS) {
|
||||
if (method == VPM_RAILDIRS || method == VPM_SIGNALDIRS) {
|
||||
CalcRaildirsDrawstyle(thd, x, y);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ enum {
|
|||
VPM_RAILDIRS = 3,
|
||||
VPM_X_AND_Y = 4,
|
||||
VPM_X_AND_Y_LIMITED = 5,
|
||||
VPM_SIGNALDIRS = 6,
|
||||
};
|
||||
|
||||
void VpSelectTilesWithMethod(int x, int y, int method);
|
||||
|
|
Loading…
Reference in New Issue