示例#1
0
        public static void RegisterStation(StationController controller, PassengerJobGenerator gen)
        {
            if (LinkedGenerators.ContainsKey(controller))
            {
                return;
            }

            LinkedGenerators.Add(controller, gen);

            if (gen.PlatformTracks.Count > 0)
            {
                // potential destination
                PassDestinations[controller.stationInfo.YardID] = controller;
            }
        }
示例#2
0
        public static void CreateMachines(StationController station, bool signsEnabled)
        {
            if (PlatformDefs.TryGetValue(station.stationInfo.YardID, out var defList))
            {
                NextPlatformChoice[station.stationInfo.YardID] = 0;

                foreach (PlatformDefinition def in defList)
                {
                    //PassengerJobs.ModEntry.Logger.Log("Creating platform controller for " + def.Name);

                    if (PassengerJobGenerator.FindRTWithId(def.TrackId) is RailTrack pTrack)
                    {
                        def.PlatformTrack = pTrack.logicTrack;
                        //PassengerJobs.ModEntry.Logger.Log("Set track");
                    }
                    else
                    {
                        PassengerJobs.ModEntry.Logger.Warning("Couldn't find platform track for " + def.Name);
                        return;
                    }

                    // create dummy object to hold controller
                    var dummyObj = new GameObject($"PlatformController_{def.TrackId}");
                    dummyObj.transform.SetParent(station.gameObject.transform, false);

                    def.Controller = dummyObj.AddComponent <PlatformController>();
                    def.Controller.Initialize(pTrack, def.Name, station.stationInfo.YardID);

                    TrackToPlatformMap.Add(def.PlatformTrack.ID.FullID, def);

                    def.Controller.SignsActive = signsEnabled;
                    CreatePlatformSigns(def.TrackId, def.Controller);

                    PassengerJobs.ModEntry.Logger.Log("Successfully created platform controller for track " + def.TrackId);

                    def.Initialized = true;
                }
            }
        }
