summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rail_cmd.c73
1 files changed, 51 insertions, 22 deletions
diff --git a/rail_cmd.c b/rail_cmd.c
index 9fa64e757..df2c59a46 100644
--- a/rail_cmd.c
+++ b/rail_cmd.c
@@ -873,6 +873,7 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
byte m5;
int32 cost;
int track = p1 & 0x7;
+ byte a,b,c,d;
assert(track >= 0 && track < 6); // only 6 possible track-combinations
@@ -901,13 +902,21 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (!CheckTileOwnership(tile))
return CMD_ERROR;
+ // calculate masks for..
+ 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; // .. 2-way signal for this track
+
// 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;
+ } else {
+ d = _map3_lo[tile] & c; // mask of built signals. it only affects &0xF0
+ if (d == 0) cost += _price.build_signals; // no signals built yet
// 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 (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) {
@@ -918,23 +927,17 @@ int32 CmdBuildSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
_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
+ d = 0; // no existing signals
if (!p2)
goto ignore_presig;
}
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;
- }
+ if ( d != 0 && d != a)
+ c = (d == c)?b:a;
_map3_lo[tile] = (_map3_lo[tile]&~(a|b)) | c;
} else // CTRL pressed
@@ -1064,7 +1067,7 @@ int32 CmdBuildManySignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
}
/* Remove signals
- * p1 = unused
+ * p1 bits 0..2 = track
* p2 = unused
*/
@@ -1072,6 +1075,8 @@ int32 CmdRemoveSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileInfo ti;
uint tile;
+ int track = p1 & 0x7;
+ byte a,b,c,d;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1094,16 +1099,29 @@ int32 CmdRemoveSignals(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (_current_player != OWNER_WATER && !CheckTileOwnership(tile))
return CMD_ERROR;
+ // calculate already built signals
+ 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;
+
+ /* no signals on selected track? */
+ if (d == 0)
+ return CMD_ERROR;
+
/* Do it? */
if (flags & DC_EXEC) {
- byte bits = _map5[tile];
- _map5[tile] &= ~RAIL_TYPE_SIGNALS;
- _map2[tile] &= ~0xF0;
- CLRBIT(_map3_hi[tile], 2); // remove any possible semaphores
+
+ _map3_lo[tile] &= ~c;
- /* TTDBUG: this code contains a bug, if a tile contains 2 signals
- * on separate tracks, it won't work properly for the 2nd track */
- SetSignalsOnBothDir(tile, FIND_FIRST_BIT(bits & RAIL_BIT_MASK));
+ /* removed last signal from tile? */
+ if ((_map3_lo[tile] & 0xF0) == 0) {
+ _map5[tile] &= ~RAIL_TYPE_SIGNALS;
+ _map2[tile] &= ~0xF0;
+ CLRBIT(_map3_hi[tile], 2); // remove any possible semaphores
+ }
+
+ SetSignalsOnBothDir(tile, track);
MarkTileDirtyByTile(tile);
}
@@ -1229,9 +1247,20 @@ regular_track:;
return cost;
} else if ((m5 & RAIL_TYPE_MASK)==RAIL_TYPE_SIGNALS) {
- cost = DoCommandByTile(tile, 0, 0, flags, CMD_REMOVE_SIGNALS);
- if (cost == CMD_ERROR)
- return CMD_ERROR;
+ cost = 0;
+ if (_map3_lo[tile] & (_signals_table[0] | _signals_table[0 + 8])) { // check for signals in the first track
+ ret = DoCommandByTile(tile, 0, 0, flags, CMD_REMOVE_SIGNALS);
+ if (ret == CMD_ERROR)
+ return CMD_ERROR;
+ cost += ret;
+ };
+ if (_map3_lo[tile] & (_signals_table[3] | _signals_table[3 + 8])) { // check for signals in the other track
+ ret = DoCommandByTile(tile, 3, 0, flags, CMD_REMOVE_SIGNALS);
+ if (ret == CMD_ERROR)
+ return CMD_ERROR;
+ cost += ret;
+ };
+
m5 &= RAIL_BIT_MASK;
if (flags & DC_EXEC)
goto regular_track;