src/rail_cmd.cpp
branchgamebalance
changeset 9912 1ac8aac92385
parent 9911 0b8b245a2391
child 9913 e79cd19772dd
--- a/src/rail_cmd.cpp	Wed Jun 13 11:45:14 2007 +0000
+++ b/src/rail_cmd.cpp	Wed Jun 13 12:05:56 2007 +0000
@@ -206,20 +206,17 @@
 		}
 
 		/* no special foundation */
-		if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0)
+		if ((~_valid_tileh_slopes[0][tileh] & rail_bits) == 0) {
 			return 0;
+		} else if (!_patches.build_on_slopes || _is_old_ai_player) {
+			return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
+		}
 
 		if ((~_valid_tileh_slopes[1][tileh] & rail_bits) == 0 || ( // whole tile is leveled up
 					(rail_bits == TRACK_BIT_X || rail_bits == TRACK_BIT_Y) &&
 					(tileh == SLOPE_W || tileh == SLOPE_S || tileh == SLOPE_E || tileh == SLOPE_N)
 				)) { // partly up
-			if (existing != 0) {
-				return 0;
-			} else if (!_patches.build_on_slopes || _is_old_ai_player) {
-				return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
-			} else {
-				return _eco->GetPrice(CEconomy::TERRAFORM);
-			}
+			return (existing != 0) ? 0 : _eco->GetPrice(CEconomy::TERRAFORM);
 		}
 	}
 	return_cmd_error(STR_1000_LAND_SLOPED_IN_WRONG_DIRECTION);
