src/rail_cmd.cpp
changeset 7659 5456fc83a700
parent 7654 5c08e1d4ab5e
child 7768 2060e8d65a72
equal deleted inserted replaced
7658:742319a52186 7659:5456fc83a700
   736 	}
   736 	}
   737 
   737 
   738 	return cost;
   738 	return cost;
   739 }
   739 }
   740 
   740 
       
   741 static bool CheckSignalAutoFill(TileIndex &tile, Trackdir &trackdir, int &signal_ctr, bool remove)
       
   742 {
       
   743 	tile = AddTileIndexDiffCWrap(tile, _trackdelta[trackdir]);
       
   744 	if (tile == INVALID_TILE) return false;
       
   745 
       
   746 	/* Check for track bits on the new tile */
       
   747 	uint32 ts = GetTileTrackStatus(tile, TRANSPORT_RAIL, 0);
       
   748 	TrackdirBits trackdirbits = (TrackdirBits)(ts & TRACKDIR_BIT_MASK);
       
   749 
       
   750 	if (TracksOverlap(TrackdirBitsToTrackBits(trackdirbits))) return false;
       
   751 	trackdirbits &= TrackdirReachesTrackdirs(trackdir);
       
   752 
       
   753 	/* No track bits, must stop */
       
   754 	if (trackdirbits == TRACKDIR_BIT_NONE) return false;
       
   755 
       
   756 	/* Get the first track dir */
       
   757 	trackdir = RemoveFirstTrackdir(&trackdirbits);
       
   758 
       
   759 	/* Any left? It's a junction so we stop */
       
   760 	if (trackdirbits != TRACKDIR_BIT_NONE) return false;
       
   761 
       
   762 	switch (GetTileType(tile)) {
       
   763 		case MP_RAILWAY:
       
   764 			if (IsRailDepot(tile)) return false;
       
   765 			if (!remove && HasSignalOnTrack(tile, TrackdirToTrack(trackdir))) return false;
       
   766 			signal_ctr++;
       
   767 			if (IsDiagonalTrackdir(trackdir)) {
       
   768 				signal_ctr++;
       
   769 				/* Ensure signal_ctr even so X and Y pieces get signals */
       
   770 				CLRBIT(signal_ctr, 0);
       
   771 			}
       
   772 			return true;
       
   773 
       
   774 		case MP_STREET:
       
   775 			if (!IsLevelCrossing(tile)) return false;
       
   776 			signal_ctr += 2;
       
   777 			return true;
       
   778 
       
   779 		case MP_TUNNELBRIDGE: {
       
   780 			TileIndex orig_tile = tile;
       
   781 			/* Skip to end of tunnel or bridge */
       
   782 			if (IsBridge(tile)) {
       
   783 				if (GetBridgeTransportType(tile) != TRANSPORT_RAIL) return false;
       
   784 				if (GetBridgeRampDirection(tile) != TrackdirToExitdir(trackdir)) return false;
       
   785 				tile = GetOtherBridgeEnd(tile);
       
   786 			} else {
       
   787 				if (GetTunnelTransportType(tile) != TRANSPORT_RAIL) return false;
       
   788 				if (GetTunnelDirection(tile) != TrackdirToExitdir(trackdir)) return false;
       
   789 				tile = GetOtherTunnelEnd(tile);
       
   790 			}
       
   791 			signal_ctr += 2 + DistanceMax(orig_tile, tile) * 2;
       
   792 			return true;
       
   793 		}
       
   794 
       
   795 		default: return false;
       
   796 	}
       
   797 }
       
   798 
   741 /** Build many signals by dragging; AutoSignals
   799 /** Build many signals by dragging; AutoSignals
   742  * @param tile start tile of drag
   800  * @param tile start tile of drag
   743  * @param flags operation to perform
   801  * @param flags operation to perform
   744  * @param p1  end tile of drag
   802  * @param p1  end tile of drag
   745  * @param p2 various bitstuffed elements
   803  * @param p2 various bitstuffed elements
   746  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   804  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   747  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   805  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   748  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   806  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   749  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
   807  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
       
   808  * - p2 = (bit  6)    - 0 = selected stretch, 1 = auto fill
   750  * - p2 = (bit 24-31) - user defined signals_density
   809  * - p2 = (bit 24-31) - user defined signals_density
   751  */
   810  */
   752 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   811 static CommandCost CmdSignalTrackHelper(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   753 {
   812 {
   754 	CommandCost ret, total_cost;
   813 	CommandCost ret, total_cost;
   755 	int signal_ctr;
   814 	int signal_ctr;
   756 	byte signals;
   815 	byte signals;
   757 	bool error = true;
   816 	bool error = true;
   758 	TileIndex end_tile;
   817 	TileIndex end_tile;
       
   818 	TileIndex start_tile = tile;
   759 
   819 
   760 	Track track = (Track)GB(p2, 0, 3);
   820 	Track track = (Track)GB(p2, 0, 3);
   761 	bool mode = HASBIT(p2, 3);
   821 	bool mode = HASBIT(p2, 3);
   762 	bool semaphores = HASBIT(p2, 4);
   822 	bool semaphores = HASBIT(p2, 4);
   763 	bool remove = HASBIT(p2, 5);
   823 	bool remove = HASBIT(p2, 5);
       
   824 	bool autofill = HASBIT(p2, 6);
   764 	Trackdir trackdir = TrackToTrackdir(track);
   825 	Trackdir trackdir = TrackToTrackdir(track);
   765 	byte signal_density = GB(p2, 24, 8);
   826 	byte signal_density = GB(p2, 24, 8);
   766 
   827 
   767 	if (p1 >= MapSize()) return CMD_ERROR;
   828 	if (p1 >= MapSize()) return CMD_ERROR;
   768 	end_tile = p1;
   829 	end_tile = p1;
   772 
   833 
   773 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   834 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
   774 
   835 
   775 	/* for vertical/horizontal tracks, double the given signals density
   836 	/* for vertical/horizontal tracks, double the given signals density
   776 	 * since the original amount will be too dense (shorter tracks) */
   837 	 * since the original amount will be too dense (shorter tracks) */
   777 	if (!IsDiagonalTrack(track)) signal_density *= 2;
   838 	signal_density *= 2;
   778 
   839 
   779 	if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
   840 	if (CmdFailed(ValidateAutoDrag(&trackdir, tile, end_tile))) return CMD_ERROR;
   780 
   841 
   781 	track = TrackdirToTrack(trackdir); /* trackdir might have changed, keep track in sync */
   842 	track = TrackdirToTrack(trackdir); /* trackdir might have changed, keep track in sync */
       
   843 	Trackdir start_trackdir = trackdir;
       
   844 
       
   845 	/* Autofill must start on a valid track to be able to avoid loops */
       
   846 	if (autofill && !HasTrack(tile, track)) return CMD_ERROR;
   782 
   847 
   783 	/* copy the signal-style of the first rail-piece if existing */
   848 	/* copy the signal-style of the first rail-piece if existing */
   784 	if (HasSignals(tile)) {
   849 	if (HasSignals(tile)) {
   785 		signals = GetPresentSignals(tile) & SignalOnTrack(track);
   850 		signals = GetPresentSignals(tile) & SignalOnTrack(track);
   786 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
   851 		if (signals == 0) signals = SignalOnTrack(track); /* Can this actually occur? */
   788 		/* copy signal/semaphores style (independent of CTRL) */
   853 		/* copy signal/semaphores style (independent of CTRL) */
   789 		semaphores = GetSignalVariant(tile, track) != SIG_ELECTRIC;
   854 		semaphores = GetSignalVariant(tile, track) != SIG_ELECTRIC;
   790 	} else { // no signals exist, drag a two-way signal stretch
   855 	} else { // no signals exist, drag a two-way signal stretch
   791 		signals = SignalOnTrack(track);
   856 		signals = SignalOnTrack(track);
   792 	}
   857 	}
       
   858 
       
   859 	byte signal_dir = 0;
       
   860 	if (signals & SignalAlongTrackdir(trackdir))   SETBIT(signal_dir, 0);
       
   861 	if (signals & SignalAgainstTrackdir(trackdir)) SETBIT(signal_dir, 1);
   793 
   862 
   794 	/* signal_ctr         - amount of tiles already processed
   863 	/* signal_ctr         - amount of tiles already processed
   795 	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
   864 	 * signals_density    - patch setting to put signal on every Nth tile (double space on |, -- tracks)
   796 	 **********
   865 	 **********
   797 	 * trackdir   - trackdir to build with autorail
   866 	 * trackdir   - trackdir to build with autorail
   800 	 *              and convert all others to semaphore/signal
   869 	 *              and convert all others to semaphore/signal
   801 	 * remove     - 1 remove signals, 0 build signals */
   870 	 * remove     - 1 remove signals, 0 build signals */
   802 	signal_ctr = 0;
   871 	signal_ctr = 0;
   803 	for (;;) {
   872 	for (;;) {
   804 		/* only build/remove signals with the specified density */
   873 		/* only build/remove signals with the specified density */
   805 		if (signal_ctr % signal_density == 0) {
   874 		if ((remove && autofill) || signal_ctr % signal_density == 0) {
   806 			uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
   875 			uint32 p1 = GB(TrackdirToTrack(trackdir), 0, 3);
   807 			SB(p1, 3, 1, mode);
   876 			SB(p1, 3, 1, mode);
   808 			SB(p1, 4, 1, semaphores);
   877 			SB(p1, 4, 1, semaphores);
       
   878 
       
   879 			/* Pick the correct orientation for the track direction */
       
   880 			signals = 0;
       
   881 			if (HASBIT(signal_dir, 0)) signals |= SignalAlongTrackdir(trackdir);
       
   882 			if (HASBIT(signal_dir, 1)) signals |= SignalAgainstTrackdir(trackdir);
       
   883 
   809 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
   884 			ret = DoCommand(tile, p1, signals, flags, remove ? CMD_REMOVE_SIGNALS : CMD_BUILD_SIGNALS);
   810 
   885 
   811 			/* Be user-friendly and try placing signals as much as possible */
   886 			/* Be user-friendly and try placing signals as much as possible */
   812 			if (CmdSucceeded(ret)) {
   887 			if (CmdSucceeded(ret)) {
   813 				error = false;
   888 				error = false;
   814 				total_cost.AddCost(ret);
   889 				total_cost.AddCost(ret);
   815 			}
   890 			}
   816 		}
   891 		}
   817 
   892 
   818 		if (tile == end_tile) break;
   893 		if (autofill) {
   819 
   894 			if (!CheckSignalAutoFill(tile, trackdir, signal_ctr, remove)) break;
   820 		tile += ToTileIndexDiff(_trackdelta[trackdir]);
   895 
   821 		signal_ctr++;
   896 			/* Prevent possible loops */
   822 
   897 			if (tile == start_tile && trackdir == start_trackdir) break;
   823 		/* toggle railbit for the non-diagonal tracks (|, -- tracks) */
   898 		} else {
   824 		if (!IsDiagonalTrackdir(trackdir)) ToggleBitT(trackdir, 0);
   899 			if (tile == end_tile) break;
       
   900 
       
   901 			tile += ToTileIndexDiff(_trackdelta[trackdir]);
       
   902 			signal_ctr++;
       
   903 
       
   904 			/* toggle railbit for the non-diagonal tracks (|, -- tracks) */
       
   905 			if (IsDiagonalTrackdir(trackdir)) {
       
   906 				signal_ctr++;
       
   907 			} else {
       
   908 				ToggleBitT(trackdir, 0);
       
   909 			}
       
   910 		}
   825 	}
   911 	}
   826 
   912 
   827 	return error ? CMD_ERROR : total_cost;
   913 	return error ? CMD_ERROR : total_cost;
   828 }
   914 }
   829 
   915 
   835  * @param p2 various bitstuffed elements
   921  * @param p2 various bitstuffed elements
   836  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   922  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   837  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   923  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   838  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   924  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   839  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
   925  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
       
   926  * - p2 = (bit  6)    - 0 = selected stretch, 1 = auto fill
   840  * - p2 = (bit 24-31) - user defined signals_density
   927  * - p2 = (bit 24-31) - user defined signals_density
   841  * @see CmdSignalTrackHelper
   928  * @see CmdSignalTrackHelper
   842  */
   929  */
   843 CommandCost CmdBuildSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   930 CommandCost CmdBuildSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   844 {
   931 {
   898  * @param p2 various bitstuffed elements
   985  * @param p2 various bitstuffed elements
   899  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   986  * - p2 = (bit  0- 2) - track-orientation, valid values: 0-5 (Track enum)
   900  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   987  * - p2 = (bit  3)    - 1 = override signal/semaphore, or pre/exit/combo signal (CTRL-toggle)
   901  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   988  * - p2 = (bit  4)    - 0 = signals, 1 = semaphores
   902  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
   989  * - p2 = (bit  5)    - 0 = build, 1 = remove signals
       
   990  * - p2 = (bit  6)    - 0 = selected stretch, 1 = auto fill
   903  * - p2 = (bit 24-31) - user defined signals_density
   991  * - p2 = (bit 24-31) - user defined signals_density
   904  * @see CmdSignalTrackHelper
   992  * @see CmdSignalTrackHelper
   905  */
   993  */
   906 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   994 CommandCost CmdRemoveSignalTrack(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   907 {
   995 {