Beispiel #1
0
        private void UpdatePotentialTracks()
        {
            potentialTracks.Clear();
            var num = 1f;

            while (true)
            {
                foreach (var allTrack in TrackFinder.AllTracks)
                {
                    if (RailTrack.GetPointWithinRangeWithYOffset(allTrack, transform.position, num * 200f)
                        .HasValue)
                    {
                        potentialTracks.Add(allTrack);
                    }
                }

                if (potentialTracks.Count <= 0 && num <= 4.0)
                {
                    Debug.LogWarning(
                        string.Format("No tracks in {0} radius. Expanding radius!",
                                      (float)(num * 200.0)), this);
                    num += 0.2f;
                }
                else
                {
                    break;
                }
            }

            if (potentialTracks.Count != 0)
            {
                return;
            }
            Debug.LogError("No near tracks found. Can't spawn crew vehicle");
        }
Beispiel #2
0
        private static StaticPassengerJobDefinition PopulateTransportJobAndSpawn(
            JobChainController chainController, Station startStation,
            Track startTrack, Track destTrack, List <TrainCarType> carTypes,
            StationsChainData chainData, float timeLimit, float initialPay, bool unifyConsist = false)
        {
            // Spawn the cars
            RailTrack startRT     = SingletonBehaviour <LogicController> .Instance.LogicToRailTrack[startTrack];
            var       spawnedCars = CarSpawner.SpawnCarTypesOnTrack(carTypes, startRT, true, 0, false, true);

            if (spawnedCars == null)
            {
                return(null);
            }

            chainController.trainCarsForJobChain = spawnedCars;
            var logicCars = TrainCar.ExtractLogicCars(spawnedCars);

            if (logicCars == null)
            {
                PassengerJobs.ModEntry.Logger.Error("Couldn't extract logic cars, deleting spawned cars");
                SingletonBehaviour <CarSpawner> .Instance.DeleteTrainCars(spawnedCars, true);

                return(null);
            }

            if (unifyConsist && SkinManager_Patch.Enabled)
            {
                SkinManager_Patch.UnifyConsist(spawnedCars);
            }

            return(PopulateTransportJobExistingCars(chainController, startStation, startTrack, destTrack, logicCars, chainData, timeLimit, initialPay));
        }
        /// <summary>
        /// Computes if track without revresing is long enough for given length
        /// </summary>
        /// <param name="current"></param>
        /// <param name="from"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static bool IsDirectLengthEnough(this RailTrack current, RailTrack from, double length)
        {
            if (current.logicTrack.length > length)
            {
                return(true);
            }

            bool isFromInJuction  = current.inIsConnected && current.GetAllInBranches().Any(b => b.track == from);
            bool isFromOutJuction = current.outIsConnected && current.GetAllOutBranches().Any(b => b.track == from);

            if (current.inIsConnected && !isFromInJuction)
            {
                foreach (var branch in current.GetAllInBranches())
                {
                    if (CanGoToDirectly(current, from, branch.track) && IsDirectLengthEnough(branch.track, current, length - current.logicTrack.length))
                    {
                        return(true);
                    }
                }
            }

            if (current.outIsConnected && !isFromOutJuction)
            {
                foreach (var branch in current.GetAllOutBranches())
                {
                    if (CanGoToDirectly(current, from, branch.track) && IsDirectLengthEnough(branch.track, current, length - current.logicTrack.length))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        public bool Receive(TrainCarInformationPacket packet, ClientId client)
        {
            var player = MultiPlayerManager.Instance.RemotePlayers[client];

            Logger.LogInfo($"Spawning remote car {packet.CarType} at {packet.Position} moved by {WorldMover.currentMove} for {player}");

            var prefab = CarTypes.GetCarPrefab(packet.CarType);

            var(rail, _) = RailTrack.GetClosest(packet.Position + WorldMover.currentMove);
            TrainCar train;

            using (SpawningCar)
                train = CarSpawner.SpawnCar(prefab, rail, packet.Position + WorldMover.currentMove, packet.Forward);

            if (train.GetComponent <LocoControllerShunter>())
            {
                train.gameObject.AddComponent <LocoStateShunterSync>().Init(packet.Id);
            }
            //else if (train.GetComponent<LocoControllerDiesel>()) train.gameObject.AddComponent<LocoStateDieselSync>().Init(packet.Id);
            //else if (train.GetComponent<LocoControllerSteam>()) train.gameObject.AddComponent<LocoStateHandcarSync>().Init(packet.Id);
            //else if (train.GetComponent<LocoControllerHandcar>()) train.gameObject.AddComponent<LocoStateHandcarSync>().Init(packet.Id);
            //else if (train.GetComponent<LocoControllerBase>()) train.gameObject.AddComponent<LocoStateSync>().Init(packet.Id);
            else
            {
                train.gameObject.AddComponent <TrainCarSync>().Init(packet.Id);
            }

            train.logicCar.ID = packet.Name;
            train.trainPlatesCtrl.trainCarPlates.ForEach(plate => plate.id.text = packet.Name);

            return(true);
        }
        public static (RailTrack, double, bool) GetAheadTrack(this RailTrack current, double currentCarSpan, bool direction, double aheadDistance)
        {
            aheadDistance -= direction ? current.logicTrack.length - currentCarSpan : currentCarSpan;

            while (aheadDistance >= 0.0f)
            {
                RailTrack nextTrack = current.GetNextTrack(direction);

                if (nextTrack == null)
                {
                    break;
                }

                direction = nextTrack.GetDirectionFromPrev(current);

                current = nextTrack;

                aheadDistance -= current.logicTrack.length;
            }

            double span = direction ? current.logicTrack.length + aheadDistance : -aheadDistance;

            if (span > current.logicTrack.length)
            {
                span = current.logicTrack.length;
            }

            return(current, span, direction);
        }
Beispiel #6
0
 private void ClearFlags()
 {
     destinationTrack = null;
     canSpawnAtPoint  = false;
     destHighlighter.TurnOff();
     SetState(State.EnterSpawnMode);
 }
Beispiel #7
0
        public static IEnumerable <TrackEvent> GetTrackEvents(RailTrack track, bool first, double start)
        {
            var allTrackEvents = GetTrackEvents(track);
            var filtered       = allTrackEvents.RelativeFromSpan(start, first);

            // Debug.Log($"allTrackEvents:\n{string.Join("\n",allTrackEvents)}\nfiltered:\n{string.Join("\n",filtered)}");
            return(filtered);
        }
Beispiel #8
0
        public static GradeEvent?GetGrade(RailTrack track, double startSpan, bool direction)
        {
            var events = FollowTrack(track, startSpan, direction ? float.NegativeInfinity : float.PositiveInfinity);

            return(events
                   .OfType <GradeEvent>()
                   .FirstOrDefault(ev => !ev.Direction));
        }
Beispiel #9
0
 public static IEnumerable <TrackEvent> GetTrackEvents(RailTrack track)
 {
     if (!indexedTracks.TryGetValue(track, out var data))
     {
         data = indexedTracks[track] = GenerateTrackEvents(track).ToList();
     }
     return(data);
 }
Beispiel #10
0
        public static float?GetSpeedLimit(RailTrack track, double startSpan, bool direction)
        {
            var events = FollowTrack(track, startSpan, direction ? /*float.NegativeInfinity*/ -1000 : /*float.PositiveInfinity*/ 1000);

            return(events
                   .OfType <SpeedLimitEvent>()
                   .FirstOrDefault(ev => !ev.Direction)
                   ?.limit);
        }
        public static bool GetDirectionFromPrev(this RailTrack current, RailTrack prev)
        {
            if (IsTrackOutBranch(current, prev))
            {
                return(false);
            }

            return(true);
        }
        public static bool IsTrackOutBranch(this RailTrack current, RailTrack next)
        {
            if (!current.outIsConnected)
            {
                return(false);
            }

            return(current.GetAllOutBranches().Any(b => b.track == next));
        }
Beispiel #13
0
 public static IEnumerable <TrackEvent> GetTrackEvents(RailTrack track)
 {
     if (!indexedTracks.TryGetValue(track, out var data))
     {
         float start = Time.realtimeSinceStartup;
         data = indexedTracks[track] = GenerateTrackEvents(track).ToList();
         float end = Time.realtimeSinceStartup;
         Main.DebugLog($"Indexed track {track.logicTrack.ID}."
                       + $" Found {data.Count} events ({data.OfType<SpeedLimitEvent>().Count()} speed signs) in {end-start} s.");
     }
     return(data);
 }
Beispiel #14
0
        public void OnUpdate()
        {
            if (potentialTracks.Count == 0 || (uint)(state - 1) > 1U)
            {
                return;
            }
            if (Physics.Raycast(signalOrigin.position, signalOrigin.forward, out hit, 100f,
                                trackMask))
            {
                var point = hit.point;
                foreach (var potentialTrack in potentialTracks)
                {
                    var rangeWithYoffset =
                        RailTrack.GetPointWithinRangeWithYOffset(potentialTrack, point, 3f, -1.75f);
                    if (rangeWithYoffset.HasValue)
                    {
                        destinationTrack = potentialTrack;
                        var startingFromIndex =
                            CarSpawner.FindClosestValidPointForCarStartingFromIndex(
                                potentialTrack.GetPointSet().points, rangeWithYoffset.Value.index,
                                carBounds.extents);
                        var hasValue = startingFromIndex.HasValue;
                        closestPointOnDestinationTrack = !hasValue ? rangeWithYoffset : startingFromIndex;
                        canSpawnAtPoint = hasValue;
                        var position = (Vector3)closestPointOnDestinationTrack.Value.position +
                                       WorldMover.currentMove;
                        var forward = closestPointOnDestinationTrack.Value.forward;
                        if (!spawnWithTrackDirection)
                        {
                            forward *= -1f;
                        }
                        destHighlighter.Highlight(position, forward, carBounds,
                                                  canSpawnAtPoint ? validMaterial : invalidMaterial);
                        display.SetAction(canSpawnAtPoint ? "confirm" : "cancel");
                        if (canSpawnAtPoint && state == State.PickDestination)
                        {
                            UpdateLCDRerailDirectionArrow();
                            return;
                        }

                        lcdArrow.TurnOff();
                        return;
                    }
                }
            }

            canSpawnAtPoint  = false;
            destinationTrack = null;
            destHighlighter.Highlight(signalOrigin.position + signalOrigin.forward * 20f,
                                      signalOrigin.right, carBounds, invalidMaterial);
            display.SetAction("cancel");
            lcdArrow.TurnOff();
        }
        public static RailTrack GetNextFromPrev(this RailTrack current, RailTrack prev)
        {
            if (IsTrackInBranch(current, prev))
            {
                return(GetOutTrack(current));
            }

            if (IsTrackOutBranch(current, prev))
            {
                return(GetInTrack(current));
            }

            return(null);
        }
Beispiel #16
0
        private static IEnumerable <TrackEvent> GenerateTrackEvents(RailTrack track)
        {
            var          pointSet   = track.GetPointSet();
            EquiPointSet simplified = EquiPointSet.ResampleEquidistant(
                pointSet,
                Mathf.Min(SIMPLIFIED_RESOLUTION, (float)pointSet.span / 3));

            foreach (var point in simplified.points)
            {
                foreach (var trackEvent in FindSigns(point))
                {
                    yield return(trackEvent);
                }
            }
        }
Beispiel #17
0
        private static string DumpNodes(List <RailTrack> neighbors, RailTrack parent)
        {
            return("[" + neighbors.Select(
                       t =>
            {
                string prefix = "NC";

                if (parent.outJunction != null)
                {
                    if (parent.outJunction.inBranch.track == t)
                    {
                        prefix = "OJin";
                    }
                    if (parent.outJunction.outBranches.Any(b => b.track == t))
                    {
                        prefix = "OJout";
                    }
                }
                else if (parent.outIsConnected && parent.outBranch.track == t)
                {
                    prefix = "OB";
                }

                if (parent.inJunction != null)
                {
                    if (parent.inJunction.inBranch.track == t)
                    {
                        prefix = "IJin";
                    }
                    if (parent.inJunction.outBranches.Any(b => b.track == t))
                    {
                        prefix = "IJout";
                    }
                }
                else if (parent.inIsConnected && parent.inBranch.track == t)
                {
                    prefix = "IB";
                }

                prefix += ":";
                return prefix + t.logicTrack.ID.FullID;
            })
                   .Aggregate(string.Empty, (a, b) =>
            {
                return a + "|" + b;
            })
                   + "]");
        }
Beispiel #18
0
        public PathFinder(Track start, Track goal)
        {
            Terminal.Log($"{start.ID.FullID} -> {goal.ID.FullID}");

            RailTrack startTrack = RailTrackRegistry.AllTracks.FirstOrDefault((RailTrack track) => track?.logicTrack.ID.FullID == start.ID.FullID);
            RailTrack goalTrack  = RailTrackRegistry.AllTracks.FirstOrDefault((RailTrack track) => track?.logicTrack.ID.FullID == goal.ID.FullID);

            if (startTrack == null || goalTrack == null)
            {
                Terminal.Log("start track or goal track not found");
                return;
            }

            this.start = startTrack;
            this.goal  = goalTrack;
        }
        public static bool IsSectorFreeFromJunction(this RailTrack current, double sectorLength, Junction junction)
        {
            if (current.inJunction == junction)
            {
                return(IsSectorFree(current, sectorLength, false));
            }
            else if (current.outJunction == junction)
            {
                return(IsSectorFree(current, sectorLength, true));
            }

#if DEBUG
            Terminal.Log($"IsSectorFreeFromJunction: not connected to given junction... track {current.logicTrack.ID.FullID} junction {junction?.GetInstanceID()} inJunction {current.inJunction?.GetInstanceID()} outJunction {current.outJunction?.GetInstanceID()}");
#endif
            return(true);
        }
        public static bool IsSectorFree(this RailTrack current, double sectorLength, bool fromOutConnection)
        {
            if (fromOutConnection)
            {
#if DEBUG2
                current.onTrackBogies.ToList().ForEach(b => Terminal.Log($"SpanOut: {b.traveller.Span}"));
#endif
                return(current.onTrackBogies.All(b => b.traveller.Span < (current.logicTrack.length - sectorLength)));
            }
            else
            {
#if DEBUG2
                current.onTrackBogies.ToList().ForEach(b => Terminal.Log($"SpanIn: {b.traveller.Span}"));
#endif
                return(current.onTrackBogies.All(b => b.traveller.Span > sectorLength));
            }
        }
 public static RailTrack GetInTrack(this RailTrack current)
 {
     if (current.inJunction != null)
     {
         if (current.inJunction.inBranch.track == current)
         {
             return(current.inJunction.outBranches[current.inJunction.selectedBranch].track);
         }
         else
         {
             return(current.inJunction.inBranch.track);
         }
     }
     else
     {
         return(current.inBranch.track);
     }
 }
Beispiel #22
0
        public void Initialize(RailTrack track, string name, string yardId)
        {
            if (LoadCompletedSound == null)
            {
                LoadCompletedSound = PocketWatchManager.Instance.alarmAudio;
                if (LoadCompletedSound != null)
                {
                    PassengerJobs.ModEntry.Logger.Log("Grabbed pocket watch bell sound");
                }
            }

            PlatformTrack = track;
            TrackId       = PlatformTrack.logicTrack.ID.TrackPartOnly;
            LogicMachine  = new WarehouseMachine(track.logicTrack, SUPPORTED_CARGO);
            PlatformName  = name;
            YardId        = yardId;
            enabled       = true;
        }
Beispiel #23
0
        // Return a List of Locations representing the found path
        public async Task <List <RailTrack> > FindPath(bool allowReverse, double consistLength, List <TrackTransition> bannedTransitions)
        {
            List <RailTrack> path = new List <RailTrack>();

            if (start == null || goal == null)
            {
                return(null);
            }

            HashSet <string> carsToIgnore = new HashSet <string>();

            if (PlayerManager.LastLoco != null)
            {
                PlayerManager.LastLoco.trainset.cars.ForEach(c => carsToIgnore.Add(c.logicCar.ID));
            }

            await Astar(allowReverse, carsToIgnore, consistLength, bannedTransitions);

            RailTrack current = goal;

            //path.Add(current);

            while (!current.Equals(start))
            {
                if (!cameFrom.ContainsKey(current))
                {
                    Terminal.Log($"cameFrom does not contain current {current.logicTrack.ID.FullID}");
                    return(null);
                }

                path.Add(current);
                current = cameFrom[current];
            }

            if (path.Count > 0)
            {
                path.Add(start);
            }

            path.Reverse();

            return(path);
        }
        /// <summary>
        /// If we can go through junctoin without reveresing
        /// </summary>
        /// <param name="current"></param>
        /// <param name="junction"></param>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <returns></returns>
        private static bool CanGoThroughJunctionDirectly(this RailTrack current, Junction junction, RailTrack from, RailTrack to)
        {
            bool fromIsOutBranch = junction != null && junction.outBranches.Any(b => b.track == from);

            if (fromIsOutBranch)
            {
                //Terminal.Log($"{from?.logicTrack.ID.FullID} -> {to?.logicTrack.ID.FullID} fromIsOutBranch");
                return(false);
            }

            bool currentIsOutBranch = junction != null && junction.outBranches.Any(b => b.track == current);

            if (currentIsOutBranch)
            {
                //Terminal.Log($"{from?.logicTrack.ID.FullID} -> {to?.logicTrack.ID.FullID} currentIsOutBranch {junction.inBranch.track.logicTrack.ID.FullID}");
                return(junction.inBranch.track == to);
            }

            return(true);
        }
Beispiel #25
0
            public static bool Prefix(Bogie __instance, RailTrack track, bool first)
            {
                var junction = first ? track.inJunction : track.outJunction;

                if (junction == null)
                {
                    return(false);
                }

                var isBroken    = JunctionIsBroken(junction);
                var branchIndex = junction.outBranches.FindIndex(b => b.track == track);

                // Main.DebugLog(() => $"branchIndex={branchIndex}, selectedBranch={junction.selectedBranch}");
                if (branchIndex < 0)
                {
                    // facing-point movement
                    if (isBroken && Random.value < Main.settings.damagedJunctionFlipPercent / 100f)
                    {
                        junction.Switch(Junction.SwitchMode.NO_SOUND);
                    }
                    return(false);
                }

                if (branchIndex == junction.selectedBranch)
                {
                    // trailing-point movement on correct branch
                    return(false);
                }

                // trailing-point movement on incorrect branch
                if (!isBroken && Random.value < Main.settings.runningThroughDamagePercent / 100f)
                {
                    DamageJunction(__instance.Car, junction);
                }
                if (Main.settings.forceSwitchOnRunningThrough)
                {
                    junction.Switch(Junction.SwitchMode.FORCED);
                }

                return(false);
            }
Beispiel #26
0
            public void UpdatePosition(Bogie bogie)
            {
                RailTrack trackCurrent = bogie.track;
                double    spanCurrent  = bogie.traveller.Span;

                if (track == null)
                {
                    track = trackCurrent;
                    span  = spanCurrent;
                }
                else if (trackCurrent != track)
                {
                    trackNext    = trackCurrent.GetNextFromPrev(track);
                    trackPrev    = track;
                    track        = trackCurrent;
                    span         = spanCurrent;
                    changedTrack = true;
                }
                else
                {
                    changedTrack = false;

                    moving = dvCar.GetVelocity().sqrMagnitude > 0.02f;

                    if (moving)
                    {
                        double diff = spanCurrent - span;
                        if (diff < -Mathf.Epsilon)
                        {
                            trackNext = trackCurrent.GetInTrack();
                        }
                        else if (diff > Mathf.Epsilon)
                        {
                            trackNext = trackCurrent.GetOutTrack();
                        }

                        span = spanCurrent;
                    }
                }
            }
        public static bool CanGoToDirectly(this RailTrack current, RailTrack from, RailTrack to, out Junction reversingJunction)
        {
            reversingJunction = null;

            bool isInJuction  = current.inIsConnected && current.GetAllInBranches().Any(b => b.track == to);
            bool isOutJuction = current.outIsConnected && current.GetAllOutBranches().Any(b => b.track == to);

            if (current.inIsConnected)
            {
                //Terminal.Log($"IN: {from?.logicTrack.ID.FullID} -> {current.logicTrack.ID.FullID} -> {to?.logicTrack.ID.FullID}");
                if (isInJuction && CanGoThroughJunctionDirectly(current, current.inJunction, from, to))
                {
                    return(true);
                }
            }

            if (current.outIsConnected)
            {
                //Terminal.Log($"OUT: {from?.logicTrack.ID.FullID} -> {current.logicTrack.ID.FullID} -> {to?.logicTrack.ID.FullID}");
                if (isOutJuction && CanGoThroughJunctionDirectly(current, current.outJunction, from, to))
                {
                    return(true);
                }
            }

            if (isInJuction)
            {
                reversingJunction = current.inJunction;
            }

            if (isOutJuction)
            {
                reversingJunction = current.outJunction;
            }

            return(false);
        }
Beispiel #28
0
        public static JobChainControllerWithEmptyHaulGeneration GenerateShuntingUnloadJobWithCarSpawning(
            StationController destinationStation,
            bool forceLicenseReqs,
            System.Random rng)
        {
            Debug.Log("[PersistentJobs] unload: generating with car spawning");
            YardTracksOrganizer yto = YardTracksOrganizer.Instance;
            List <CargoGroup>   availableCargoGroups = destinationStation.proceduralJobsRuleset.inputCargoGroups;
            int countTrainCars = rng.Next(
                destinationStation.proceduralJobsRuleset.minCarsPerJob,
                destinationStation.proceduralJobsRuleset.maxCarsPerJob);

            if (forceLicenseReqs)
            {
                Debug.Log("[PersistentJobs] unload: forcing license requirements");
                if (!LicenseManager.IsJobLicenseAcquired(JobLicenses.Shunting))
                {
                    Debug.LogError("[PersistentJobs] unload: Trying to generate a ShuntingUnload job with " +
                                   "forceLicenseReqs=true should never happen if player doesn't have Shunting license!");
                    return(null);
                }
                availableCargoGroups
                    = (from cg in availableCargoGroups
                       where LicenseManager.IsLicensedForJob(cg.CargoRequiredLicenses)
                       select cg).ToList();
                countTrainCars
                    = Math.Min(countTrainCars, LicenseManager.GetMaxNumberOfCarsPerJobWithAcquiredJobLicenses());
            }
            if (availableCargoGroups.Count == 0)
            {
                Debug.LogWarning("[PersistentJobs] unload: no available cargo groups");
                return(null);
            }

            CargoGroup chosenCargoGroup = Utilities.GetRandomFromEnumerable(availableCargoGroups, rng);

            // choose cargo & trainCar types
            Debug.Log("[PersistentJobs] unload: choosing cargo & trainCar types");
            List <CargoType>    availableCargoTypes  = chosenCargoGroup.cargoTypes;
            List <CargoType>    orderedCargoTypes    = new List <CargoType>();
            List <TrainCarType> orderedTrainCarTypes = new List <TrainCarType>();

            for (int i = 0; i < countTrainCars; i++)
            {
                CargoType chosenCargoType = Utilities.GetRandomFromEnumerable(availableCargoTypes, rng);
                List <CargoContainerType> availableContainers
                    = CargoTypes.GetCarContainerTypesThatSupportCargoType(chosenCargoType);
                CargoContainerType  chosenContainerType = Utilities.GetRandomFromEnumerable(availableContainers, rng);
                List <TrainCarType> availableTrainCarTypes
                    = CargoTypes.GetTrainCarTypesThatAreSpecificContainerType(chosenContainerType);
                TrainCarType chosenTrainCarType = Utilities.GetRandomFromEnumerable(availableTrainCarTypes, rng);
                orderedCargoTypes.Add(chosenCargoType);
                orderedTrainCarTypes.Add(chosenTrainCarType);
            }
            float approxTrainLength = yto.GetTotalCarTypesLength(orderedTrainCarTypes)
                                      + yto.GetSeparationLengthBetweenCars(countTrainCars);

            // choose starting track
            Debug.Log("[PersistentJobs] unload: choosing starting track");
            Track startingTrack
                = Utilities.GetTrackThatHasEnoughFreeSpace(yto, destinationStation.logicStation.yard.TransferInTracks, approxTrainLength);

            if (startingTrack == null)
            {
                Debug.LogWarning("[PersistentJobs] unload: Couldn't find startingTrack with enough free space for train!");
                return(null);
            }

            // choose random starting station
            // no need to ensure it has has free space; this is just a back story
            Debug.Log("[PersistentJobs] unload: choosing origin (inconsequential)");
            List <StationController> availableOrigins = new List <StationController>(chosenCargoGroup.stations);
            StationController        startingStation  = Utilities.GetRandomFromEnumerable(availableOrigins, rng);

            // spawn trainCars
            Debug.Log("[PersistentJobs] unload: spawning trainCars");
            RailTrack       railTrack        = SingletonBehaviour <LogicController> .Instance.LogicToRailTrack[startingTrack];
            List <TrainCar> orderedTrainCars = CarSpawner.SpawnCarTypesOnTrack(
                orderedTrainCarTypes,
                railTrack,
                true,
                0.0,
                false,
                true);

            if (orderedTrainCars == null)
            {
                Debug.LogWarning("[PersistentJobs] unload: Failed to spawn trainCars!");
                return(null);
            }

            JobChainControllerWithEmptyHaulGeneration jcc = GenerateShuntingUnloadJobWithExistingCars(
                startingStation,
                startingTrack,
                destinationStation,
                orderedTrainCars,
                orderedCargoTypes,
                rng,
                true);

            if (jcc == null)
            {
                Debug.LogWarning("[PersistentJobs] unload: Couldn't generate job chain. Deleting spawned trainCars!");
                SingletonBehaviour <CarSpawner> .Instance.DeleteTrainCars(orderedTrainCars, true);

                return(null);
            }

            return(jcc);
        }
Beispiel #29
0
        public static IEnumerable <TrackEvent> FollowTrack(RailTrack track, double startSpan, double distance)
        {
            const int MAX_ITERATIONS    = 100;
            double    distanceFromStart = 0f;

            for (int i = 0; i < MAX_ITERATIONS; i++)
            {
                yield return(new TrackChangeEvent(distanceFromStart, track.logicTrack.ID));

                bool travelDirection = distance > 0;

                var trackEvents = TrackIndexer
                                  .GetTrackEvents(track, travelDirection, startSpan)
                                  .Offset(distanceFromStart);

                foreach (var trackEvent in trackEvents)
                {
                    yield return(trackEvent);
                }

                double newSpan = startSpan + distance;

                Junction        nextJunction;
                Junction.Branch nextBranch;
                if (newSpan < 0)
                {
                    nextBranch = track.GetInBranch();
                    if (nextBranch == null)
                    {
                        yield break;
                    }
                    distance          += startSpan;
                    distanceFromStart += startSpan;
                    if (nextBranch.first)
                    {
                        distance *= -1;
                    }
                    nextJunction = track.inJunction;
                }
                else
                {
                    double trackSpan = track.GetPointSet().span;
                    if (newSpan >= trackSpan)
                    {
                        nextBranch = track.GetOutBranch();
                        if (nextBranch == null)
                        {
                            yield break;
                        }
                        distance          -= trackSpan - startSpan;
                        distanceFromStart += trackSpan - startSpan;
                        if (!nextBranch.first)
                        {
                            distance *= -1;
                        }
                        nextJunction = track.outJunction;
                    }
                    else
                    {
                        yield break;
                    }
                }

                if (nextBranch == null)
                {
                    yield break;
                }

                if (nextJunction != null && nextJunction.inBranch.track == track)
                {
                    yield return(new JunctionEvent(distanceFromStart, true, nextJunction));
                }

                track     = nextBranch.track;
                startSpan = nextBranch.first ? 0.0 : nextBranch.track.GetPointSet().span;
            }
        }
Beispiel #30
0
        public static void Register()
        {
            Register("hud.dumpTrack", _ =>
            {
                if (PlayerManager.Car == null)
                {
                    return;
                }
                var bogie = PlayerManager.Car.Bogies[0];
                var track = bogie.track;
                if (track == null)
                {
                    return;
                }
                var direction = bogie.trackDirection;
                var span      = bogie.traveller.Span;
                var segments  = SignPlacer.GetSegmentInfos(track.curve, 0.4f, 200f, false);
                var output    = $"direction = {direction}, span = {span}\n";
                output       += string.Join("\n", segments.Select(seg => $"{seg.bezierStartT} -> {seg.bezierEndT}, {seg.segmentLength}, {seg.GetSpeed()}"));
                Terminal.Log(output);
                Main.DebugLog(output);
            });

            Register("hud.raycast", _ =>
            {
                var transform = PlayerManager.PlayerTransform;
                Terminal.Log($"casting from {transform.position} @ {transform.forward}");
                var hits = Physics.RaycastAll(
                    new Ray(transform.position, transform.forward),
                    1000f,
                    1 << TrackIndexer.SIGN_COLLIDER_LAYER);
                foreach (var hit in hits)
                {
                    Terminal.Log($"hit {hit.collider} at {hit.transform.position}: dp = {Vector3.Dot(transform.forward, hit.transform.forward)}, layer = {hit.collider.gameObject.layer}");
                }
            });

            Register("hud.trackevents", _ =>
            {
                var transform = PlayerManager.PlayerTransform;
                (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position);
                if (startTrack == null)
                {
                    return;
                }
                var events = TrackIndexer.GetTrackEvents(startTrack);

                Terminal.Log($"All on track {startTrack.logicTrack.ID}");
                foreach (var trackEvent in events)
                {
                    Terminal.Log(trackEvent.ToString());
                    Main.DebugLog(trackEvent.ToString());
                }

                var pointForward   = point?.forward ?? Vector3.zero;
                var pointSpan      = point?.span ?? 0;
                var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f;
                Terminal.Log($"From {pointSpan} {trackDirection}:");
                foreach (var trackEvent in TrackIndexer.GetTrackEvents(startTrack, trackDirection, pointSpan))
                {
                    Terminal.Log(trackEvent.ToString());
                    Main.DebugLog(trackEvent.ToString());
                }
            });

            Register("hud.followTrack", _ =>
            {
                var transform = PlayerManager.PlayerTransform;
                (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position);
                if (startTrack == null)
                {
                    return;
                }
                var pointForward   = point?.forward ?? Vector3.zero;
                var pointSpan      = point?.span ?? 0;
                var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f ? 1 : -1;

                var trackEvents = TrackFollower.FollowTrack(startTrack, pointSpan, trackDirection * 1000f);
                foreach (var trackEvent in trackEvents)
                {
                    Terminal.Log(trackEvent.ToString());
                    Main.DebugLog(trackEvent.ToString());
                }
            });

            Register("hud.findCarOnJunction", _ =>
            {
                var transform = PlayerManager.PlayerTransform;
                (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position);
                if (startTrack == null)
                {
                    return;
                }
                var pointForward   = point?.forward ?? Vector3.zero;
                var pointSpan      = point?.span ?? 0;
                var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f ? 1 : -1;

                var trackEvents = TrackFollower.FollowTrack(startTrack, pointSpan, trackDirection * 1000f);
                var junction    = trackEvents.OfType <JunctionEvent>().FirstOrDefault();
                if (junction == null)
                {
                    Terminal.Log("no junction");
                    return;
                }

                Terminal.Log(Overlay.GetCarOnJunction(junction.junction)?.ID ?? "no car on junction");
            });

            Register("hud.dumpInterior", _ =>
            {
                if (PlayerManager.Car == null)
                {
                    return;
                }
                if (PlayerManager.Car.loadedInterior != null)
                {
                    Terminal.Log(DumpHierarchy(PlayerManager.Car.loadedInterior));
                }
            });

            Register("hud.getSpeedLimit", _ =>
            {
                var transform = PlayerManager.PlayerTransform;
                (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position);
                if (startTrack == null)
                {
                    return;
                }
                var pointForward   = point?.forward ?? Vector3.zero;
                var pointSpan      = point?.span ?? 0;
                var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f;
                Terminal.Log($"{TrackFollower.GetSpeedLimit(startTrack, pointSpan, trackDirection)}");
            });
        }