@@ -301,6 +298,12 @@
 				RoadBits tram = GetRoadBits(tile, ROADTYPE_TRAM);
 				switch (roadtypes) {
 					default: break;
+					case ROADTYPES_TRAM:
+						/* Tram crossings must always have road. */
+						SetRoadOwner(tile, ROADTYPE_ROAD, _current_player);
+						roadtypes |= ROADTYPES_ROAD;
+						break;
+
 					case ROADTYPES_ROADTRAM: if (road == tram) break;
 						/* FALL THROUGH */
 					case ROADTYPES_ROADHWAY: // Road and highway are incompatible in this case
@@ -692,7 +695,7 @@
 		/* build new signals */
 		cost = _eco->GetPrice(CEconomy::BUILD_SIGNALS);
 	} else {
-		if (p2 != 0 && sigvar != GetSignalVariant(tile)) {
+		if (p2 != 0 && sigvar != GetSignalVariant(tile, track)) {
 			/* convert signals <-> semaphores */
 			cost = _eco->GetPrice(CEconomy::BUILD_SIGNALS) + _eco->GetPrice(CEconomy::REMOVE_SIGNALS);
 		} else {
@@ -705,22 +708,24 @@
 		if (!HasSignals(tile)) {
 			/* there are no signals at all on this tile yet */
 			SetHasSignals(tile, true);
-			_m[tile].m2 |= 0xF0;              // all signals are on
-			_m[tile].m3 &= ~0xF0;             // no signals built by default
-			SetSignalType(tile, SIGTYPE_NORMAL);
-			SetSignalVariant(tile, sigvar);
+			SetSignalStates(tile, 0xF); // all signals are on
+			SetPresentSignals(tile, 0); // no signals built by default
+			SetSignalType(tile, track, SIGTYPE_NORMAL);
+			SetSignalVariant(tile, track, sigvar);
 		}
 
 		if (p2 == 0) {
 			if (!HasSignalOnTrack(tile, track)) {
 				/* build new signals */
-				_m[tile].m3 |= SignalOnTrack(track);
+				SetPresentSignals(tile, GetPresentSignals(tile) | SignalOnTrack(track));
+				SetSignalType(tile, track, SIGTYPE_NORMAL);
+				SetSignalVariant(tile, track, sigvar);
 			} else {
 				if (pre_signal) {
 					/* cycle between normal -> pre -> exit -> combo -> ... */
-					SignalType type = GetSignalType(tile);
+					SignalType type = GetSignalType(tile, track);
 
-					SetSignalType(tile, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
+					SetSignalType(tile, track, type == SIGTYPE_COMBO ? SIGTYPE_NORMAL : (SignalType)(type + 1));
 				} else {
 					CycleSignalSide(tile, track);
 				}
@@ -728,9 +733,8 @@
 		} 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);
+			SetPresentSignals(tile, (GetPresentSignals(tile) & ~SignalOnTrack(track)) | (p2 & SignalOnTrack(track)));
+			SetSignalVariant(tile, track, sigvar);
 		}
 
 		MarkTileDirtyByTile(tile);
@@ -784,11 +788,11 @@
 
 	/* copy the signal-style of the first rail-piece if existing */
 	if (HasSignals(tile)) {
-		signals = _m[tile].m3 & SignalOnTrack(track);
+		signals = GetPresentSignals(tile) & SignalOnTrack(track);
 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
 
 		/* copy signal/semaphores style (independent of CTRL) */
-		semaphores = GetSignalVariant(tile) != SIG_ELECTRIC;
+		semaphores = GetSignalVariant(tile, track) != SIG_ELECTRIC;
 	} else { // no signals exist, drag a two-way signal stretch
 		signals = SignalOnTrack(track);
 	}
@@ -874,13 +878,13 @@
 
 	/* Do it? */
 	if (flags & DC_EXEC) {
-		_m[tile].m3 &= ~SignalOnTrack(track);
+		SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
 
 		/* removed last signal from tile? */
-		if (GB(_m[tile].m3, 4, 4) == 0) {
-			SB(_m[tile].m2, 4, 4, 0);
+		if (GetPresentSignals(tile) == 0) {
+			SetSignalStates(tile, 0);
 			SetHasSignals(tile, false);
-			SetSignalVariant(tile, SIG_ELECTRIC); // remove any possible semaphores
+			SetSignalVariant(tile, INVALID_TRACK, SIG_ELECTRIC); // remove any possible semaphores
 		}
 
 		SetSignalsOnBothDir(tile, track);
@@ -1091,7 +1095,7 @@
 
 #include "table/track_land.h"
 
-static void DrawSingleSignal(TileIndex tile, byte condition, uint image, uint pos)
+static void DrawSingleSignal(TileIndex tile, Track track, byte condition, uint image, uint pos)
 {
 	bool side = (_opt.road_side != 0) && _patches.signal_side;
 	static const Point SignalPositions[2][12] = {
@@ -1128,10 +1132,10 @@
 	/* _signal_base is set by our NewGRF Action 5 loader. If it is 0 then we
 	 * just draw the standard signals, else we get the offset from _signal_base
 	 * and draw that sprite. All the signal sprites are loaded sequentially. */
-	if (_signal_base == 0 || (GetSignalType(tile) == 0 && GetSignalVariant(tile) == SIG_ELECTRIC)) {
-		sprite = SignalBase[side][GetSignalVariant(tile)][GetSignalType(tile)] + image + condition;
+	if (_signal_base == 0 || (GetSignalType(tile, track) == SIGTYPE_NORMAL && GetSignalVariant(tile, track) == SIG_ELECTRIC)) {
+		sprite = SignalBase[side][GetSignalVariant(tile, track)][GetSignalType(tile, track)] + image + condition;
 	} else {
-		sprite = _signal_base + (GetSignalType(tile) - 1) * 16 + GetSignalVariant(tile) * 64 + image + condition;
+		sprite = _signal_base + (GetSignalType(tile, track) - 1) * 16 + GetSignalVariant(tile, track) * 64 + image + condition;
 	}
 
 	AddSortableSpriteToDraw(sprite, PAL_NONE, x, y, 1, 1, 10, GetSlopeZ(x,y));
@@ -1301,33 +1305,33 @@
 
 static void DrawSignals(TileIndex tile, TrackBits rails)
 {
-#define MAYBE_DRAW_SIGNAL(x,y,z) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, GetSingleSignalState(tile, x), y - 0x4FB, z)
+#define MAYBE_DRAW_SIGNAL(x,y,z,t) if (IsSignalPresent(tile, x)) DrawSingleSignal(tile, t, GetSingleSignalState(tile, x), y - 0x4FB, z)
 
 	if (!(rails & TRACK_BIT_Y)) {
 		if (!(rails & TRACK_BIT_X)) {
 			if (rails & TRACK_BIT_LEFT) {
-				MAYBE_DRAW_SIGNAL(2, 0x509, 0);
-				MAYBE_DRAW_SIGNAL(3, 0x507, 1);
+				MAYBE_DRAW_SIGNAL(2, 0x509, 0, TRACK_LEFT);
+				MAYBE_DRAW_SIGNAL(3, 0x507, 1, TRACK_LEFT);
 			}
 			if (rails & TRACK_BIT_RIGHT) {
-				MAYBE_DRAW_SIGNAL(0, 0x509, 2);
-				MAYBE_DRAW_SIGNAL(1, 0x507, 3);
+				MAYBE_DRAW_SIGNAL(0, 0x509, 2, TRACK_RIGHT);
+				MAYBE_DRAW_SIGNAL(1, 0x507, 3, TRACK_RIGHT);
 			}
 			if (rails & TRACK_BIT_UPPER) {
-				MAYBE_DRAW_SIGNAL(3, 0x505, 4);
-				MAYBE_DRAW_SIGNAL(2, 0x503, 5);
+				MAYBE_DRAW_SIGNAL(3, 0x505, 4, TRACK_UPPER);
+				MAYBE_DRAW_SIGNAL(2, 0x503, 5, TRACK_UPPER);
 			}
 			if (rails & TRACK_BIT_LOWER) {
-				MAYBE_DRAW_SIGNAL(1, 0x505, 6);
-				MAYBE_DRAW_SIGNAL(0, 0x503, 7);
+				MAYBE_DRAW_SIGNAL(1, 0x505, 6, TRACK_LOWER);
+				MAYBE_DRAW_SIGNAL(0, 0x503, 7, TRACK_LOWER);
 			}
 		} else {
-			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8);
-			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9);
+			MAYBE_DRAW_SIGNAL(3, 0x4FB, 8, TRACK_X);
+			MAYBE_DRAW_SIGNAL(2, 0x4FD, 9, TRACK_X);
 		}
 	} else {
-		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10);
-		MAYBE_DRAW_SIGNAL(2, 0x501, 11);
+		MAYBE_DRAW_SIGNAL(3, 0x4FF, 10, TRACK_Y);
+		MAYBE_DRAW_SIGNAL(2, 0x501, 11, TRACK_Y);
 	}
 }
 
@@ -1511,11 +1515,12 @@
 static bool SetSignalsEnumProc(TileIndex tile, void* data, Trackdir trackdir, uint length, byte* state)
 {
 	SetSignalsData* ssd = (SetSignalsData*)data;
+	Track track = TrackdirToTrack(trackdir);
 
 	if (!IsTileType(tile, MP_RAILWAY)) return false;
 
 	/* the tile has signals? */
-	if (HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) {
+	if (HasSignalOnTrack(tile, track)) {
 		if (HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
 			/* yes, add the signal to the list of signals */
 			if (ssd->cur != NUM_SSD_ENTRY) {
@@ -1525,10 +1530,10 @@
 			}
 
 			/* remember if this block has a presignal. */
-			ssd->has_presignal |= IsPresignalEntry(tile);
+			ssd->has_presignal |= IsPresignalEntry(tile, track);
 		}
 
-		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile)) {
+		if (HasSignalOnTrackdir(tile, trackdir) && IsPresignalExit(tile, track)) {
 			/* this is an exit signal that points out from the segment */
 			ssd->presignal_exits++;
 			if (GetSignalStateByTrackdir(tile, trackdir) != SIGNAL_STATE_RED)
@@ -1666,14 +1671,15 @@
 	for (i = 0; i != ssd->cur; i++) {
 		TileIndex tile = ssd->tile[i];
 		byte bit = SignalAgainstTrackdir(ssd->bit[i]);
-		uint16 m2 = _m[tile].m2;
+		uint signals = GetSignalStates(tile);
+		Track track = TrackdirToTrack(ssd->bit[i]);
 
 		/* presignals don't turn green if there is at least one presignal exit and none are free */
-		if (IsPresignalEntry(tile)) {
+		if (IsPresignalEntry(tile, track)) {
 			int ex = ssd->presignal_exits, exfree = ssd->presignal_exits_free;
 
 			/* subtract for dual combo signals so they don't count themselves */
-			if (IsPresignalExit(tile) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
+			if (IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, ssd->bit[i])) {
 				ex--;
 				if (GetSignalStateByTrackdir(tile, ssd->bit[i]) != SIGNAL_STATE_RED) exfree--;
 			}
@@ -1686,14 +1692,14 @@
 		if (ssd->stop) {
 make_red:
 			/* turn red */
-			if ((bit & m2) == 0) continue;
+			if ((bit & signals) == 0) continue;
 		} else {
 			/* turn green */
-			if ((bit & m2) != 0) continue;
+			if ((bit & signals) != 0) continue;
 		}
 
 		/* Update signals on the other side of this exit-combo signal; it changed. */
-		if (IsPresignalExit(tile)) {
+		if (IsPresignalExit(tile, track)) {
 			if (ssd->cur_stack != NUM_SSD_STACK) {
 				ssd->next_tile[ssd->cur_stack] = tile;
 				ssd->next_dir[ssd->cur_stack] = _dir_from_track[ssd->bit[i]];
@@ -1704,7 +1710,7 @@
 		}
 
 		/* it changed, so toggle it */
-		_m[tile].m2 = m2 ^ bit;
+		SetSignalStates(tile, signals ^ bit);
 		MarkTileDirtyByTile(tile);
 	}
 }
@@ -1722,7 +1728,7 @@
 		ssd.cur = ssd.presignal_exits = ssd.presignal_exits_free = 0;
 		ssd.has_presignal = false;
 
-		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
+		FollowTrack(tile, 0xC000 | TRANSPORT_RAIL, 0, direction, SetSignalsEnumProc, SetSignalsAfterProc, &ssd);
 		ChangeSignalStates(&ssd);
 
 		/* remember the result only for the first iteration. */
@@ -1914,7 +1920,7 @@
 }
 
 
-static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode)
+static uint32 GetTileTrackStatus_Track(TileIndex tile, TransportType mode, uint sub_mode)
 {
 	if (mode != TRANSPORT_RAIL) return 0;
 
@@ -1928,11 +1934,8 @@
 
 		case RAIL_TILE_SIGNALS: {
 			uint32 ret = GetTrackBits(tile) * 0x101;
-			byte a;
-			uint16 b;
-
-			a = _m[tile].m3;
-			b = _m[tile].m2;
+			byte a = GetPresentSignals(tile);
+			uint b = GetSignalStates(tile);
 
 			b &= a;
 
@@ -1940,13 +1943,13 @@
 			 * direction), we pretend them to be green. (So if
 			 * signals are only one way, the other way will
 			 * implicitely become `red' */
-			if ((a & 0xC0) == 0) b |= 0xC0;
-			if ((a & 0x30) == 0) b |= 0x30;
+			if ((a & 0xC) == 0) b |= 0xC;
+			if ((a & 0x3) == 0) b |= 0x3;
 
-			if ((b & 0x80) == 0) ret |= 0x10070000;
-			if ((b & 0x40) == 0) ret |= 0x07100000;
-			if ((b & 0x20) == 0) ret |= 0x20080000;
-			if ((b & 0x10) == 0) ret |= 0x08200000;
+			if ((b & 0x8) == 0) ret |= 0x10070000;
+			if ((b & 0x4) == 0) ret |= 0x07100000;
+			if ((b & 0x2) == 0) ret |= 0x20080000;
+			if ((b & 0x1) == 0) ret |= 0x08200000;
 
 			return ret;
 		}
@@ -1974,14 +1977,34 @@
 			break;
 
 		case RAIL_TILE_SIGNALS: {
-			const StringID signal_type[] = {
-				STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS,
-				STR_RAILROAD_TRACK_WITH_PRESIGNALS,
-				STR_RAILROAD_TRACK_WITH_EXITSIGNALS,
-				STR_RAILROAD_TRACK_WITH_COMBOSIGNALS
+			const StringID signal_type[4][4] = {
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_SIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRESIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXITSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS
+				},
+				{
+					STR_RAILROAD_TRACK_WITH_NORMAL_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_PRE_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_EXIT_COMBOSIGNALS,
+					STR_RAILROAD_TRACK_WITH_COMBOSIGNALS
+				}
 			};
 
-			td->str = signal_type[GetSignalType(tile)];
+			td->str = signal_type[GetSignalType(tile, TRACK_UPPER)][GetSignalType(tile, TRACK_LOWER)];
 			break;
 		}