示例#3
0
        public PassengerTransportChainController GenerateNewTransportJob(TrainCarsPerLogicTrack consistInfo = null)
        {
            int nTotalCars;
            List <TrainCarType> jobCarTypes;
            float trainLength;
            Track startPlatform;

            if (consistInfo == null)
            {
                // generate a consist
                nTotalCars = Rand.Next(MIN_CARS_EXPRESS, MAX_CARS_EXPRESS + 1);

                if (PassengerJobs.Settings.UniformConsists)
                {
                    TrainCarType carType = PassCarTypes.ChooseOne(Rand);
                    jobCarTypes = Enumerable.Repeat(carType, nTotalCars).ToList();
                }
                else
                {
                    jobCarTypes = PassCarTypes.ChooseMany(Rand, nTotalCars);
                }

                trainLength = TrackOrg.GetTotalCarTypesLength(jobCarTypes) + TrackOrg.GetSeparationLengthBetweenCars(nTotalCars);

                var pool = TrackOrg.FilterOutReservedTracks(TrackOrg.FilterOutOccupiedTracks(PlatformTracks));
                if (!(TrackOrg.GetTrackThatHasEnoughFreeSpace(pool, trainLength) is Track startTrack))
                {
                    PassengerJobs.ModEntry.Logger.Log($"Couldn't find storage track with enough free space for new job at {Controller.stationInfo.YardID}");
                    return(null);
                }

                startPlatform = startTrack;
            }
            else
            {
                // Use existing consist
                nTotalCars    = consistInfo.cars.Count;
                jobCarTypes   = consistInfo.cars.Select(car => car.carType).ToList();
                trainLength   = TrackOrg.GetTotalCarTypesLength(jobCarTypes) + TrackOrg.GetSeparationLengthBetweenCars(nTotalCars);
                startPlatform = consistInfo.track;
            }

            if (startPlatform == null)
            {
                PassengerJobs.ModEntry.Logger.Log($"No available platform for new job at {Controller.stationInfo.Name}");
                return(null);
            }

            // Choose a route
            var               destPool     = PassDestinations.Values.ToList();
            Track             destPlatform = null;
            StationController destStation  = null;

            // this prevents generating jobs like "ChainJob[Passenger]: FF - FF (FF-PE-47)"
            destPool.Remove(Controller);

            while ((destPlatform == null) && (destPool.Count > 0))
            {
                // search the possible destinations 1 by 1 until we find an opening (or we don't)
                destStation = destPool.ChooseOne(Rand);

                // pick ending platform
                PassengerJobGenerator destGenerator = LinkedGenerators[destStation];
                destPlatform = TrackOrg.GetTrackThatHasEnoughFreeSpace(destGenerator.PlatformTracks, trainLength);

                // remove this station from the pool
                destPool.Remove(destStation);
            }

            if (destPlatform == null)
            {
                PassengerJobs.ModEntry.Logger.Log($"No available destination platform for new job at {Controller.stationInfo.Name}");
                return(null);
            }

            // create job chain controller
            var chainJobObject = new GameObject($"ChainJob[Passenger]: {Controller.logicStation.ID} - {destStation.logicStation.ID}");

            chainJobObject.transform.SetParent(Controller.transform);
            var chainController = new PassengerTransportChainController(chainJobObject);

            StaticPassengerJobDefinition jobDefinition;

            //--------------------------------------------------------------------------------------------------------------------------------
            // Create transport leg job
            var chainData = new StationsChainData(Controller.stationInfo.YardID, destStation.stationInfo.YardID);
            PaymentCalculationData transportPaymentData = GetJobPaymentData(jobCarTypes);

            // calculate haul payment
            float haulDistance     = JobPaymentCalculator.GetDistanceBetweenStations(Controller, destStation);
            float bonusLimit       = JobPaymentCalculator.CalculateHaulBonusTimeLimit(haulDistance, false);
            float transportPayment = JobPaymentCalculator.CalculateJobPayment(JobType.Transport, haulDistance, transportPaymentData);

            // scale job payment depending on settings
            float wageScale = PassengerJobs.Settings.UseCustomWages ? BASE_WAGE_SCALE : 1;

            transportPayment = Mathf.Round(transportPayment * wageScale);

            if (consistInfo == null)
            {
                jobDefinition = PopulateTransportJobAndSpawn(
                    chainController, Controller.logicStation, startPlatform, destPlatform,
                    jobCarTypes, chainData, bonusLimit, transportPayment, true);
            }
            else
            {
                chainController.trainCarsForJobChain = consistInfo.cars;

                jobDefinition = PopulateTransportJobExistingCars(
                    chainController, Controller.logicStation, startPlatform, destPlatform,
                    consistInfo.LogicCars, chainData, bonusLimit, transportPayment);
            }

            if (jobDefinition == null)
            {
                PassengerJobs.ModEntry.Logger.Warning($"Failed to generate transport job definition for {chainController.jobChainGO.name}");
                chainController.DestroyChain();
                return(null);
            }
            jobDefinition.subType = PassJobType.Express;

            chainController.AddJobDefinitionToChain(jobDefinition);

            // Finalize job
            chainController.FinalizeSetupAndGenerateFirstJob();
            PassengerJobs.ModEntry.Logger.Log($"Generated new passenger haul job: {chainJobObject.name} ({chainController.currentJobInChain.ID})");

            return(chainController);
        }
示例#4
0
 public void PurgeData()
 {
     PassengerLicenseUtil.RefundLicenses();
     PassengerLicenseUtil.DestroySpawnedLicenses();
     PassengerJobGenerator.PurgePassengerJobChains();
 }
