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; }
private static JobChainControllerWithEmptyHaulGeneration GenerateShuntingUnloadChainController( StationController startingStation, Track startingTrack, WarehouseMachine unloadMachine, StationController destinationStation, List <CarsPerTrack> carsPerDestinationTrack, List <TrainCar> orderedTrainCars, List <CargoType> orderedCargoTypes, List <float> orderedCargoAmounts, bool forceCorrectCargoStateOnCars, float bonusTimeLimit, float initialWage, JobLicenses requiredLicenses) { Debug.Log(string.Format( "[PersistentJobs] unload: attempting to generate ChainJob[{0}]: {1} - {2}", JobType.ShuntingLoad, startingStation.logicStation.ID, destinationStation.logicStation.ID )); GameObject gameObject = new GameObject(string.Format( "ChainJob[{0}]: {1} - {2}", JobType.ShuntingUnload, startingStation.logicStation.ID, destinationStation.logicStation.ID )); gameObject.transform.SetParent(destinationStation.transform); JobChainControllerWithEmptyHaulGeneration jobChainController = new JobChainControllerWithEmptyHaulGeneration(gameObject); StationsChainData chainData = new StationsChainData( startingStation.stationInfo.YardID, destinationStation.stationInfo.YardID); jobChainController.trainCarsForJobChain = orderedTrainCars; Dictionary <CargoType, List <(TrainCar, float)> > cargoTypeToTrainCarAndAmount = new Dictionary <CargoType, List <(TrainCar, float)> >(); for (int i = 0; i < orderedTrainCars.Count; i++) { if (!cargoTypeToTrainCarAndAmount.ContainsKey(orderedCargoTypes[i])) { cargoTypeToTrainCarAndAmount[orderedCargoTypes[i]] = new List <(TrainCar, float)>(); } cargoTypeToTrainCarAndAmount[orderedCargoTypes[i]].Add((orderedTrainCars[i], orderedCargoAmounts[i])); } List <CarsPerCargoType> unloadData = cargoTypeToTrainCarAndAmount.Select( kvPair => new CarsPerCargoType( kvPair.Key, kvPair.Value.Select(t => t.Item1.logicCar).ToList(), kvPair.Value.Aggregate(0.0f, (sum, t) => sum + t.Item2))).ToList(); StaticShuntingUnloadJobDefinition staticShuntingUnloadJobDefinition = gameObject.AddComponent <StaticShuntingUnloadJobDefinition>(); staticShuntingUnloadJobDefinition.PopulateBaseJobDefinition( destinationStation.logicStation, bonusTimeLimit, initialWage, chainData, requiredLicenses); staticShuntingUnloadJobDefinition.startingTrack = startingTrack; staticShuntingUnloadJobDefinition.carsPerDestinationTrack = carsPerDestinationTrack; staticShuntingUnloadJobDefinition.unloadData = unloadData; staticShuntingUnloadJobDefinition.unloadMachine = unloadMachine; staticShuntingUnloadJobDefinition.forceCorrectCargoStateOnCars = forceCorrectCargoStateOnCars; jobChainController.AddJobDefinitionToChain(staticShuntingUnloadJobDefinition); return(jobChainController); }
public static JobChainControllerWithEmptyHaulGeneration GenerateShuntingUnloadJobWithExistingCars( StationController startingStation, Track startingTrack, StationController destinationStation, List <TrainCar> trainCars, List <CargoType> transportedCargoPerCar, System.Random rng, bool forceCorrectCargoStateOnCars = false) { Debug.Log("[PersistentJobs] unload: generating with pre-spawned cars"); YardTracksOrganizer yto = YardTracksOrganizer.Instance; HashSet <CargoContainerType> carContainerTypes = new HashSet <CargoContainerType>(); foreach (TrainCar trainCar in trainCars) { carContainerTypes.Add(CargoTypes.CarTypeToContainerType[trainCar.carType]); } float approxTrainLength = yto.GetTotalTrainCarsLength(trainCars) + yto.GetSeparationLengthBetweenCars(trainCars.Count); // choose warehouse machine Debug.Log("[PersistentJobs] unload: choosing warehouse machine"); List <WarehouseMachineController> supportedWMCs = destinationStation.warehouseMachineControllers .Where(wm => wm.supportedCargoTypes.Intersect(transportedCargoPerCar).Count() > 0) .ToList(); if (supportedWMCs.Count == 0) { Debug.LogWarning(string.Format( "[PersistentJobs] unload: Could not create ChainJob[{0}]: {1} - {2}. Found no supported WarehouseMachine!", JobType.ShuntingLoad, startingStation.logicStation.ID, destinationStation.logicStation.ID)); return(null); } WarehouseMachine loadMachine = Utilities.GetRandomFromEnumerable(supportedWMCs, rng).warehouseMachine; // choose destination tracks int maxCountTracks = destinationStation.proceduralJobsRuleset.maxShuntingStorageTracks; int countTracks = rng.Next(1, maxCountTracks + 1); // bias toward less than max number of tracks for shorter trains if (trainCars.Count < 2 * maxCountTracks) { countTracks = rng.Next(0, Mathf.FloorToInt(1.5f * maxCountTracks)) % maxCountTracks + 1; } Debug.Log(string.Format("[PersistentJobs] unload: choosing {0} destination tracks", countTracks)); List <Track> destinationTracks = new List <Track>(); do { destinationTracks.Clear(); for (int i = 0; i < countTracks; i++) { Track track = Utilities.GetTrackThatHasEnoughFreeSpace( yto, destinationStation.logicStation.yard.StorageTracks.Except(destinationTracks).ToList(), approxTrainLength / (float)countTracks); if (track == null) { break; } destinationTracks.Add(track); } } while (destinationTracks.Count < countTracks--); if (destinationTracks.Count == 0) { Debug.LogWarning(string.Format( "[PersistentJobs] unload: Could not create ChainJob[{0}]: {1} - {2}. " + "Found no StorageTrack with enough free space!", JobType.ShuntingUnload, startingStation.logicStation.ID, destinationStation.logicStation.ID)); return(null); } // divide trainCars between destination tracks int countCarsPerTrainset = trainCars.Count / destinationTracks.Count; int countTrainsetsWithExtraCar = trainCars.Count % destinationTracks.Count; Debug.Log(string.Format( "[PersistentJobs] unload: dividing trainCars {0} per track with {1} extra", countCarsPerTrainset, countTrainsetsWithExtraCar)); List <TrainCar> orderedTrainCars = new List <TrainCar>(); List <CarsPerTrack> carsPerDestinationTrack = new List <CarsPerTrack>(); for (int i = 0; i < destinationTracks.Count; i++) { int rangeStart = i * countCarsPerTrainset + Math.Min(i, countTrainsetsWithExtraCar); int rangeCount = i < countTrainsetsWithExtraCar ? countCarsPerTrainset + 1 : countCarsPerTrainset; Track destinationTrack = destinationTracks[i]; carsPerDestinationTrack.Add( new CarsPerTrack( destinationTrack, (from car in trainCars.GetRange(rangeStart, rangeCount) select car.logicCar).ToList())); } Debug.Log("[PersistentJobs] unload: calculating time/wage/licenses"); float bonusTimeLimit; float initialWage; Utilities.CalculateShuntingBonusTimeLimitAndWage( JobType.ShuntingLoad, destinationTracks.Count, (from tc in trainCars select tc.carType).ToList <TrainCarType>(), transportedCargoPerCar, out bonusTimeLimit, out initialWage ); JobLicenses requiredLicenses = LicenseManager.GetRequiredLicensesForJobType(JobType.ShuntingUnload) | LicenseManager.GetRequiredLicensesForCargoTypes(transportedCargoPerCar) | LicenseManager.GetRequiredLicenseForNumberOfTransportedCars(trainCars.Count); return(GenerateShuntingUnloadChainController( startingStation, startingTrack, loadMachine, destinationStation, carsPerDestinationTrack, trainCars, transportedCargoPerCar, trainCars.Select( tc => tc.logicCar.CurrentCargoTypeInCar == CargoType.None ? 1.0f : tc.logicCar.LoadedCargoAmount).ToList(), forceCorrectCargoStateOnCars, bonusTimeLimit, initialWage, requiredLicenses)); }
private static StaticPassengerJobDefinition CreateSavedPassengerJob(GameObject jobChainGO, PassengerJobDefinitionData jobData) { // associated station if (!(GetStationWithId(jobData.stationId) is Station logicStation)) { PrintError($"Couldn't find corresponding Station with ID: {jobData.stationId}! Skipping load of this job chain!"); return(null); } // bonus time limit, base payment if (jobData.timeLimitForJob < 0f || jobData.initialWage < 0f || string.IsNullOrEmpty(jobData.originStationId) || string.IsNullOrEmpty(jobData.destinationStationId)) { PrintError("Invalid data! Skipping load of this job chain!"); return(null); } // license requirements if (!LicenseManager.IsValidForParsingToJobLicense(jobData.requiredLicenses)) { PrintError("Undefined job licenses requirement! Skipping load of this job chain!"); return(null); } // starting track if (!(GetYardTrackWithId(jobData.startingTrack) is Track startTrack)) { PrintError($"Couldn't find corresponding start Track with ID: {jobData.startingTrack}! Skipping load of this job chain!"); return(null); } // destination track if (!(GetYardTrackWithId(jobData.destinationTrack) is Track destTrack)) { PrintError($"Couldn't find corresponding destination Track with ID: {jobData.destinationTrack}! Skipping load of this job chain!"); return(null); } // consist if (!(GetCarsFromCarGuids(jobData.trainCarGuids) is List <Car> consist)) { PrintError("Couldn't find all carsToTransport with transportCarGuids! Skipping load of this job chain!"); return(null); } // loading platform WarehouseMachine loadMachine = null; if (!string.IsNullOrEmpty(jobData.loadingTrackId)) { if (PlatformManager.GetPlatformByTrackId(jobData.loadingTrackId) is PlatformDefinition pd) { loadMachine = pd.Controller.LogicMachine; } } // unloading platform WarehouseMachine unloadMachine = null; if (!string.IsNullOrEmpty(jobData.unloadingTrackId)) { if (PlatformManager.GetPlatformByTrackId(jobData.unloadingTrackId) is PlatformDefinition pd) { unloadMachine = pd.Controller.LogicMachine; } } // Named train SpecialTrain special = null; if (!string.IsNullOrWhiteSpace(jobData.specialName)) { special = SpecialConsistManager.TrainDefinitions.Find(train => string.Equals(train.Name, jobData.specialName)); } StaticPassengerJobDefinition jobDefinition = jobChainGO.AddComponent <StaticPassengerJobDefinition>(); var chainData = new StationsChainData(jobData.originStationId, jobData.destinationStationId); jobDefinition.PopulateBaseJobDefinition(logicStation, jobData.timeLimitForJob, jobData.initialWage, chainData, (JobLicenses)jobData.requiredLicenses); jobDefinition.subType = (JobType)jobData.subType; jobDefinition.startingTrack = startTrack; jobDefinition.destinationTrack = destTrack; jobDefinition.trainCarsToTransport = consist; jobDefinition.loadMachine = loadMachine; jobDefinition.unloadMachine = unloadMachine; jobDefinition.specialDefinition = special; return(jobDefinition); }
public static JobChainControllerWithEmptyHaulGeneration GenerateShuntingLoadJobWithExistingCars( StationController startingStation, List <CarsPerTrack> carsPerStartingTrack, StationController destStation, List <TrainCar> trainCars, List <CargoType> transportedCargoPerCar, System.Random rng, bool forceCorrectCargoStateOnCars = false) { Debug.Log("[PersistentJobs] load: generating with pre-spawned cars"); YardTracksOrganizer yto = YardTracksOrganizer.Instance; HashSet <CargoContainerType> carContainerTypes = new HashSet <CargoContainerType>(); foreach (TrainCar trainCar in trainCars) { carContainerTypes.Add(CargoTypes.CarTypeToContainerType[trainCar.carType]); } float approxTrainLength = yto.GetTotalTrainCarsLength(trainCars) + yto.GetSeparationLengthBetweenCars(trainCars.Count); // choose warehosue machine Debug.Log("[PersistentJobs] load: choosing warehouse machine"); List <WarehouseMachineController> supportedWMCs = startingStation.warehouseMachineControllers .Where(wm => wm.supportedCargoTypes.Intersect(transportedCargoPerCar).Count() > 0) .ToList(); if (supportedWMCs.Count == 0) { Debug.LogWarning(string.Format( "[PersistentJobs] load: Could not create ChainJob[{0}]: {1} - {2}. Found no supported WarehouseMachine!", JobType.ShuntingLoad, startingStation.logicStation.ID, destStation.logicStation.ID )); return(null); } WarehouseMachine loadMachine = Utilities.GetRandomFromEnumerable(supportedWMCs, rng).warehouseMachine; // choose destination track Debug.Log("[PersistentJobs] load: choosing destination track"); Track destinationTrack = Utilities.GetTrackThatHasEnoughFreeSpace( yto, yto.FilterOutOccupiedTracks(startingStation.logicStation.yard.TransferOutTracks), approxTrainLength ); if (destinationTrack == null) { destinationTrack = Utilities.GetTrackThatHasEnoughFreeSpace( yto, startingStation.logicStation.yard.TransferOutTracks, approxTrainLength ); } if (destinationTrack == null) { Debug.LogWarning(string.Format( "[PersistentJobs] load: Could not create ChainJob[{0}]: {1} - {2}. " + "Found no TransferOutTrack with enough free space!", JobType.ShuntingLoad, startingStation.logicStation.ID, destStation.logicStation.ID )); return(null); } Debug.Log("[PersistentJobs] load: calculating time/wage/licenses"); List <TrainCarType> transportedCarTypes = (from tc in trainCars select tc.carType) .ToList <TrainCarType>(); float bonusTimeLimit; float initialWage; Utilities.CalculateShuntingBonusTimeLimitAndWage( JobType.ShuntingLoad, carsPerStartingTrack.Count, transportedCarTypes, transportedCargoPerCar, out bonusTimeLimit, out initialWage ); JobLicenses requiredLicenses = LicenseManager.GetRequiredLicensesForJobType(JobType.ShuntingLoad) | LicenseManager.GetRequiredLicensesForCargoTypes(transportedCargoPerCar) | LicenseManager.GetRequiredLicenseForNumberOfTransportedCars(trainCars.Count); return(GenerateShuntingLoadChainController( startingStation, carsPerStartingTrack, loadMachine, destStation, destinationTrack, trainCars, transportedCargoPerCar, Enumerable.Repeat(1.0f, trainCars.Count).ToList(), forceCorrectCargoStateOnCars, bonusTimeLimit, initialWage, requiredLicenses )); }