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 { |