示例#5
0
        public PassengerTransportChainController GenerateNewTransportJob(TrainCarsPerLogicTrack consistInfo = null, SpecialTrain prevSpecial = null)
        {
            int nTotalCars;
            List <TrainCarType> jobCarTypes = null;
            float trainLength;
            Track startSiding;

            // Establish the starting consist and its storage location
            if (consistInfo == null)
            {
                // generate a consist
                nTotalCars = Rand.Next(MIN_CARS_EXPRESS, MAX_CARS_EXPRESS + 1);

                float singleCarLength = TrackOrg.GetCarTypeLength(TrainCarType.PassengerRed);
                trainLength = (singleCarLength * nTotalCars) + TrackOrg.GetSeparationLengthBetweenCars(nTotalCars);

                // pick start storage track
                var emptyTracks = TrackOrg.FilterOutOccupiedTracks(StorageTracks);
                startSiding = TrackOrg.GetTrackWithEnoughFreeSpace(emptyTracks, trainLength);

                if (startSiding == null)
                {
                    startSiding = TrackOrg.GetTrackWithEnoughFreeSpace(StorageTracks, trainLength);
                }
            }
            else
            {
                // Use existing consist
                nTotalCars  = consistInfo.cars.Count;
                jobCarTypes = consistInfo.cars.Select(car => car.carType).ToList();
                trainLength = TrackOrg.GetTotalCarTypesLength(jobCarTypes) + TrackOrg.GetSeparationLengthBetweenCars(nTotalCars);
                startSiding = consistInfo.track;
            }

            if (startSiding == null)
            {
                //PassengerJobs.ModEntry.Logger.Log($"No available starting siding for express job at {Controller.stationInfo.Name}");
                return(null);
            }

            // Try to find a loading platform to use
            PlatformDefinition loadingPlatform = PlatformManager.PickPlatform(Controller.stationInfo.YardID);

            // Choose a route
            var               destPool    = PassDestinations.Values.ToList();
            Track             destSiding  = null;
            StationController destStation = null;

            // this prevents generating jobs like "ChainJob[Passenger]: FF - FF (FF-PE-47)"
            destPool.Remove(Controller);

            while ((destSiding == null) && (destPool.Count > 0))
            {
                // search the possible destinations 1 by 1 until we find an opening (or we don't)
                destStation = destPool.ChooseOne(Rand);

                // pick ending platform
                PassengerJobGenerator destGenerator = LinkedGenerators[destStation];
                destSiding = TrackOrg.GetTrackWithEnoughFreeSpace(destGenerator.StorageTracks, trainLength);

                // remove this station from the pool
                destPool.Remove(destStation);
            }

            if (destSiding == null)
            {
                //PassengerJobs.ModEntry.Logger.Log($"No available destination siding for new job at {Controller.stationInfo.Name}");
                return(null);
            }

            // we found a route :D
            // if we're creating a new consist, check if it can be a special train
            // let's try 2/3 chance of special train, 1/3 normal gen
            SpecialTrain  specialInfo = null;
            List <string> skinList    = null;

            if (consistInfo == null)
            {
                // default 67% chance, or as configured (if there is a special available)
                double choice = Rand.NextDouble();

                if ((choice <= PassengerJobs.Settings.NamedTrainProbability) &&
                    (SpecialConsistManager.GetTrainForRoute(Controller.stationInfo.YardID, destStation.stationInfo.YardID) is SpecialTrain special))
                {
                    specialInfo = special;
                    IEnumerable <SpecialTrainSkin> consistSkins = special.Skins.ChooseMany(Rand, nTotalCars);
                    jobCarTypes = consistSkins.Select(s => s.CarType).ToList();
                    skinList    = consistSkins.Select(s => s.Name).ToList();
                }
                else
                {
                    // normal consist generation
                    if (PassengerJobs.Settings.UniformConsists)
                    {
                        TrainCarType carType = PassCarTypes.ChooseOne(Rand);
                        jobCarTypes = Enumerable.Repeat(carType, nTotalCars).ToList();
                    }
                    else
                    {
                        jobCarTypes = PassCarTypes.ChooseMany(Rand, nTotalCars);
                    }
                }
            }
            else
            {
                // extant consist, use existing special (if it exists)
                specialInfo = prevSpecial;
            }

            // Try to find an unloading platform
            PlatformDefinition unloadingPlatform = PlatformManager.PickPlatform(destStation.stationInfo.YardID);

            // create job chain controller
            var chainJobObject = new GameObject($"ChainJob[Passenger]: {Controller.logicStation.ID} - {destStation.logicStation.ID}");

            chainJobObject.transform.SetParent(Controller.transform);
            var chainController = new PassengerTransportChainController(chainJobObject);

            StaticPassengerJobDefinition jobDefinition;

            //--------------------------------------------------------------------------------------------------------------------------------
            // Create transport leg job
            var chainData = new StationsChainData(Controller.stationInfo.YardID, destStation.stationInfo.YardID);
            PaymentCalculationData transportPaymentData = GetJobPaymentData(jobCarTypes);

            // calculate haul payment
            float haulDistance     = JobPaymentCalculator.GetDistanceBetweenStations(Controller, destStation);
            float bonusLimit       = JobPaymentCalculator.CalculateHaulBonusTimeLimit(haulDistance, false);
            float transportPayment = JobPaymentCalculator.CalculateJobPayment(JobType.Transport, haulDistance, transportPaymentData);

            // calculate additional payment for shunting
            const float            shuntDistance    = 500f;
            PaymentCalculationData emptyPaymentData = GetJobPaymentData(jobCarTypes, true);
            float platformBonusTime = JobPaymentCalculator.CalculateShuntingBonusTimeLimit(1) * 0.7f + PlatformController.START_XFER_DELAY;

            if (loadingPlatform?.Initialized == true)
            {
                float loadPayment = JobPaymentCalculator.CalculateJobPayment(JobType.ShuntingLoad, shuntDistance, emptyPaymentData);
                transportPayment += loadPayment;
                bonusLimit       += platformBonusTime;
            }

            if (unloadingPlatform?.Initialized == true)
            {
                float unloadPayment = JobPaymentCalculator.CalculateJobPayment(JobType.ShuntingUnload, shuntDistance, emptyPaymentData);
                transportPayment += unloadPayment;
                bonusLimit       += platformBonusTime;
            }

            // scale job payment depending on settings
            float wageScale = PassengerJobs.Settings.UseCustomWages ? BASE_WAGE_SCALE : 1;

            transportPayment = Mathf.Round(transportPayment * wageScale);

            if (consistInfo == null)
            {
                jobDefinition = PopulateTransportJobAndSpawn(
                    chainController, Controller.logicStation, startSiding, destSiding,
                    jobCarTypes, chainData, bonusLimit, transportPayment, true, skinList);
            }
            else
            {
                chainController.trainCarsForJobChain = consistInfo.cars;

                jobDefinition = PopulateTransportJobExistingCars(
                    chainController, Controller.logicStation, startSiding, destSiding,
                    consistInfo.LogicCars, chainData, bonusLimit, transportPayment);
            }

            if (jobDefinition == null)
            {
                PassengerJobs.ModEntry.Logger.Warning($"Failed to generate transport job definition for {chainController.jobChainGO.name}");
                chainController.DestroyChain();
                return(null);
            }
            jobDefinition.subType           = PassJobType.Express;
            jobDefinition.specialDefinition = specialInfo;

            // Setup any warehouse tasks
            if (loadingPlatform?.Initialized == true)
            {
                jobDefinition.loadMachine = loadingPlatform.Controller.LogicMachine;
            }

            if (unloadingPlatform?.Initialized == true)
            {
                jobDefinition.unloadMachine = unloadingPlatform.Controller.LogicMachine;
            }

            chainController.AddJobDefinitionToChain(jobDefinition);

            // Finalize job
            chainController.FinalizeSetupAndGenerateFirstJob();
            PassengerJobs.ModEntry.Logger.Log($"Generated new passenger haul job: {chainJobObject.name} ({chainController.currentJobInChain.ID})");

            return(chainController);
        }