static void Postfix(LocoControllerSteam __instance, float position) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (PlayerManager.Car != null && PlayerManager.Car.trainset != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } List <TrainCar> trainsetCars = trainset.cars; for (int i = 0; i < trainsetCars.Count; i++) { TrainCar car = trainsetCars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoSteamHeavy) { LocoControllerSteam steamController = car.GetComponent <LocoControllerSteam>(); if (steamController) { if (GetCarsBehind(PlayerManager.Car).Contains(car)) { if (GetCarsInFrontOf(car).Contains(PlayerManager.Car)) { steamController.SetReverser(position); } else { steamController.SetReverser(position * -1f); } } else if (GetCarsInFrontOf(PlayerManager.Car).Contains(car)) { if (GetCarsBehind(car).Contains(PlayerManager.Car)) { steamController.SetReverser(position); } else { steamController.SetReverser(position * -1f); } } } } } }
private void TrainCar_TrainsetChanged(Trainset set) { if (isBeingDestroyed || set == null || set.firstCar == null || trainCar.logicCar == null || !trainCar) { return; } //Issue with trainset being detatched in the middle positioning not updating correctly. if (set.locoIndices.Count == 0 && set.firstCar == trainCar) { StartCoroutine(ResetAuthorityToHostWhenStationary(set)); } else { CheckAuthorityChange(); } if (!Trainset.allSets.Contains(tempFrontTrainsetWithAuthority)) { tempFrontTrainsetWithAuthority = null; } if (!Trainset.allSets.Contains(tempRearTrainsetWithAuthority)) { tempRearTrainsetWithAuthority = null; } }
public static RouteTask FromDestination(Track destination, Trainset trainset) { RouteTask newTask = new RouteTask(); newTask.DestinationTrack = destination; newTask.TrainSets.Add(trainset); return(newTask); }
public static RouteTaskChain FromDestination(Track destination, Trainset trainset) { return(new RouteTaskChain() { tasks = new List <RouteTask>() { RouteTask.FromDestination(destination, trainset) } }); }
internal GameObject[] GetPlayersInTrainSet(Trainset trainset) { List <GameObject> players = new List <GameObject>(); foreach (TrainCar car in trainset.cars) { if (car) { players.AddRange(GetPlayersInTrain(car)); } } return(players.ToArray()); }
static void Postfix(LocoControllerBase __instance, float nextTargetIndependentBrake) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (Main.remoteCar) { targetCar = Main.remoteCar; trainset = targetCar.trainset; } else if (PlayerManager.Car != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } for (int i = 0; i < trainset.cars.Count; i++) { TrainCar car = trainset.cars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoShunter) { LocoControllerShunter locoController = car.GetComponent <LocoControllerShunter>(); if (locoController) { locoController.SetIndependentBrake(nextTargetIndependentBrake); } } else if (car.carType == TrainCarType.LocoDiesel) { LocoControllerDiesel locoController = car.GetComponent <LocoControllerDiesel>(); if (locoController) { locoController.SetIndependentBrake(nextTargetIndependentBrake); } } } }
public void UpdateJobCars() { jobCars.Clear(); jobCarsUsed.Clear(); jobConsists.Clear(); // jobConsistUsed = null; currentTracks.Clear(); List <Task> tasks = GetFirstUnfinishedTasks(); currentTasks = tasks.Count; foreach (Task t in tasks) { jobCars.AddRange(t.GetTaskData().cars); } foreach (Car c in jobCars) { jobCarsUsed[c] = false; } foreach (Car car in jobCars) { if (!jobCarsUsed[car]) { TrackID trackID = car.CurrentTrack?.ID; if (!SingletonBehaviour <IdGenerator> .Instance.logicCarToTrainCar.TryGetValue(car, out TrainCar trainCar)) { continue; } Trainset trainset = trainCar.trainset; foreach (TrainCar tc in trainset.cars) { Car c = tc.logicCar; if (c != null) { if (jobCarsUsed.ContainsKey(c)) { jobCarsUsed[c] = true; } if (trackID == null) { trackID = c.CurrentTrack?.ID; } } } jobConsists.Add(trainset); currentTracks.Add(trackID); } } }
/// <summary> /// Return a transform to point to the the nth consist. /// </summary> /// <param name="index"></param> /// <returns></returns> public Transform GetPointerAt(int index) { if (jobConsists.Count < 1 || jobNotAllowed) { return(null); } index %= jobConsists.Count; Trainset t = jobConsists[index]; if (t == PlayerManager.LastLoco?.trainset) { return(PlayerManager.LastLoco?.transform); } // Get car in middle of set. // TODO: Raise pointer to middle of car height. return(t.cars[t.cars.Count / 2].transform); }
public void SetRoute(Route route, Trainset trainset) { Trainset = trainset; if (route == null || route.Path.Count == 0) { throw new ArgumentNullException(nameof(route)); } Route = route; ElapsedTime = 0.0f; TrackState = TrackingState.BeforeStart; if (!Running) { Module.StartCoroutine(PositionUpdate()); } }
public void Init(Trainset set, MultiPlayerId id, List <TrainCar>?carOrder) { _syncs.Add(set, this); _trainset = set; if (Authoritative) { _bogiePosition = new BogiePosition[set.cars.Sum(c => c.Bogies.Length)]; } else { _offsets = new double[set.cars.Sum(c => c.Bogies.Length)]; _trackPosition = new double[_offsets.Length]; _dampVel = new double[_offsets.Length]; _vels = new float[_offsets.Length]; _tracks = new RailTrack[_offsets.Length]; _bogiePos = new Vector3[set.cars.Max(c => c.Bogies.Length)]; } if (carOrder is {})
static void Postfix(LocoControllerSteam __instance, float throttle) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (PlayerManager.Car != null && PlayerManager.Car.trainset != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } List <TrainCar> trainsetCars = trainset.cars; for (int i = 0; i < trainsetCars.Count; i++) { TrainCar car = trainsetCars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoSteamHeavy) { LocoControllerSteam steamController = car.GetComponent <LocoControllerSteam>(); if (steamController) { steamController.SetThrottle(throttle); } } } }
static void Prefix(LocoControllerDiesel __instance, ToggleDirection toggle) { TrainCar targetCar = __instance.GetComponent <TrainCar>(); Trainset trainset = targetCar.trainset; if (trainset == null) { return; } for (int i = 0; i < trainset.cars.Count; i++) { TrainCar car = trainset.cars[i]; if (targetCar.Equals(car)) { continue; } if (car.carType == TrainCarType.LocoShunter) { LocoControllerShunter locoController = car.GetComponent <LocoControllerShunter>(); if (locoController != null) { locoController.SetSandersOn(toggle == ToggleDirection.UP); } } else if (car.carType == TrainCarType.LocoDiesel) { LocoControllerDiesel locoController = car.GetComponent <LocoControllerDiesel>(); if (locoController != null) { locoController.SetSandersOn(toggle == ToggleDirection.UP); } } } }
public static float TotalMass(this Trainset trainset) => trainset.cars.Sum(c => c.totalMass + CargoTypes.GetCargoMass(c.LoadedCargo, c.LoadedCargoAmount));
public static float OverallLength(this Trainset trainset) => trainset.cars.Sum(c => c.logicCar.length);
public static float Length(this Trainset trainset) { return(trainset.cars.Sum(c => c.logicCar.length)); }
public static bool IsFree(this Track current, Trainset trainset) { return(IsFree(current, new HashSet <string>(trainset.cars.Select(c => c.logicCar.ID)))); }
static void Postfix(LocoControllerDiesel __instance, float position) { TrainCar currentCar = __instance.GetComponent <TrainCar>(); TrainCar targetCar = null; Trainset trainset = null; if (Main.remoteCar) { targetCar = Main.remoteCar; trainset = targetCar.trainset; } else if (PlayerManager.Car != null) { targetCar = PlayerManager.Car; trainset = PlayerManager.Car.trainset; } if (currentCar == null || targetCar == null || !targetCar.Equals(currentCar) || trainset == null || trainset.cars.Count < 2) { return; } List <TrainCar> trainsetCars = trainset.cars; for (int i = 0; i < trainsetCars.Count; i++) { TrainCar car = trainsetCars[i]; if (targetCar.Equals(car)) { continue; } LocoControllerBase locoController = null; if (car.carType == TrainCarType.LocoShunter) { locoController = car.GetComponent <LocoControllerShunter>(); } else if (car.carType == TrainCarType.LocoDiesel) { locoController = car.GetComponent <LocoControllerDiesel>(); } if (locoController != null) { if (GetCarsBehind(targetCar).Contains(car)) { if (GetCarsInFrontOf(car).Contains(targetCar)) { locoController.SetReverser(position); } else { locoController.SetReverser(position * -1f); } } else if (GetCarsInFrontOf(targetCar).Contains(car)) { if (GetCarsBehind(car).Contains(targetCar)) { locoController.SetReverser(position); } else { locoController.SetReverser(position * -1f); } } } } }
private IEnumerator ResetAuthorityToHostWhenStationary(Trainset set) { yield return(new WaitUntil(() => velocity.magnitude * 3.6f < 1)); SingletonBehaviour <NetworkTrainManager> .Instance.SendAuthorityChange(set, localPlayer.Id); }
public async static System.Threading.Tasks.Task DoCommand(CommandArg[] args) { if (args.Length == 0) { throw new CommandException("No command args"); } if (args[0].String == "job" || args[0].String == "loco") { List <JobBooklet> allJobBooklets = new List <JobBooklet>(JobBooklet.allExistingJobBooklets); JobBooklet jobBooklet = null; if (allJobBooklets.Count == 0) { throw new CommandException("No current job"); } if (allJobBooklets.Count > 1 || args.Length > 1) { if (args.Length < 2) { throw new CommandException("Multiple job, specify job name"); } jobBooklet = allJobBooklets.FirstOrDefault(j => j.job.ID == args[1].String); } else { jobBooklet = allJobBooklets[0]; } if (jobBooklet == null) { throw new CommandException("Unknown job"); } RouteTaskChain chain = RouteTaskChain.FromDVJob(jobBooklet.job); if (chain == null) { throw new CommandException("Not supported job type yet"); } Terminal.Log($"Using job {jobBooklet.job.ID} chain {chain}"); TrainCar trainCar; RouteTracker routeTracker = new RouteTracker(chain, true); if (args[0].String == "loco") { trainCar = PlayerManager.LastLoco; if (trainCar == null) { throw new CommandException("No last loco"); } } else { trainCar = routeTracker.CurrentTask.TrainSets.FirstOrDefault()?.firstCar; } if (routeTracker.CurrentTask == null) { throw new CommandException("No suitable task"); } Track startTrack = trainCar.trainset.firstCar.Bogies[0].track.logicTrack; await FindAndSwitch(startTrack, routeTracker.CurrentTask.DestinationTrack, ReversingStrategy.ChooseBest, trainCar.trainset); routeTracker.SetRoute(Module.ActiveRoute.Route, trainCar.trainset); Module.ActiveRoute.RouteTracker = routeTracker; } else if (args[0].String == "tracker") { TrainCar trainCar = PlayerManager.LastLoco; if (trainCar == null) { throw new CommandException("No last loco"); } if (Module.ActiveRoute.RouteTracker.CurrentTask == null) { throw new CommandException("Tracker has no task"); } Track startTrack = trainCar.trainset.firstCar.Bogies[0].track.logicTrack; await FindAndSwitch(startTrack, Module.ActiveRoute.RouteTracker.CurrentTask.DestinationTrack, ReversingStrategy.ChooseBest, trainCar.trainset); Module.ActiveRoute.RouteTracker.SetRoute(Module.ActiveRoute.Route, trainCar.trainset); } else if (args[0].String == "from" && args.Length == 4 && args[2].String == "to") { Trainset trainset = null; //default value if we don't have consist (trainset) if (args[1].String == "loco") { TrainCar trainCar = PlayerManager.LastLoco; if (trainCar == null) { throw new CommandException("No last loco"); } if (trainCar.trainset.firstCar.logicCar.BogiesOnSameTrack) { args[1].String = trainCar.trainset.firstCar.logicCar.CurrentTrack.ID.FullID; } else { args[1].String = trainCar.trainset.firstCar.logicCar.FrontBogieTrack.ID.FullID; } trainset = trainCar.trainset; Terminal.Log($"current loco track end"); } else if (args[1].String == "job.trainset") { //TODO } if (trainset == null) { throw new CommandException("Goal track must be associated with car"); } RailTrack startTrack = RailTrackRegistry.AllTracks.FirstOrDefault((RailTrack track) => track?.logicTrack.ID.FullID == args[1].String); RailTrack goalTrack = RailTrackRegistry.AllTracks.FirstOrDefault((RailTrack track) => track?.logicTrack.ID.FullID == args[3].String); RouteTaskChain chain = RouteTaskChain.FromDestination(goalTrack.logicTrack, trainset); var tracker = new RouteTracker(chain, false); if (startTrack == null || goalTrack == null) { throw new CommandException("start track or goal track not found"); } await FindAndSwitch(startTrack.logicTrack, goalTrack.logicTrack, Module.settings.ReversingStrategy, trainset); tracker.SetRoute(Module.ActiveRoute.Route, trainset); Module.ActiveRoute.RouteTracker = tracker; } else if (args[0].String == "opposite") { if (!Module.ActiveRoute.IsSet) { throw new CommandException("No route active"); } var route = await Module.ActiveRoute.Route.FindOppositeRoute(); if (route != null) { Module.ActiveRoute.Route = route; route.AdjustSwitches(); Module.ActiveRoute.RouteTracker.SetRoute(route, route.Trainset); Terminal.Log($"Route {route.Length} {route?.SecondTrack?.logicTrack.ID.FullDisplayID}"); } else { throw new CommandException("Opposite route could not be found"); } } else if (args[0].String == "clear") { if (Module.ActiveRoute.IsSet) { Module.ActiveRoute.ClearRoute(); } else { throw new CommandException("no active route"); } } else if (args[0].String == "info") { if (Module.ActiveRoute.IsSet) { Terminal.Log("Active route:"); Terminal.Log(Module.ActiveRoute.Route.ToString()); #if DEBUG Terminal.Log(Module.ActiveRoute.Route.Path.Select(t => t.logicTrack.ID.FullID).Aggregate((i, j) => i + "->" + j)); #endif } else { throw new CommandException("no active route"); } } #if DEBUG else if (args[0].String == "track") { var track = RailTrackRegistry.AllTracks.Where(t => t.logicTrack.ID.FullID.ToLower() == args[1].String.ToLower()).FirstOrDefault(); if (track == null) { throw new CommandException("track not found"); } Terminal.Log($"{track.logicTrack.ID.FullID} {track.logicTrack.length}m"); if (track.inIsConnected) { Terminal.Log("IN: " + track.GetAllInBranches().Select(b => b.track.logicTrack.ID.FullID).Aggregate((a, b) => a + "; " + b)); } if (track.outIsConnected) { Terminal.Log("OUT: " + track.GetAllOutBranches().Select(b => b.track.logicTrack.ID.FullID).Aggregate((a, b) => a + "; " + b)); } } else if (args[0].String == "trainset") { TrainCar trainCar = PlayerManager.LastLoco; if (trainCar == null) { throw new CommandException("No last loco"); } Terminal.Log($"loco trainset cars: {trainCar.trainset.cars.Count}"); Terminal.Log($"first car: {trainCar.trainset.firstCar.logicCar.ID}"); Terminal.Log($"last car: {trainCar.trainset.lastCar.logicCar.ID}"); Terminal.Log($"first car track: {trainCar.trainset.firstCar.logicCar.CurrentTrack?.ID.FullDisplayID}"); Terminal.Log($"last car track: {trainCar.trainset.lastCar.logicCar.CurrentTrack?.ID.FullDisplayID}"); Terminal.Log($"first car front boogie track: {trainCar.trainset.firstCar.logicCar.FrontBogieTrack?.ID.FullDisplayID}"); Terminal.Log($"first car rear boogie track: {trainCar.trainset.firstCar.logicCar.RearBogieTrack?.ID.FullDisplayID}"); } #endif else if (args[0].String == "auto") { TrainCar trainCar = PlayerManager.LastLoco; if (trainCar == null) { throw new CommandException("No last loco"); } if (args[1].String == "stop") { var locoAI = Module.GetLocoAI(trainCar); locoAI.Stop(); return; } RailTrack goalTrack = RailTrackRegistry.AllTracks.FirstOrDefault((RailTrack track) => track?.logicTrack.ID.FullID == args[1].String); if (goalTrack == null) { throw new CommandException("Goal track not found"); } RouteTaskChain chain = RouteTaskChain.FromDestination(goalTrack.logicTrack, trainCar.trainset); var tracker = new RouteTracker(chain, false); Track startTrack = trainCar.trainset.firstCar.Bogies[0].track.logicTrack; var route = await Route.FindRoute(startTrack, tracker.CurrentTask.DestinationTrack, ReversingStrategy.ChooseBest, trainCar.trainset); tracker.SetRoute(route, trainCar.trainset); var driver = Module.GetLocoAI(trainCar); driver.StartAI(tracker); } else { throw new CommandException($"Unknown subcommand {args[0]}"); } }
private async static System.Threading.Tasks.Task FindAndSwitch(Track begin, Track end, ReversingStrategy reversingStrategy, Trainset trainset) { if (begin is null) { throw new CommandException("Empty begin"); } if (end is null) { throw new CommandException("Empty end"); } var route = await Route.FindRoute(begin, end, reversingStrategy, trainset); if (route == null) { Module.ActiveRoute.ClearRoute(); throw new CommandException("Path cannot be found"); } else { Module.ActiveRoute.Route = route; route.AdjustSwitches(); } }
private void GainAndReleaseAuthorityOfTrainsInRangeOfCurrent() { if (!trainCar.rearCoupler || !trainCar.frontCoupler || velocity.magnitude * 3.6f <= .5f) { return; } GameObject collidedCouplerRear = trainCar.rearCoupler.GetFirstCouplerInRange(3)?.gameObject; GameObject collidedCouplerFront = trainCar.frontCoupler.GetFirstCouplerInRange(3)?.gameObject; if (collidedCouplerRear && collidedCouplerRear.GetComponent <Coupler>() && collidedCouplerRear.GetComponent <Coupler>().train != trainCar) { var coupler = collidedCouplerRear.GetComponent <Coupler>(); var otherTrain = coupler.train; var otherTrainServerState = SingletonBehaviour <NetworkTrainManager> .Instance.GetServerStateById(otherTrain.CarGUID); if (otherTrainServerState != null && serverState.AuthorityPlayerId != otherTrainServerState.AuthorityPlayerId) { if (tempRearTrainsetWithAuthority != otherTrain.trainset) { ushort gainer = otherTrainServerState.AuthorityPlayerId; if (tempRearTrainsetWithAuthority == null) { gainer = serverState.AuthorityPlayerId; } var trainSync = otherTrain.GetComponent <NetworkTrainPosSync>(); if (coupler.isFrontCoupler) { trainSync.tempFrontTrainsetWithAuthority = trainCar.trainset; } else { trainSync.tempRearTrainsetWithAuthority = trainCar.trainset; } SingletonBehaviour <NetworkTrainManager> .Instance.SendAuthorityChange(otherTrain.trainset, gainer); tempRearTrainsetWithAuthority = otherTrain.trainset; } } } if (!collidedCouplerRear && tempRearTrainsetWithAuthority != null) { var frontTrain = tempRearTrainsetWithAuthority.firstCar.GetComponent <NetworkTrainPosSync>(); var rearTrain = tempRearTrainsetWithAuthority.lastCar.GetComponent <NetworkTrainPosSync>(); tempRearTrainsetWithAuthority = null; if (frontTrain.tempFrontTrainsetWithAuthority == trainCar.trainset) { frontTrain.tempFrontTrainsetWithAuthority = null; } if (frontTrain.tempRearTrainsetWithAuthority == trainCar.trainset) { frontTrain.tempRearTrainsetWithAuthority = null; } if (rearTrain.tempFrontTrainsetWithAuthority == trainCar.trainset) { rearTrain.tempFrontTrainsetWithAuthority = null; } if (rearTrain.tempRearTrainsetWithAuthority == trainCar.trainset) { rearTrain.tempRearTrainsetWithAuthority = null; } frontTrain.CheckAuthorityChange(); rearTrain.CheckAuthorityChange(); CheckAuthorityChange(); } if (collidedCouplerFront && collidedCouplerFront.GetComponent <Coupler>() && collidedCouplerFront.GetComponent <Coupler>().train != trainCar) { var coupler = collidedCouplerFront.GetComponent <Coupler>(); var otherTrain = coupler.train; var otherTrainServerState = SingletonBehaviour <NetworkTrainManager> .Instance.GetServerStateById(otherTrain.CarGUID); if (otherTrainServerState != null && serverState.AuthorityPlayerId != otherTrainServerState.AuthorityPlayerId) { if (tempFrontTrainsetWithAuthority != otherTrain.trainset) { var trainSync = otherTrain.GetComponent <NetworkTrainPosSync>(); if (coupler.isFrontCoupler) { trainSync.tempFrontTrainsetWithAuthority = trainCar.trainset; } else { trainSync.tempRearTrainsetWithAuthority = trainCar.trainset; } SingletonBehaviour <NetworkTrainManager> .Instance.SendAuthorityChange(otherTrain.trainset, serverState.AuthorityPlayerId); tempFrontTrainsetWithAuthority = otherTrain.trainset; } } } if (!collidedCouplerFront && tempFrontTrainsetWithAuthority != null) { var frontTrain = tempFrontTrainsetWithAuthority.firstCar.GetComponent <NetworkTrainPosSync>(); var rearTrain = tempFrontTrainsetWithAuthority.lastCar.GetComponent <NetworkTrainPosSync>(); tempFrontTrainsetWithAuthority = null; if (frontTrain.tempFrontTrainsetWithAuthority == trainCar.trainset) { frontTrain.tempFrontTrainsetWithAuthority = null; } if (frontTrain.tempRearTrainsetWithAuthority == trainCar.trainset) { frontTrain.tempRearTrainsetWithAuthority = null; } if (rearTrain.tempFrontTrainsetWithAuthority == trainCar.trainset) { rearTrain.tempFrontTrainsetWithAuthority = null; } if (rearTrain.tempRearTrainsetWithAuthority == trainCar.trainset) { rearTrain.tempRearTrainsetWithAuthority = null; } frontTrain.CheckAuthorityChange(); rearTrain.CheckAuthorityChange(); CheckAuthorityChange(); } }
void IDispatch.UpdateDispatch() { // Recatalogue groups of cars for this task. groups.Clear(); foreach (Car c in cars.Keys) { cars[c] = false; } foreach (Car c in cars.Keys) { bool test = uncouple && c.BogiesOnSameTrack && c.CurrentTrack == track; } // Will go through up to cars.Count different groups. List <Group> detachedGroups = new List <Group>(); foreach (Car car in cars.Keys) { if (cars[car] || !SingletonBehaviour <IdGenerator> .Instance.logicCarToTrainCar.TryGetValue(car, out TrainCar trainCar)) { continue; } while (!cars[car]) { /* * Comb through the trainset for contiguous groups of cars that are associated with this task. */ Trainset trainset = trainCar.trainset; List <Car> currentCars = new List <Car>(); bool inGroup = false; for (int i = 0; i < trainset.cars.Count; i++) { TrainCar tc = trainset.cars[i]; Car c = tc.logicCar; if (c != null && cars.ContainsKey(c) && !cars[c]) { cars[c] = true; // If this is an uncoupling dispatch, only add if car is not on destination. if (!uncouple || c.CurrentTrack != track || !c.BogiesOnSameTrack) { currentCars.Add(c); } inGroup = true; } else if (inGroup) { if (currentCars.Count > 0) { Group group = new Group(currentCars); if (trainset == PlayerManager.LastLoco?.trainset) { int place = i - currentCars.Count; if (!trainset.cars.First().IsLoco&& trainset.cars.Last().IsLoco) { currentCars.Reverse(); place = trainset.cars.Count - i; } group.consistPos = place; groups.Add(group); } else { detachedGroups.Add(group); } } break; } } } } groups.AddRange(detachedGroups); }