protected float Sample(ProfileableResource resource, Vector3 worldPos, float noiseScalar)
        {
            float abundance = 0f;

            AbundanceRequest req = new AbundanceRequest();
            double           alt;
            double           lat;
            double           lon;

            part.vessel.mainBody.GetLatLonAlt(new Vector3d(worldPos.x, worldPos.y, worldPos.z), out lat, out lon, out alt);

            req.BodyId       = FlightGlobals.GetBodyIndex(part.vessel.mainBody);
            req.ResourceName = resource.resourceName;
            req.Latitude     = lat;
            req.Altitude     = alt;
            req.Longitude    = lon;

            // Sample atmo
            req.ResourceType = HarvestTypes.Atmospheric;
            abundance       += ResourceMap.Instance.GetAbundance(req);
            if (resource.useAtmo)
            {
                abundance = abundance * (float)part.vessel.mainBody.GetPressure(alt);
            }

            // Sample exo
            req.ResourceType = HarvestTypes.Exospheric;
            abundance        = abundance + ResourceMap.Instance.GetAbundance(req);
            //Utils.Log(String.Format("[ModuleProfilingScanner]: Sampling position {0}, geocentric alt {1}, lat {2} lon {3}\n Noise: {4} Result: {5}", worldPos.ToString(), alt, lat, lon, noiseScalar, abundance));
            abundance = abundance + noiseScalar * UnityEngine.Random.Range(-1.0f, 1.0f);

            return(Mathf.Clamp(abundance, 0f, 10000f));
        }
Example #2
0
        static void ProcessHarvester(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleResourceHarvester harvester, vessel_resources resources, double elapsed_s)
        {
            // note: ignore stock temperature mechanic of harvesters
            // note: ignore autoshutdown
            // note: ignore depletion (stock seem to do the same)
            // note: using hard-coded crew bonus values from the wiki because the module data make zero sense (DERP ALERT)
            // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)

            // if active
            if (Lib.Proto.GetBool(m, "IsActivated"))
            {
                // do nothing if full
                // note: comparing against previous amount
                if (resources.Info(v, harvester.ResourceName).level < harvester.FillAmount - double.Epsilon)
                {
                    // get malfunction penalty
                    double penalty = Reliability.Penalty(p, "Harvester");

                    // deduce crew bonus
                    int exp_level = -1;
                    if (harvester.UseSpecialistBonus)
                    {
                        foreach (ProtoCrewMember c in v.protoVessel.GetVesselCrew())
                        {
                            exp_level = Math.Max(exp_level, c.trait == harvester.Specialty ? c.experienceLevel : -1);
                        }
                    }
                    double exp_bonus = exp_level < 0 ? 1.0 : 5.0 + (double)exp_level * 4.0;

                    // detect amount of ore in the ground
                    AbundanceRequest request = new AbundanceRequest
                    {
                        Altitude     = v.altitude,
                        BodyId       = v.mainBody.flightGlobalsIndex,
                        CheckForLock = false,
                        Latitude     = v.latitude,
                        Longitude    = v.longitude,
                        ResourceType = (HarvestTypes)harvester.HarvesterType,
                        ResourceName = harvester.ResourceName
                    };
                    double abundance = ResourceMap.Instance.GetAbundance(request);

                    // if there is actually something (should be if active when unloaded)
                    if (abundance > harvester.HarvestThreshold)
                    {
                        // create and commit recipe
                        resource_recipe recipe = new resource_recipe(resource_recipe.harvester_priority);
                        foreach (var ir in harvester.inputList)
                        {
                            recipe.Input(ir.ResourceName, ir.Ratio * elapsed_s);
                        }
                        recipe.Output(harvester.ResourceName, abundance * harvester.Efficiency * exp_bonus * penalty * elapsed_s);
                        resources.Transform(recipe);
                    }
                }

                // undo stock behaviour by forcing last_update_time to now
                Lib.Proto.Set(m, "lastUpdateTime", Planetarium.GetUniversalTime());
            }
        }
Example #3
0
        public void Update()
        {
            // in editor and flight, update ui button label
            Events["Toggle"].guiName = Lib.StatusToggle(title, running ? "running" : "stopped");

            // if in flight, and the stock planet resource system is online
            if (Lib.IsFlight() && ResourceMap.Instance != null)
            {
                // shortcut
                CelestialBody body = vessel.mainBody;

                // determine if overall situation is valid for extraction
                bool valid = false;
                if (deployed)
                {
                    switch (type)
                    {
                    case 0: valid = vessel.Landed && GroundContact(); break;

                    case 1: valid = body.ocean && (vessel.Splashed || vessel.altitude < 0.0); break;

                    case 2: valid = body.atmosphere && vessel.altitude < body.atmosphereDepth; break;

                    case 3: valid = vessel.altitude > body.atmosphereDepth || !body.atmosphere; break;
                    }
                }

                // if situation is valid
                double abundance = 0.0;
                if (valid)
                {
                    // get abundance
                    AbundanceRequest request = new AbundanceRequest
                    {
                        ResourceType = (HarvestTypes)type,
                        ResourceName = resource,
                        BodyId       = body.flightGlobalsIndex,
                        Latitude     = vessel.latitude,
                        Longitude    = vessel.longitude,
                        Altitude     = vessel.altitude,
                        CheckForLock = false
                    };
                    abundance = ResourceMap.Instance.GetAbundance(request);
                }

                // determine if resources can be harvested
                // - invalid conditions
                // - abundance below threshold
                // - pressure below threshold
                starved = !valid || abundance <= min_abundance || (type == 2 && body.GetPressure(vessel.altitude) <= min_pressure);

                // update ui
                Events["Toggle"].guiActive    = valid;
                Fields["Abundance"].guiActive = valid;
                Fields["Abundance"].guiName   = Lib.BuildString(resource, " abundance");
                Abundance = abundance > double.Epsilon ? Lib.HumanReadablePerc(abundance, "F2") : "none";
            }
        }
            public ResourceAbundanceTracker(ModuleResourceScanner scanner)
            {
                request = new AbundanceRequest();
                request.CheckForLock = scanner.RequiresUnlock;
                request.ResourceType = (HarvestTypes)scanner.ScannerType;
                request.ResourceName = scanner.ResourceName;

                abundance = 0;
            }
        private static double GetAbundance(AbundanceRequest request)
        {
            // retrieve and convert to double
            double abundance = (double)(decimal)ResourceMap.Instance.GetAbundance(request) * 100;

            if (abundance < 1)
            {
                abundance = Math.Pow(abundance, 3);
            }

            return(abundance);
        }
Example #6
0
        public static int GenerateAbundanceSeed(AbundanceRequest request, CBAttributeMapSO.MapAttribute biome, CelestialBody body)
        {
            var seed = RegolithScenario.Instance.gameSettings.Seed;
            seed *= (request.BodyId + 1);
            seed += request.ResourceName.Length * request.ResourceName.Substring(1).ToCharArray().First();
            seed += body.bodyName.Length * body.bodyName.Substring(1).ToCharArray().First();

            if (biome != null)
            {
                seed += Convert.ToInt32(biome.mapColor.grayscale * 4096) * ((int)request.ResourceType + 1);
            }
            return seed;
        }
 public double GetAmount(string ResourceName, RPLocation location, double rate)
 {
     AbundanceRequest request = new AbundanceRequest {
         Altitude = location.altitude,
         BodyId = location.bodyIndex,
         CheckForLock = false,
         Latitude = location.latitude,
         Longitude = location.longitude,
         ResourceType = 0,
         ResourceName = ResourceName
     };
     return ResourceMap.Instance.GetAbundance(request) * rate;
 }
Example #8
0
 public static float GetAbundance(double latitude, double longitude, string resourceName, int bodyId, int resType, int altitude, bool checkForLock = true)
 {
     var abRequest = new AbundanceRequest
                     {
                         Latitude = latitude,
                         Longitude = longitude,
                         BodyId = bodyId,
                         ResourceName = resourceName,
                         ResourceType = (HarvestTypes)resType,
                         Altitude = altitude,
                         CheckForLock = checkForLock  //TRUE = means that biome unlocking is active
                     };
     return GetAbundance(abRequest);
 }
        public double GetAmount(string ResourceName, RPLocation location, double rate)
        {
            AbundanceRequest request = new AbundanceRequest {
                Altitude     = location.altitude,
                BodyId       = location.bodyIndex,
                CheckForLock = false,
                Latitude     = location.latitude,
                Longitude    = location.longitude,
                ResourceType = 0,
                ResourceName = ResourceName
            };

            return(ResourceMap.Instance.GetAbundance(request) * rate);
        }
Example #10
0
		// return resource abundance at vessel position
		private static double SampleAbundance(Vessel v, Harvester harvester)
		{
			// get abundance
			AbundanceRequest request = new AbundanceRequest
			{
				ResourceType = (HarvestTypes)harvester.type,
				ResourceName = harvester.resource,
				BodyId = v.mainBody.flightGlobalsIndex,
				Latitude = v.latitude,
				Longitude = v.longitude,
				Altitude = v.altitude,
				CheckForLock = false
			};
			return ResourceMap.Instance.GetAbundance(request);
		}
        // return resource abundance at vessel position
        double SampleAbundance()
        {
            // get abundance
            AbundanceRequest request = new AbundanceRequest
            {
                ResourceType = (HarvestTypes)type,
                ResourceName = resource,
                BodyId       = vessel.mainBody.flightGlobalsIndex,
                Latitude     = vessel.latitude,
                Longitude    = vessel.longitude,
                Altitude     = vessel.altitude,
                CheckForLock = false
            };

            return(ResourceMap.Instance.GetAbundance(request));
        }
Example #12
0
        ///<summary>
        ///returns the amount of a given resource for a body and place
        /// takes the args <body> <geocoordinates> and <resource-string> in any order
        ///</summary>
        public ScalarDoubleValue GetResourceByName(params Structure[] args)
        {
            if (args.Length != 3)
            {
                return(null);
            }
            BodyTarget     body       = args.Where(s => s.GetType() == typeof(BodyTarget)).Cast <BodyTarget>().First();
            GeoCoordinates coordinate = args.Where(s => s.GetType() == typeof(GeoCoordinates)).Cast <GeoCoordinates>().First();
            StringValue    s_type     = args.Where(s => s.GetType() == typeof(StringValue)).Cast <StringValue>().First();

            if (resourceNames == null)
            {
                resourceNames = ResourceMap.Instance.FetchAllResourceNames(HarvestTypes.Planetary);
            }

            var resourceName = resourceNames.FirstOrDefault(name => string.Equals(name, s_type, StringComparison.InvariantCultureIgnoreCase));

            if (resourceName == null)
            {
                throw new kOS.Safe.Exceptions.KOSException("invalid resource type");
            }

            if ((SCANWrapper.IsCovered(coordinate.Longitude, coordinate.Latitude, body.Body, "ResourceHiRes")) || ((HasKerbNet("Resource") && (IsInKerbNetFoV(body.Body, coordinate.Longitude, coordinate.Latitude)))))
            {
                float amount   = 0f;
                var   aRequest = new AbundanceRequest
                {
                    Latitude        = coordinate.Latitude,
                    Longitude       = coordinate.Longitude,
                    BodyId          = body.Body.flightGlobalsIndex,
                    ResourceName    = resourceName,
                    ResourceType    = HarvestTypes.Planetary,
                    Altitude        = 0,
                    CheckForLock    = SCANWrapper.GetResourceBiomeLock(),
                    BiomeName       = ScienceUtil.GetExperimentBiome(body.Body, coordinate.Latitude, coordinate.Longitude),
                    ExcludeVariance = false,
                };

                amount = ResourceMap.Instance.GetAbundance(aRequest);
                return(amount);
            }
            else
            {
                return(-1.0);
            }
        }
Example #13
0
        protected override ConversionRecipe PrepareRecipe(double deltaTime)
        {
            if (HighLogic.LoadedSceneIsFlight && this.HarvesterType == 3)
            {
                // Handle resource generation here.
                var request = new AbundanceRequest
                {
                    Altitude     = this.vessel.altitude,
                    BodyId       = FlightGlobals.currentMainBody.flightGlobalsIndex,
                    CheckForLock = false,
                    // BiomeName = ??
                    Latitude     = this.vessel.latitude,
                    Longitude    = this.vessel.longitude,
                    ResourceType = HarvestTypes.Exospheric,
                    ResourceName = this.ResourceName
                };

                var abundance = ResourceMap.Instance.GetAbundance(request);
                if (abundance < 1E-09 || abundance < this.HarvestThreshold)
                {
                    this.status      = "missing resource";
                    this.IsActivated = false;
                    return(null);
                }
                else
                {
                    // we found a resource!
                    if (counter % 10 == 0)
                    {
                        ScreenMessages.PostScreenMessage("Found " + this.ResourceName);
                    }

                    this.status = "harvesting";
                    var conversionRate = abundance * this.Efficiency * this.GetCrewBonus();
                    var orbitalSpeed   = this.vessel.orbit.vel.magnitude + 1;
                    var intakeRate     = conversionRate * orbitalSpeed;

                    return(GenerateRecipie(intakeRate));
                }
            }
            else
            {
                return(base.PrepareRecipe(deltaTime));
            }
        }
Example #14
0
        internal static float ResourceOverlay(double lat, double lon, string name, CelestialBody body)
        {
            float amount   = 0f;
            var   aRequest = new AbundanceRequest
            {
                Latitude        = lat,
                Longitude       = lon,
                BodyId          = body.flightGlobalsIndex,
                ResourceName    = name,
                ResourceType    = HarvestTypes.Planetary,
                Altitude        = 0,
                CheckForLock    = SCANcontroller.controller.resourceBiomeLock,
                BiomeName       = getBiomeName(body, lon, lat),
                ExcludeVariance = false,
            };

            amount = ResourceMap.Instance.GetAbundance(aRequest);
            return(amount);
        }
Example #15
0
        public static float GetAbundance(string resourceName, CelestialBody body, double lat, double lon)
        {
            var biome = ScienceUtil.GetExperimentBiome(body, lat, lon);
            var key   = new Key(resourceName, biome, lat, lon);

            if (!cache.ContainsKey(key))
            {
                var req = new AbundanceRequest
                {
                    Latitude        = lat,
                    Longitude       = lon,
                    BodyId          = body.flightGlobalsIndex,
                    ResourceName    = resourceName,
                    ResourceType    = HarvestTypes.Planetary,
                    Altitude        = 0,
                    CheckForLock    = false,
                    BiomeName       = biome,
                    ExcludeVariance = false,
                };
                cache[key] = ResourceMap.Instance.GetAbundance(req);
            }
            return(cache[key]);
        }
Example #16
0
        ///<summary>
        ///returns the amount of a given resource for a body and place
        /// takes the args <body> <geocoordinates> and <resource-string> in any order
        ///</summary>
        public ScalarDoubleValue GetResourceByName(params Structure[] args)
        {
            if (args.Length != 3)
            {
                return(null);
            }
            BodyTarget body = args.Where(s => s.GetType() == typeof(BodyTarget)).Cast <BodyTarget>().First();
            //            BodyTarget body = args[0] as BodyTarget;
            GeoCoordinates coordinate = args.Where(s => s.GetType() == typeof(GeoCoordinates)).Cast <GeoCoordinates>().First();
            StringValue    s_type     = args.Where(s => s.GetType() == typeof(StringValue)).Cast <StringValue>().First();

            if ((SCANWrapper.IsCovered(coordinate.Longitude, coordinate.Latitude, body.Body, s_type)) || ((HasKerbNet("Resource") && (IsInKerbNetFoV(body.Body, coordinate.Longitude, coordinate.Latitude)))))

            {
                float amount   = 0f;
                var   aRequest = new AbundanceRequest
                {
                    Latitude        = coordinate.Latitude,
                    Longitude       = coordinate.Longitude,
                    BodyId          = body.Body.flightGlobalsIndex,
                    ResourceName    = s_type,
                    ResourceType    = HarvestTypes.Planetary,
                    Altitude        = 0,
                    CheckForLock    = SCANWrapper.GetResourceBiomeLock(),
                    BiomeName       = ScienceUtil.GetExperimentBiome(body.Body, coordinate.Latitude, coordinate.Longitude),
                    ExcludeVariance = false,
                };

                amount = ResourceMap.Instance.GetAbundance(aRequest);
                return(amount);
            }
            else
            {
                return(-1.0);
            }
        }
Example #17
0
        protected string getAbundance(string resourceName)
        {
            AbundanceRequest request   = new AbundanceRequest();
            double           lattitude = ResourceUtilities.Deg2Rad(this.part.vessel.latitude);
            double           longitude = ResourceUtilities.Deg2Rad(this.part.vessel.longitude);

            request.BiomeName    = Utils.GetCurrentBiome(this.part.vessel).name;
            request.BodyId       = this.part.vessel.mainBody.flightGlobalsIndex;
            request.Longitude    = longitude;
            request.Latitude     = lattitude;
            request.CheckForLock = true;
            request.ResourceName = resourceName;

            float abundance = ResourceMap.Instance.GetAbundance(request) * 100.0f;

            if (abundance > 0.001)
            {
                return(string.Format("{0:f2}%", abundance));
            }
            else
            {
                return("Unknown");
            }
        }
Example #18
0
        private void DrawLogistics()
        {
            var vessels = LogisticsTools.GetNearbyVessels(2000, true, _model, true);
            List <LogisticsResource>   resources = new List <LogisticsResource>();
            Dictionary <string, float> dr        = new Dictionary <string, float>();

            int kerbals = 0;

            foreach (Vessel v in vessels)
            {
                // Storage
                foreach (var r in v.GetStorage())
                {
                    getResourceFromList(resources, r.resourceName).maxAmount += r.amount;
                }

                // Amount
                foreach (var r in v.GetResourceAmounts())
                {
                    getResourceFromList(resources, r.resourceName).amount += r.amount;
                }

                // Production of converters
                foreach (var r in v.GetProduction())
                {
                    getResourceFromList(resources, r.resourceName).change += r.amount;
                }

                // Consumption of Converters
                foreach (var r in v.GetProduction(false))
                {
                    getResourceFromList(resources, r.resourceName).change -= r.amount;
                }

                // Drills
                foreach (Part drill in v.Parts.Where(p => p.Modules.Contains("ModuleResourceHarvester")))
                {
                    foreach (ModuleResourceHarvester m in drill.FindModulesImplementing <ModuleResourceHarvester>().Where(mod => mod.IsActivated))
                    {
                        if (v.Parts.Exists(p => p.Resources.list.Exists(r => r.resourceName == m.ResourceName && r.amount < r.maxAmount)))
                        // test if storage for this resource on this vessel is not full
                        {
                            AbundanceRequest ar = new AbundanceRequest
                            {
                                Altitude     = v.altitude,
                                BodyId       = FlightGlobals.currentMainBody.flightGlobalsIndex,
                                CheckForLock = false,
                                Latitude     = v.latitude,
                                Longitude    = v.longitude,
                                ResourceType = HarvestTypes.Planetary,
                                ResourceName = m.ResourceName
                            };
                            getResourceFromList(resources, m.ResourceName).change   += (double)ResourceMap.Instance.GetAbundance(ar);
                            getResourceFromList(resources, "ElectricCharge").change -= 6;
                        }
                    }
                }

                // Life Support
                kerbals += v.GetCrewCount();
            }
            if (_usils)
            {
                getResourceFromList(resources, "Supplies").change       -= kerbals * 0.00005;
                getResourceFromList(resources, "Mulch").change          += kerbals * 0.00005;
                getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.01;
            }
            resources.Sort(new LogisticsResourceComparer());
            foreach (LogisticsResource r in resources)
            {
                GUILayout.Label(r.resourceName + ": " + numberToOut(r.amount, -1, false) + "/" + Math.Round(r.maxAmount, 5) + " (" + numberToOut(r.change, r.change > 0 ? r.maxAmount - r.amount : r.amount) + ")");
            }
        }
Example #19
0
        static void ProcessHarvester(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleResourceHarvester harvester, vessel_resources resources, double elapsed_s)
        {
            // note: ignore stock temperature mechanic of harvesters
            // note: ignore autoshutdown
            // note: ignore depletion (stock seem to do the same)
            // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)

            // if active
            if (Lib.Proto.GetBool(m, "IsActivated"))
            {
                // do nothing if full
                // note: comparing against previous amount
                if (resources.Info(v, harvester.ResourceName).level < harvester.FillAmount - double.Epsilon)
                {
                    // deduce crew bonus
                    int exp_level = -1;
                    if (harvester.UseSpecialistBonus)
                    {
                        foreach (ProtoCrewMember c in Lib.CrewList(v))
                        {
                            if (c.experienceTrait.Effects.Find(k => k.Name == harvester.ExperienceEffect) != null)
                            {
                                exp_level = Math.Max(exp_level, c.experienceLevel);
                            }
                        }
                    }
                    double exp_bonus = exp_level < 0
          ? harvester.EfficiencyBonus * harvester.SpecialistBonusBase
          : harvester.EfficiencyBonus * (harvester.SpecialistBonusBase + (harvester.SpecialistEfficiencyFactor * (exp_level + 1)));

                    // detect amount of ore in the ground
                    AbundanceRequest request = new AbundanceRequest
                    {
                        Altitude     = v.altitude,
                        BodyId       = v.mainBody.flightGlobalsIndex,
                        CheckForLock = false,
                        Latitude     = v.latitude,
                        Longitude    = v.longitude,
                        ResourceType = (HarvestTypes)harvester.HarvesterType,
                        ResourceName = harvester.ResourceName
                    };
                    double abundance = ResourceMap.Instance.GetAbundance(request);

                    // if there is actually something (should be if active when unloaded)
                    if (abundance > harvester.HarvestThreshold)
                    {
                        // create and commit recipe
                        resource_recipe recipe = new resource_recipe();
                        foreach (var ir in harvester.inputList)
                        {
                            recipe.Input(ir.ResourceName, ir.Ratio * elapsed_s);
                        }
                        recipe.Output(harvester.ResourceName, abundance * harvester.Efficiency * exp_bonus * elapsed_s, true);
                        resources.Transform(recipe);
                    }
                }

                // undo stock behaviour by forcing last_update_time to now
                Lib.Proto.Set(m, "lastUpdateTime", Planetarium.GetUniversalTime());
            }
        }
Example #20
0
        private void DrawLogistics()
        {
            var vessels = LogisticsTools.GetNearbyVessels(2000, true, _model, true);
            List <LogisticsResource>   resources = new List <LogisticsResource>();
            Dictionary <string, float> dr        = new Dictionary <string, float>();

            int kerbals = 0;

            foreach (Vessel v in vessels)
            {
                // Storage
                foreach (var r in v.GetStorage())
                {
                    getResourceFromList(resources, r.resourceName).maxAmount += r.amount;
                }

                // Amount
                foreach (var r in v.GetResourceAmounts())
                {
                    getResourceFromList(resources, r.resourceName).amount += r.amount;
                }

                // Production of converters
                foreach (var r in v.GetProduction())
                {
                    getResourceFromList(resources, r.resourceName).change += r.amount;
                }

                // Consumption of Converters
                foreach (var r in v.GetProduction(false))
                {
                    getResourceFromList(resources, r.resourceName).change -= r.amount;
                }

                // Drills
                foreach (Part drill in v.Parts.Where(p => p.Modules.Contains("ModuleResourceHarvester")))
                {
                    foreach (ModuleResourceHarvester m in drill.FindModulesImplementing <ModuleResourceHarvester>().Where(mod => mod.IsActivated))
                    {
                        bool hasResource = false;
                        foreach (var p in v.Parts)
                        {
                            var res = p.Resources.Get(m.ResourceName);
                            if (res == null)
                            {
                                continue;
                            }
                            if (res.amount <= res.maxAmount)
                            {
                                hasResource = true;
                            }
                        }
                        if (hasResource)
                        // test if storage for this resource on this vessel is not full
                        {
                            AbundanceRequest ar = new AbundanceRequest
                            {
                                Altitude     = v.altitude,
                                BodyId       = FlightGlobals.currentMainBody.flightGlobalsIndex,
                                CheckForLock = false,
                                Latitude     = v.latitude,
                                Longitude    = v.longitude,
                                ResourceType = HarvestTypes.Planetary,
                                ResourceName = m.ResourceName
                            };
                            getResourceFromList(resources, m.ResourceName).change   += (double)ResourceMap.Instance.GetAbundance(ar);
                            getResourceFromList(resources, "ElectricCharge").change -= 6;
                        }
                    }
                }

                // Life Support
                kerbals += v.GetCrewCount();
            }
            if (_usils)
            {
                getResourceFromList(resources, "Supplies").change       -= kerbals * 0.00005;
                getResourceFromList(resources, "Mulch").change          += kerbals * 0.00005;
                getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.01;
            }
            if (_tacls)
            {
                // TAC-LS consumption rates are a bit complex to calculate, so here is an approximated calculation where
                // - Kerbals on EVA are not handled
                // - BaseElectricityConsumptionRate is not taken into account
                getResourceFromList(resources, "Oxygen").change         -= kerbals * 0.001713537562385;
                getResourceFromList(resources, "Food").change           -= kerbals * 0.000016927083333;
                getResourceFromList(resources, "Water").change          -= kerbals * 0.000011188078704;
                getResourceFromList(resources, "CarbonDioxide").change  += kerbals * 0.00148012889876;
                getResourceFromList(resources, "Waste").change          += kerbals * 0.000001539351852;
                getResourceFromList(resources, "WasteWater").change     += kerbals * 0.000014247685185;
                getResourceFromList(resources, "ElectricCharge").change -= kerbals * 0.014166666666667;
                // Values are based on TAC-LS Version 0.11.1.20
            }
            // Consumption rates for Snacks are not calculated

            resources.Sort(new LogisticsResourceComparer());
            foreach (LogisticsResource r in resources)
            {
                GUILayout.Label(r.resourceName + ": " + numberToOut(r.amount, -1, false) + "/" + Math.Round(r.maxAmount, 5) + " (" + numberToOut(r.change, r.change > 0 ? r.maxAmount - r.amount : r.amount) + ")");
            }
        }
Example #21
0
  // called at every simulation step
  public void FixedUpdate()
  {
    // do nothing if paused
    if (Lib.IsPaused()) return;

    // do nothing if DB isn't ready
    if (!DB.Ready()) return;

    // for each vessel
    foreach(Vessel vessel in FlightGlobals.Vessels)
    {
      // skip invalid vessels
      if (!Lib.IsVessel(vessel)) continue;

      // skip loaded vessels
      if (vessel.loaded) continue;

      // get vessel info from the cache
      vessel_info info = Cache.VesselInfo(vessel);

      // calculate atmospheric factor (proportion of flux not blocked by atmosphere)
      double atmo_factor = Sim.AtmosphereFactor(vessel.mainBody, info.position, info.sun_dir);

      // for each part
      foreach(ProtoPartSnapshot part in vessel.protoVessel.protoPartSnapshots)
      {
        // get part prefab (required for module properties)
        Part part_prefab = PartLoader.getPartInfoByName(part.partName).partPrefab;

        // store index of ModuleResourceConverter to process
        // rationale: a part can contain multiple resource converters
        int converter_index = 0;

        // for each module
        foreach(ProtoPartModuleSnapshot module in part.modules)
        {
          // command module
          if (module.moduleName == "ModuleCommand")
          {
            // get module from prefab
            ModuleCommand command = part_prefab.Modules.GetModules<ModuleCommand>()[0];

            // do not consume if this is a MCM with no crew
            // rationale: for consistency, the game doesn't consume resources for MCM without crew in loaded vessels
            //            this make some sense: you left a vessel with some battery and nobody on board, you expect it to not consume EC
            if (command.minimumCrew == 0 || part.protoModuleCrew.Count > 0)
            {
              // for each input resource
              foreach(ModuleResource ir in command.inputResources)
              {
                // consume the resource
                Lib.RequestResource(vessel, ir.name, ir.rate * TimeWarp.fixedDeltaTime);
              }
            }
          }
          // solar panel
          else if (module.moduleName == "ModuleDeployableSolarPanel")
          {
            // determine if extended
            bool extended = module.moduleValues.GetValue("stateString") == ModuleDeployableSolarPanel.panelStates.EXTENDED.ToString();

            // if in sunlight and extended
            if (info.sunlight && extended)
            {
              // get module from prefab
              ModuleDeployableSolarPanel panel = part_prefab.Modules.GetModules<ModuleDeployableSolarPanel>()[0];

              // produce electric charge
              Lib.RequestResource(vessel, "ElectricCharge", -PanelOutput(vessel, part, panel, info.sun_dir, info.sun_dist, atmo_factor) * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
            }
          }
          // generator
          // note: assume generators require all input
          else if (module.moduleName == "ModuleGenerator")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("generatorIsActive"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleGenerator generator = part_prefab.Modules.GetModules<ModuleGenerator>()[0];

              // determine if vessel is full of all output resources
              bool full = true;
              foreach(var or in generator.outputList)
              {
                double amount = Lib.GetResourceAmount(vessel, or.name);
                double capacity = Lib.GetResourceCapacity(vessel, or.name);
                double perc = capacity > 0.0 ? amount / capacity : 0.0;
                full &= (perc >= 1.0 - double.Epsilon);
              }

              // if not full
              if (!full)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in generator.inputList)
                {
                  double required = ir.rate * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.name);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in generator.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.name, ir.rate * worst_input * TimeWarp.fixedDeltaTime);
                }

                // for each output resource
                foreach(var or in generator.outputList)
                {
                  // produce the resource
                  Lib.RequestResource(vessel, or.name, -or.rate * worst_input * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
                }
              }
            }
          }
          // converter
          // note: support multiple resource converters
          // note: ignore stock temperature mechanic of converters
          // note: ignore autoshutdown
          // note: ignore crew experience bonus (seem that stock ignore it too)
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          else if (module.moduleName == "ModuleResourceConverter")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleResourceConverter converter = part_prefab.Modules.GetModules<ModuleResourceConverter>()[converter_index++];

              // determine if vessel is full of all output resources
              bool full = true;
              foreach(var or in converter.outputList)
              {
                double amount = Lib.GetResourceAmount(vessel, or.ResourceName);
                double capacity = Lib.GetResourceCapacity(vessel, or.ResourceName);
                double perc = capacity > 0.0 ? amount / capacity : 0.0;
                full &= (perc >= converter.FillAmount - double.Epsilon);
              }

              // if not full
              if (!full)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in converter.inputList)
                {
                  double required = ir.Ratio * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.ResourceName);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in converter.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.ResourceName, ir.Ratio * worst_input * TimeWarp.fixedDeltaTime);
                }

                // for each output resource
                foreach(var or in converter.outputList)
                {
                  // produce the resource
                  Lib.RequestResource(vessel, or.ResourceName, -or.Ratio * worst_input * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
                }
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // drill
          // note: ignore stock temperature mechanic of harvesters
          // note: ignore autoshutdown
          // note: ignore depletion (stock seem to do the same)
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          else if (module.moduleName == "ModuleResourceHarvester")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleResourceHarvester harvester = part_prefab.Modules.GetModules<ModuleResourceHarvester>()[0];

              // deduce crew bonus
              double experience_bonus = 0.0;
              if (harvester.UseSpecialistBonus)
              {
                foreach(ProtoCrewMember c in vessel.protoVessel.GetVesselCrew())
                {
                  experience_bonus = Math.Max(experience_bonus, (c.trait == harvester.Specialty) ? (double)c.experienceLevel : 0.0);
                }
              }
              double crew_bonus = harvester.SpecialistBonusBase + (experience_bonus + 1.0) * harvester.SpecialistEfficiencyFactor;

              // detect amount of ore in the ground
              AbundanceRequest request = new AbundanceRequest
              {
                Altitude = vessel.altitude,
                BodyId = vessel.mainBody.flightGlobalsIndex,
                CheckForLock = false,
                Latitude = vessel.latitude,
                Longitude = vessel.longitude,
                ResourceType = (HarvestTypes)harvester.HarvesterType,
                ResourceName = harvester.ResourceName
              };
              double abundance = ResourceMap.Instance.GetAbundance(request);

              // if there is actually something (should be if active when unloaded)
              if (abundance > harvester.HarvestThreshold)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in harvester.inputList)
                {
                  double required = ir.Ratio * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.ResourceName);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in harvester.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.ResourceName, ir.Ratio * worst_input * TimeWarp.fixedDeltaTime);
                }

                // determine resource produced
                double res = abundance * harvester.Efficiency * crew_bonus * worst_input * Malfunction.Penalty(part);

                // accumulate ore
                Lib.RequestResource(vessel, harvester.ResourceName, -res * TimeWarp.fixedDeltaTime);
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // asteroid drill
          // note: untested
          // note: ignore stock temperature mechanic of asteroid drills
          // note: ignore autoshutdown
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          else if (module.moduleName == "ModuleAsteroidDrill")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleAsteroidDrill asteroid_drill = part_prefab.Modules.GetModules<ModuleAsteroidDrill>()[0];

              // deduce crew bonus
              double experience_bonus = 0.0;
              if (asteroid_drill.UseSpecialistBonus)
              {
                foreach(ProtoCrewMember c in vessel.protoVessel.GetVesselCrew())
                {
                  experience_bonus = Math.Max(experience_bonus, (c.trait == asteroid_drill.Specialty) ? (double)c.experienceLevel : 0.0);
                }
              }
              double crew_bonus = asteroid_drill.SpecialistBonusBase + (experience_bonus + 1.0) * asteroid_drill.SpecialistEfficiencyFactor;

              // get asteroid data
              ProtoPartModuleSnapshot asteroid_info = null;
              ProtoPartModuleSnapshot asteroid_resource = null;
              foreach(ProtoPartSnapshot p in vessel.protoVessel.protoPartSnapshots)
              {
                if (asteroid_info == null) asteroid_info = p.modules.Find(k => k.moduleName == "ModuleAsteroidInfo");
                if (asteroid_resource == null) asteroid_resource = p.modules.Find(k => k.moduleName == "ModuleAsteroidResource");
              }

              // if there is actually an asteroid attached to this active asteroid drill (it should)
              if (asteroid_info != null && asteroid_resource != null)
              {
                // get some data
                double mass_threshold = Convert.ToDouble(asteroid_info.moduleValues.GetValue("massThresholdVal"));
                double mass = Convert.ToDouble(asteroid_info.moduleValues.GetValue("currentMassVal"));
                double abundance = Convert.ToDouble(asteroid_resource.moduleValues.GetValue("abundance"));
                string res_name = asteroid_resource.moduleValues.GetValue("resourceName");
                double res_density = PartResourceLibrary.Instance.GetDefinition(res_name).density;

                // if asteroid isn't depleted
                if (mass > mass_threshold && abundance > double.Epsilon)
                {
                  // consume EC
                  double ec_required = asteroid_drill.PowerConsumption * TimeWarp.fixedDeltaTime;
                  double ec_consumed = Lib.RequestResource(vessel, "ElectricCharge", ec_required);
                  double ec_ratio = ec_consumed / ec_required;

                  // determine resource extracted
                  double res_amount = abundance * asteroid_drill.Efficiency * crew_bonus * ec_ratio * TimeWarp.fixedDeltaTime;

                  // produce mined resource
                  Lib.RequestResource(vessel, res_name, -res_amount);

                  // consume asteroid mass
                  asteroid_info.moduleValues.SetValue("currentMassVal", (mass - res_density * res_amount).ToString());
                }
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // SCANSAT support (new version)
          // TODO: enable better SCANsat support
          /*else if (module.moduleName == "SCANsat" || module.moduleName == "ModuleSCANresourceScanner")
          {
            // get ec consumption rate
            PartModule scansat = part_prefab.Modules[module.moduleName];
            double power = Lib.ReflectionValue<float>(scansat, "power");
            double ec_required = power * TimeWarp.fixedDeltaTime;

            // if it was scanning
            if (SCANsat.wasScanning(module))
            {
              // if there is enough ec
              double ec_amount = Lib.GetResourceAmount(vessel, "ElectricCharge");
              double ec_capacity = Lib.GetResourceCapacity(vessel, "ElectricCharge");
              if (ec_capacity > double.Epsilon && ec_amount / ec_capacity > 0.15) //< re-enable at 15% EC
              {
                // re-enable the scanner
                SCANsat.resumeScanner(vessel, module, part_prefab);

                // give the user some feedback
                if (DB.VesselData(vessel.id).cfg_ec == 1)
                  Message.Post(Severity.relax, "SCANsat> sensor on <b>" + vessel.vesselName + "</b> resumed operations", "we got enough ElectricCharge");
              }
            }

            // if it is scanning
            if (SCANsat.isScanning(module))
            {
              // consume ec
              double ec_consumed = Lib.RequestResource(vessel, "ElectricCharge", ec_required);

              // if there isn't enough ec
              if (ec_consumed < ec_required * 0.99 && ec_required > double.Epsilon)
              {
                // unregister scanner, and remember it
                SCANsat.stopScanner(vessel, module, part_prefab);

                // give the user some feedback
                if (DB.VesselData(vessel.id).cfg_ec == 1)
                  Message.Post(Severity.warning, "SCANsat sensor was disabled on <b>" + vessel.vesselName + "</b>", "for lack of ElectricCharge");
              }
            }
          }*/
          // SCANSAT support (old version)
          // note: this one doesn't support re-activation, is a bit slower and less clean
          //       waiting for DMagic to fix a little bug
          else if (module.moduleName == "SCANsat" || module.moduleName == "ModuleSCANresourceScanner")
          {
            // determine if scanning
            bool scanning = Convert.ToBoolean(module.moduleValues.GetValue("scanning"));

            // consume ec
            if (scanning)
            {
              // get ec consumption
              PartModule scansat = part_prefab.Modules[module.moduleName];
              double power = Lib.ReflectionValue<float>(scansat, "power");

              // consume ec
              double ec_required = power * TimeWarp.fixedDeltaTime;
              double ec_consumed = Lib.RequestResource(vessel, "ElectricCharge", ec_required);

              // if there isn't enough ec
              if (ec_consumed < ec_required * 0.99 && ec_required > double.Epsilon)
              {
                // unregister scanner using reflection
                foreach(var a in AssemblyLoader.loadedAssemblies)
                {
                  if (a.name == "SCANsat")
                  {
                    Type controller_type = a.assembly.GetType("SCANsat.SCANcontroller");
                    System.Object controller = controller_type.GetProperty("controller", BindingFlags.Public | BindingFlags.Static).GetValue(null, null);
                    controller_type.InvokeMember("removeVessel", BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance, null, controller, new System.Object[]{vessel});
                  }
                }

                // disable scanning
                module.moduleValues.SetValue("scanning", false.ToString());

                // give the user some feedback
                if (DB.VesselData(vessel.id).cfg_ec == 1)
                  Message.Post(Severity.warning, "SCANsat sensor was disabled on <b>" + vessel.vesselName + "</b>", "for lack of ElectricCharge");
              }
            }
          }
          // NearFutureSolar support
          // note: we assume deployed, this is a current limitation
          else if (module.moduleName == "ModuleCurvedSolarPanel")
          {
            // [unused] determine if extended
            //string state = module.moduleValues.GetValue("SavedState");
            //bool extended = state == ModuleDeployableSolarPanel.panelStates.EXTENDED.ToString();

            // if in sunlight
            if (info.sunlight)
            {
              // produce electric charge
              double output = CurvedPanelOutput(vessel, part, part_prefab, info.sun_dir, info.sun_dist, atmo_factor) * Malfunction.Penalty(part);
              Lib.RequestResource(vessel, "ElectricCharge", -output * TimeWarp.fixedDeltaTime);
            }
          }
          // KERBALISM modules
          else if (module.moduleName == "Scrubber") { Scrubber.BackgroundUpdate(vessel, part.flightID); }
          else if (module.moduleName == "Greenhouse") { Greenhouse.BackgroundUpdate(vessel, part.flightID); }
          else if (module.moduleName == "Malfunction") { Malfunction.BackgroundUpdate(vessel, part.flightID); }
        }
      }
    }
  }
Example #22
0
        protected string getAbundance(string resourceName)
        {
            AbundanceRequest request = new AbundanceRequest();
            double lattitude = ResourceUtilities.Deg2Rad(this.part.vessel.latitude);
            double longitude = ResourceUtilities.Deg2Rad(this.part.vessel.longitude);

            request.BiomeName = Utils.GetCurrentBiome(this.part.vessel).name;
            request.BodyId = this.part.vessel.mainBody.flightGlobalsIndex;
            request.Longitude = longitude;
            request.Latitude = lattitude;
            request.CheckForLock = true;
            request.ResourceName = resourceName;

            float abundance = ResourceMap.Instance.GetAbundance(request) * 100.0f;

            if (abundance > 0.001)
                return string.Format("{0:f2}%", abundance);
            else
                return "Unknown";
        }
Example #23
0
        public static void updateNetworkResources(double dt)
        {
           // print("updateNwres " + dt);
            //if (dt < 0)
                return;
            dt *= 4;
            if(currentPipe == 0)
            {
               // print("update vessels!");
                foreach(Vessel v in myNetwork)
                {
                    if (v.loaded)
                        continue; //ignore loaded vessel
                    //only generators will be simulated!  Must add generators from all known mods!
                    //everyone is different too!
                    //supported generators will be processed in real time, unsupported will not
                    
                    foreach(var part in v.protoVessel.protoPartSnapshots)
                    {



                        ConfigNode node = findPartConfig(part.partName);
                        if (node == null)
                            continue;
                        // print(node);
                        var modules = node.GetNodes("MODULE");
                      
                        int moduleID = 0;

                        //solar power efficiency boost:
                        double solarOut = 0;
                        double panelAltitude = v.mainBody.RevealAltitude();
                        double sunMultiplier = sunScale(v, out panelAltitude);
                        bool hasSolar = false;
                        double altitudeMultiplier = 0;
                        double chargeRate = 0;
                        string solarResourceName = "ElectricCharge";

                        foreach(var module in part.modules)
                        {
                           // print("module id " + moduleID);
                            if (moduleID > modules.Length) //found unexpected module!... there won't be any new generators here
                                continue; 
                            
                           switch(module.moduleName)
                           {
                               case "ModuleGenerator":
                                   
                                   {
                                       try { 
                                      // print("found ModuleGenerator" + moduleID.ToString());
                                       ConfigNode nonPersistantValues = modules[moduleID];
                                       var outputResource = nonPersistantValues.GetNode("OUTPUT_RESOURCE");
                                       var inputResource = nonPersistantValues.GetNode("INPUT_RESOURCE");
                                       string resource = outputResource.GetValue("name");
                                       double rate = double.Parse(outputResource.GetValue("rate"));
                                      
                                       string iResource = "";
                                       double iRate = 0;
                                           if(inputResource != null)
                                           {
                                               iResource = inputResource.GetValue("name");
                                               iRate = double.Parse(inputResource.GetValue("rate"));
                                               double input = networkResourceRequest(v, iResource, iRate * dt);
                                               double iScale = input / (iRate * dt);

                                               double output = networkResourceRequest(v, resource, -rate * iScale * dt);
                                               double oscale = output / (-rate * iScale * dt);
                                               double irefund = input * (1 - oscale);
                                               networkResourceRequest(v, iResource, irefund);

                                           }
                                           
                                           }
                                       catch
                                       {
                                           print("Failed to update ModuleGenerator module, check for updates");
                                       }
                                           
                                   }
                                   break;
                              // case "KolonyConverter":
                               case "REGO_ModuleResourceConverter":
                               case "REGO_ModuleResourceHarvester":
                                   {
                                       try
                                       {
                                           ConfigNode nonPersistantValues = modules[moduleID];
                                           string recipeInputs = nonPersistantValues.GetValue("RecipeInputs");
                                           string recipeOutputs = nonPersistantValues.GetValue("RecipeOutputs");
                                           double groundEfficiency = 1;
                                           if(module.moduleName == "REGO_ModuleResourceHarvester")
                                           {
                                               string resourcename = nonPersistantValues.GetValue("ResourceName");
                                               recipeOutputs = resourcename + ",1";
                                               var abRequest = new AbundanceRequest
                                               {
                                                   Altitude = v.altitude,
                                                   BodyId = FlightGlobals.currentMainBody.flightGlobalsIndex,
                                                   CheckForLock = false,
                                                   Latitude = v.latitude,
                                                   Longitude = v.longitude,
                                                   ResourceType = (HarvestTypes)0,
                                                   ResourceName = resourcename
                                               };
                                               var abundance = ResourceMap.Instance.GetAbundance(abRequest);
                                               groundEfficiency = abundance;
                                           }

                                           string RequiredResources = nonPersistantValues.GetValue("RequiredResources");
                                           if (recipeInputs == null) recipeInputs = "";
                                           if (recipeOutputs == null) recipeOutputs = "";
                                           if (RequiredResources == null) RequiredResources = "";
                                          // print(recipeInputs);
                                          // print(recipeOutputs);
                                          // print(RequiredResources);

                                           string isEnabled = module.moduleValues.GetValue("IsActivated");
                                           double efficiency = double.Parse(module.moduleValues.GetValue("EfficiencyBonus"));
                                          
                                           bool harvesterOK = true;
                                           
                                           if (isEnabled.ToLower() == "true" && harvesterOK)
                                           {
                                               var localdelta = processRegolithGenerator(v, dt * efficiency * groundEfficiency, recipeInputs, recipeOutputs, RequiredResources);
                                               foreach (string k in localdelta.Keys)
                                                   networkResourceRequest(v, k, -localdelta[k]);
                                           }
                                           module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
                                           /*
                                            * Regolith generators use these 
                                            isEnabled = True
                                            EfficiencyBonus = 1
                                            IsActivated = False
                                            DirtyFlag = False
                                            lastUpdateTime = 49904539.6623243
                                            */
                                       }
                                       catch (Exception exc)
                                       {
                                           print("Failed to update regolith module, check for updates:" + exc.ToString());
                                       }
                                   }
                                   break;
                               case "NetworkBroker2":
                                   {
                                       //network broker tries to take network input from the network.
                                      // print("found NetworkBroker2");
                                       try {
                                           ConfigNode nonPersistantValues = modules[moduleID];

                                           string NetworkInput = nonPersistantValues.GetValue("NetworkInput");
                                           string isEnabled = module.moduleValues.GetValue("IsActivated");
                                           bool IsActivated = bool.Parse(isEnabled);

                                           string[] NWIn = NetworkInput.Split(',');
                                           double inputRequest = double.Parse(NWIn[1]) * dt;
                                          string NetworkResource = NWIn[0];
                                          double NetworkDraw = 0;
                                           if (/*connected*/true && IsActivated && inputRequest > 0)
                                           {

                                               double nwdraw = xPipeLine2.fullNetworkRequest(v, NetworkResource, inputRequest);
                                               NetworkDraw = nwdraw / dt;
                                               double stored = xPipeLine2.networkResourceRequest(v,NWIn[0], -nwdraw);
                                               double excess = nwdraw + stored;
                                              // print("NetworkBroker2 " + nwdraw.ToString() + " store " + stored.ToString() + " excess " + excess.ToString());
                                               xPipeLine2.fullNetworkRequest(v, NWIn[0], -excess);
                                           }
                                       }
                                       catch
                                       {
                                           print("Failed to update NetworkBroker2 module, check for updates");
                                       }
                                   }
                                   break;
                               case "xPipeLine2": //update current time on pipes so regolith doesn't simulate them!
                                   {
                                       try {
                                           ConfigNode nonPersistantValues = modules[moduleID];
                                       module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
                                       }
                                       catch
                                       {
                                           print("Failed to update xPipeLine2 module, check for updates");
                                       }
                                   }
                                   break;
                               case "ModuleDeployableSolarPanel":
                                   {
                                       try
                                       {
                                           ConfigNode nonPersistantValues = modules[moduleID];
                                         
                                           bool sunTracking = true;
                                           if (!bool.TryParse(getNonPersistantValue(nonPersistantValues, "sunTracking"), out sunTracking))
                                               sunTracking = true; //squad doesn't mark suntracking on sun tracking panels!
                                           solarResourceName = getNonPersistantValue(nonPersistantValues, "resourceName");
                                           chargeRate += double.Parse(getNonPersistantValue(nonPersistantValues, "chargeRate"));
                                           ConfigNode cpowerCurve = nonPersistantValues.GetNode("powerCurve");
                                           string[] keys = cpowerCurve.GetValues("key");

                                           powerCurveFunction func = new powerCurveFunction();
                                           func.setFunction(keys);
                                          
                                           double multiplier = func.getMultiplier(panelAltitude);
                                           if(!hasSolar)
                                           {
                                               altitudeMultiplier = multiplier;
                                           }
                                           multiplier *= sunMultiplier; //simple half duty cycle for unfocused solar panels
                                           solarOut++;
                                           /*MODULE
                                            {
                                                name = ModuleDeployableSolarPanel

                                                sunTracking = false

                                                raycastTransformName = suncatcher
                                                pivotName = suncatcher

                                                isBreakable = false

                                                resourceName = ElectricCharge

                                                chargeRate = 0.75

                                                powerCurve
                                                {
                                                    key = 206000000000 0 0 0
                                                    key = 13599840256 1 0 0
                                                    key = 68773560320 0.5 0 0
                                                    key = 0 10 0 0
                                                }
                                            }*/
                                       }
                                       catch (Exception exc)
                                       {
                                           print("Failed to update solar module, check for updates" + exc.ToString());
                                       }
                                   }
                                   break;
                               default:
                                   break;
                           }

                           moduleID++;        
                        }
                        if(hasSolar)
                        {
                            networkResourceRequest(v, solarResourceName, -chargeRate * dt * altitudeMultiplier * sunMultiplier);
                        }
                    }
                }

               
            }
            currentPipe++;
            if (currentPipe > pipeCount)
                currentPipe = 0;
            

        }
Example #24
0
  // called at every simulation step
  public void FixedUpdate()
  {
    // do nothing if paused
    if (Lib.IsPaused()) return;

    // do nothing if DB isn't ready
    if (!DB.Ready()) return;

    // for each vessel
    foreach(Vessel vessel in FlightGlobals.Vessels)
    {
      // skip invalid vessels
      if (!Lib.IsVessel(vessel)) continue;

      // skip loaded vessels
      if (vessel.loaded) continue;

      // get vessel data from the db
      vessel_data vd = DB.VesselData(vessel.id);

      // get vessel info from the cache
      vessel_info info = Cache.VesselInfo(vessel);

      // calculate atmospheric factor (proportion of flux not blocked by atmosphere)
      double atmo_factor = Sim.AtmosphereFactor(vessel.mainBody, info.position, info.sun_dir);

      // for each part
      foreach(ProtoPartSnapshot part in vessel.protoVessel.protoPartSnapshots)
      {
        // get part prefab (required for module properties)
        Part part_prefab = PartLoader.getPartInfoByName(part.partName).partPrefab;

        // store index of ModuleResourceConverter to process
        // rationale: a part can contain multiple resource converters
        int converter_index = 0;

        // for each module
        foreach(ProtoPartModuleSnapshot module in part.modules)
        {
          // something weird is going on, skip this
          if (!part_prefab.Modules.Contains(module.moduleName)) continue;

          // command module
          if (module.moduleName == "ModuleCommand")
          {
            // get module from prefab
            ModuleCommand command = part_prefab.Modules.GetModules<ModuleCommand>()[0];

            // do not consume if this is a MCM with no crew
            // rationale: for consistency, the game doesn't consume resources for MCM without crew in loaded vessels
            //            this make some sense: you left a vessel with some battery and nobody on board, you expect it to not consume EC
            if (command.minimumCrew == 0 || part.protoModuleCrew.Count > 0)
            {
              // for each input resource
              foreach(ModuleResource ir in command.inputResources)
              {
                // consume the resource
                Lib.RequestResource(vessel, ir.name, ir.rate * TimeWarp.fixedDeltaTime);
              }
            }
          }
          // solar panel
          else if (module.moduleName == "ModuleDeployableSolarPanel")
          {
            // determine if extended
            bool extended = module.moduleValues.GetValue("stateString") == ModuleDeployableSolarPanel.panelStates.EXTENDED.ToString();

            // if in sunlight and extended
            if (info.sunlight && extended)
            {
              // get module from prefab
              ModuleDeployableSolarPanel panel = part_prefab.Modules.GetModules<ModuleDeployableSolarPanel>()[0];

              // produce electric charge
              Lib.RequestResource(vessel, "ElectricCharge", -PanelOutput(vessel, part, panel, info.sun_dir, info.sun_dist, atmo_factor) * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
            }
          }
          // generator
          // note: assume generators require all input
          else if (module.moduleName == "ModuleGenerator")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("generatorIsActive"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleGenerator generator = part_prefab.Modules.GetModules<ModuleGenerator>()[0];

              // determine if vessel is full of all output resources
              bool full = true;
              foreach(var or in generator.outputList)
              {
                double amount = Lib.GetResourceAmount(vessel, or.name);
                double capacity = Lib.GetResourceCapacity(vessel, or.name);
                double perc = capacity > 0.0 ? amount / capacity : 0.0;
                full &= (perc >= 1.0 - double.Epsilon);
              }

              // if not full
              if (!full)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in generator.inputList)
                {
                  double required = ir.rate * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.name);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in generator.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.name, ir.rate * worst_input * TimeWarp.fixedDeltaTime);
                }

                // for each output resource
                foreach(var or in generator.outputList)
                {
                  // produce the resource
                  Lib.RequestResource(vessel, or.name, -or.rate * worst_input * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
                }
              }
            }
          }
          // converter
          // note: support multiple resource converters
          // note: ignore stock temperature mechanic of converters
          // note: ignore autoshutdown
          // note: ignore crew experience bonus (seem that stock ignore it too)
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          // note: support PlanetaryBaseSystem converters
          // note: support NearFuture reactors
          else if (module.moduleName == "ModuleResourceConverter" || module.moduleName == "ModuleKPBSConverter" || module.moduleName == "FissionReactor")
          {
            // get module from prefab
            ModuleResourceConverter converter = part_prefab.Modules.GetModules<ModuleResourceConverter>()[converter_index++];

            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // determine if vessel is full of all output resources
              bool full = true;
              foreach(var or in converter.outputList)
              {
                double amount = Lib.GetResourceAmount(vessel, or.ResourceName);
                double capacity = Lib.GetResourceCapacity(vessel, or.ResourceName);
                double perc = capacity > 0.0 ? amount / capacity : 0.0;
                full &= (perc >= converter.FillAmount - double.Epsilon);
              }

              // if not full
              if (!full)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in converter.inputList)
                {
                  double required = ir.Ratio * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.ResourceName);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in converter.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.ResourceName, ir.Ratio * worst_input * TimeWarp.fixedDeltaTime);
                }

                // for each output resource
                foreach(var or in converter.outputList)
                {
                  // produce the resource
                  Lib.RequestResource(vessel, or.ResourceName, -or.Ratio * worst_input * TimeWarp.fixedDeltaTime * Malfunction.Penalty(part));
                }
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // drill
          // note: ignore stock temperature mechanic of harvesters
          // note: ignore autoshutdown
          // note: ignore depletion (stock seem to do the same)
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          else if (module.moduleName == "ModuleResourceHarvester")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleResourceHarvester harvester = part_prefab.Modules.GetModules<ModuleResourceHarvester>()[0];

              // [disabled] reason: not working
              // deduce crew bonus
              /*double experience_bonus = 0.0;
              if (harvester.UseSpecialistBonus)
              {
                foreach(ProtoCrewMember c in vessel.protoVessel.GetVesselCrew())
                {
                  experience_bonus = Math.Max(experience_bonus, (c.trait == harvester.Specialty) ? (double)c.experienceLevel : 0.0);
                }
              }*/
              const double crew_bonus = 1.0; //harvester.SpecialistBonusBase + (experience_bonus + 1.0) * harvester.SpecialistEfficiencyFactor;

              // detect amount of ore in the ground
              AbundanceRequest request = new AbundanceRequest
              {
                Altitude = vessel.altitude,
                BodyId = vessel.mainBody.flightGlobalsIndex,
                CheckForLock = false,
                Latitude = vessel.latitude,
                Longitude = vessel.longitude,
                ResourceType = (HarvestTypes)harvester.HarvesterType,
                ResourceName = harvester.ResourceName
              };
              double abundance = ResourceMap.Instance.GetAbundance(request);

              // if there is actually something (should be if active when unloaded)
              if (abundance > harvester.HarvestThreshold)
              {
                // calculate worst required resource percentual
                double worst_input = 1.0;
                foreach(var ir in harvester.inputList)
                {
                  double required = ir.Ratio * TimeWarp.fixedDeltaTime;
                  double amount = Lib.GetResourceAmount(vessel, ir.ResourceName);
                  worst_input = Math.Min(worst_input, amount / required);
                }

                // for each input resource
                foreach(var ir in harvester.inputList)
                {
                  // consume the resource
                  Lib.RequestResource(vessel, ir.ResourceName, ir.Ratio * worst_input * TimeWarp.fixedDeltaTime);
                }

                // determine resource produced
                double res = abundance * harvester.Efficiency * crew_bonus * worst_input * Malfunction.Penalty(part);

                // accumulate ore
                Lib.RequestResource(vessel, harvester.ResourceName, -res * TimeWarp.fixedDeltaTime);
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // asteroid drill
          // note: untested
          // note: ignore stock temperature mechanic of asteroid drills
          // note: ignore autoshutdown
          // note: 'undo' stock behaviour by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation)
          else if (module.moduleName == "ModuleAsteroidDrill")
          {
            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              // get module from prefab
              ModuleAsteroidDrill asteroid_drill = part_prefab.Modules.GetModules<ModuleAsteroidDrill>()[0];

              // [disabled] reason: not working
              // deduce crew bonus
              /*double experience_bonus = 0.0;
              if (asteroid_drill.UseSpecialistBonus)
              {
                foreach(ProtoCrewMember c in vessel.protoVessel.GetVesselCrew())
                {
                  experience_bonus = Math.Max(experience_bonus, (c.trait == asteroid_drill.Specialty) ? (double)c.experienceLevel : 0.0);
                }
              }*/
              const double crew_bonus = 1.0; //asteroid_drill.SpecialistBonusBase + (experience_bonus + 1.0) * asteroid_drill.SpecialistEfficiencyFactor;

              // get asteroid data
              ProtoPartModuleSnapshot asteroid_info = null;
              ProtoPartModuleSnapshot asteroid_resource = null;
              foreach(ProtoPartSnapshot p in vessel.protoVessel.protoPartSnapshots)
              {
                if (asteroid_info == null) asteroid_info = p.modules.Find(k => k.moduleName == "ModuleAsteroidInfo");
                if (asteroid_resource == null) asteroid_resource = p.modules.Find(k => k.moduleName == "ModuleAsteroidResource");
              }

              // if there is actually an asteroid attached to this active asteroid drill (it should)
              if (asteroid_info != null && asteroid_resource != null)
              {
                // get some data
                double mass_threshold = Convert.ToDouble(asteroid_info.moduleValues.GetValue("massThresholdVal"));
                double mass = Convert.ToDouble(asteroid_info.moduleValues.GetValue("currentMassVal"));
                double abundance = Convert.ToDouble(asteroid_resource.moduleValues.GetValue("abundance"));
                string res_name = asteroid_resource.moduleValues.GetValue("resourceName");
                double res_density = PartResourceLibrary.Instance.GetDefinition(res_name).density;

                // if asteroid isn't depleted
                if (mass > mass_threshold && abundance > double.Epsilon)
                {
                  // consume EC
                  double ec_required = asteroid_drill.PowerConsumption * TimeWarp.fixedDeltaTime;
                  double ec_consumed = Lib.RequestResource(vessel, "ElectricCharge", ec_required);
                  double ec_ratio = ec_consumed / ec_required;

                  // determine resource extracted
                  double res_amount = abundance * asteroid_drill.Efficiency * crew_bonus * ec_ratio * TimeWarp.fixedDeltaTime;

                  // produce mined resource
                  Lib.RequestResource(vessel, res_name, -res_amount);

                  // consume asteroid mass
                  asteroid_info.moduleValues.SetValue("currentMassVal", (mass - res_density * res_amount).ToString());
                }
              }

              // undo stock behaviour by forcing last_update_time to now
              module.moduleValues.SetValue("lastUpdateTime", Planetarium.GetUniversalTime().ToString());
            }
          }
          // science lab
          // note: we are only simulating the EC consumption
          // note: there is no easy way to 'stop' the lab when there isn't enough EC
          else if (module.moduleName == "ModuleScienceConverter")
          {
            // get module from prefab
            ModuleScienceConverter lab = part_prefab.Modules.GetModules<ModuleScienceConverter>()[0];

            // determine if active
            bool activated = Convert.ToBoolean(module.moduleValues.GetValue("IsActivated"));

            // if active
            if (activated)
            {
              Lib.RequestResource(vessel, "ElectricCharge", lab.powerRequirement * TimeWarp.fixedDeltaTime);
            }
          }
          // SCANSAT support
          else if (module.moduleName == "SCANsat" || module.moduleName == "ModuleSCANresourceScanner")
          {
            // get ec consumption rate
            PartModule scansat = part_prefab.Modules[module.moduleName];
            double power = Lib.ReflectionValue<float>(scansat, "power");
            double ec_required = power * TimeWarp.fixedDeltaTime;
            bool is_scanning = Lib.GetProtoValue<bool>(module, "scanning");
            bool was_disabled = vd.scansat_id.Contains(part.flightID);

            // if its scanning
            if (Lib.GetProtoValue<bool>(module, "scanning"))
            {
              // consume ec
              double ec_consumed = Lib.RequestResource(vessel, "ElectricCharge", ec_required);

              // if there isn't enough ec
              if (ec_consumed < ec_required * 0.99 && ec_required > double.Epsilon)
              {
                // unregister scanner
                SCANsat.stopScanner(vessel, module, part_prefab);

                // remember disabled scanner
                vd.scansat_id.Add(part.flightID);

                // give the user some feedback
                if (DB.VesselData(vessel.id).cfg_ec == 1)
                  Message.Post("SCANsat sensor was disabled on <b>" + vessel.vesselName + "</b>");
              }
            }
            // if it was disabled
            else if (vd.scansat_id.Contains(part.flightID))
            {
              // if there is enough ec
              double ec_amount = Lib.GetResourceAmount(vessel, "ElectricCharge");
              double ec_capacity = Lib.GetResourceCapacity(vessel, "ElectricCharge");
              if (ec_capacity > double.Epsilon && ec_amount / ec_capacity > 0.25) //< re-enable at 25% EC
              {
                // re-enable the scanner
                SCANsat.resumeScanner(vessel, module, part_prefab);

                // give the user some feedback
                if (DB.VesselData(vessel.id).cfg_ec == 1)
                  Message.Post("SCANsat sensor resumed operations on <b>" + vessel.vesselName + "</b>");
              }
            }

            // forget active scanners
            if (Lib.GetProtoValue<bool>(module, "scanning")) vd.scansat_id.Remove(part.flightID);
          }
          // NearFutureSolar support
          // note: we assume deployed, this is a current limitation
          else if (module.moduleName == "ModuleCurvedSolarPanel")
          {
            // if in sunlight
            if (info.sunlight)
            {
              PartModule curved_panel = part_prefab.Modules[module.moduleName];
              double output = CurvedPanelOutput(vessel, part, part_prefab, curved_panel, info.sun_dir, info.sun_dist, atmo_factor) * Malfunction.Penalty(part);
              Lib.RequestResource(vessel, "ElectricCharge", -output * TimeWarp.fixedDeltaTime);
            }
          }
          // NearFutureElectrical support
          // note: fission generator ignore heat
          // note: radioisotope generator doesn't support easy mode
          else if (module.moduleName == "FissionGenerator")
          {
            PartModule generator = part_prefab.Modules[module.moduleName];
            double power = Lib.ReflectionValue<float>(generator, "PowerGeneration");

            // get fission reactor tweakable, will default to 1.0 for other modules
            var reactor = part.modules.Find(k => k.moduleName == "FissionReactor");
            double tweakable = reactor == null ? 1.0 : Lib.ConfigValue(reactor.moduleValues, "CurrentPowerPercent", 100.0) * 0.01;
            Lib.RequestResource(vessel, "ElectricCharge", -power * tweakable * TimeWarp.fixedDeltaTime);
          }
          else if (module.moduleName == "ModuleRadioisotopeGenerator")
          {
            double mission_time = vessel.missionTime / (3600.0 * Lib.HoursInDay() * Lib.DaysInYear());
            PartModule generator = part_prefab.Modules[module.moduleName];
            double half_life = Lib.ReflectionValue<float>(generator, "HalfLife");
            double remaining = Math.Pow(2.0, (-mission_time) / half_life);
            double power = Lib.ReflectionValue<float>(generator, "BasePower");
            Lib.RequestResource(vessel, "ElectricCharge", -power * remaining * TimeWarp.fixedDeltaTime);
          }
          // KERBALISM modules
          else if (module.moduleName == "Scrubber") { Scrubber.BackgroundUpdate(vessel, part.flightID); }
          else if (module.moduleName == "Greenhouse") { Greenhouse.BackgroundUpdate(vessel, part.flightID); }
          else if (module.moduleName == "GravityRing") { GravityRing.BackgroundUpdate(vessel, part.flightID); }
          else if (module.moduleName == "Malfunction") { Malfunction.BackgroundUpdate(vessel, part.flightID); }
        }
      }
    }
  }
Example #25
0
        public static Dictionary <string, int> GetResourceAbundance(
            int bodyIndex,
            double altitude,
            double latitude,
            double longitude,
            HarvestTypes[] harvestTypes,
            Configuration config,
            bool forHomeworld = false)
        {
            if (config == null)
            {
                config = new Configuration();
            }

            if (config.AllowedHarvestableResources == null ||
                config.AllowedHarvestableResources.Count < 1)
            {
                config.SetHarvestableResources("");
            }

            var allowedResources = forHomeworld
                ? config.AllowedHarvestableResourcesOnHomeworld
                : config.AllowedHarvestableResources;
            var abundanceRequest = new AbundanceRequest
            {
                Altitude     = altitude,
                BodyId       = bodyIndex,
                CheckForLock = false,
                Latitude     = latitude,
                Longitude    = longitude
            };
            var radiusMultiplier = Math.Sqrt(FlightGlobals.Bodies[bodyIndex].Radius) / RESOURCE_ABUNDANCE_RADIUS_MULT;
            var bodyMultiplier   = 5;

            if (!FlightGlobals.currentMainBody.isHomeWorld)
            {
                bodyMultiplier = Math.Max(5, WOLF_GameParameters.ResourceAbundanceMultiplierValue);
            }

            var resourceList = new Dictionary <string, int>();

            foreach (var harvestType in harvestTypes.Distinct())
            {
                abundanceRequest.ResourceType = harvestType;

                var harvestableResources = ResourceMap.Instance.FetchAllResourceNames(harvestType);
                foreach (var resource in harvestableResources)
                {
                    abundanceRequest.ResourceName = resource;

                    var baseAbundance = ResourceMap.Instance.GetAbundance(abundanceRequest);
                    int abundance     = (int)Math.Round(
                        baseAbundance * RESOURCE_ABUNDANCE_MULTIPLIER * radiusMultiplier * bodyMultiplier,
                        MidpointRounding.AwayFromZero
                        );
                    if (abundance > RESOURCE_ABUNDANCE_FLOOR)
                    {
                        abundance = Math.Min(abundance, RESOURCE_ABUNDANCE_CEILING);
                    }
                    else
                    {
                        abundance = 0;
                    }

                    // Make abundance a multiple of 5
                    if (abundance > 0 && abundance % 5 != 0)
                    {
                        abundance = 5 * (int)Math.Round(abundance / 5d, MidpointRounding.AwayFromZero);
                    }

                    if (allowedResources.Contains(resource))
                    {
                        var wolfResourceName = resource + WOLF_DepotModule.HARVESTABLE_RESOURCE_SUFFIX;
                        if (resourceList.ContainsKey(wolfResourceName))
                        {
                            resourceList[wolfResourceName] += abundance;
                        }
                        else
                        {
                            resourceList.Add(wolfResourceName, abundance);
                        }
                    }
                }
            }

            return(resourceList);
        }
Example #26
0
        public static float GetAbundance(AbundanceRequest request)
        {
            try
            {
                var northing = Utilities.Deg2Rad(Utilities.fixLat(request.Latitude));
                var easting = Utilities.Deg2Rad(Utilities.fixLong(request.Longitude));
                var body = FlightGlobals.Bodies.FirstOrDefault(b => b.flightGlobalsIndex == request.BodyId);
                var biome = Utilities.GetBiome(northing, easting, body);
                var seed = GenerateAbundanceSeed(request, biome, body);
                var biomeName = GetDefaultSituation(request.ResourceType);
                if (biome != null)
                {
                    biomeName = biome.name;
                }

                //We need to determine our data set for randomization.
                //Is there biome data?
                DistributionData distro = null;
                var biomeConfigs = BiomeResources.Where(
                        r => r.PlanetName == body.bodyName
                             && r.BiomeName == biomeName
                             && r.ResourceName == request.ResourceName
                             && r.ResourceType == (int)request.ResourceType).ToList();
                var planetConfigs =
                    PlanetaryResources.Where(
                        r => r.PlanetName == body.bodyName
                             && r.ResourceName == request.ResourceName
                             && r.ResourceType == (int)request.ResourceType).ToList();
                var globalConfigs =
                    GlobalResources.Where(
                        r => r.ResourceName == request.ResourceName
                             && r.ResourceType == (int)request.ResourceType).ToList();
                //Extrapolate based on matching overrides
                if (biomeConfigs.Any())
                {
                    distro = GetBestResourceData(biomeConfigs);
                    seed *= 2;
                }
                else if (planetConfigs.Any())
                {
                    distro = GetBestResourceData(planetConfigs);
                    seed *= 3;
                }
                else if (globalConfigs.Any())
                {
                    distro = GetBestResourceData(globalConfigs);
                    seed *= 4;
                }
                else
                {
                    return 0f;
                }

                var rand = new Random(seed);
                //Our Simplex noise:
                var noiseSeed = new int[8];
                for (var ns = 0; ns < 8; ns++)
                {
                    noiseSeed[ns] = rand.Next();
                }
                var spx = new NoiseGenerator(noiseSeed);
                var noiseX = (float) northing * distro.Variance / 10f;
                var noiseY = (float)easting * distro.Variance / 10f;
                var noiseZ = (rand.Next(100)) / 100f;
                var noise = spx.noise(noiseX, noiseY, noiseZ);

                var presenceRoll = rand.Next(100);
                var isPresent = (presenceRoll <= distro.PresenceChance);
                if (!isPresent)
                    return 0f;

                //Abundance begins with a starting range.
                var min = (int)(distro.MinAbundance * 1000);
                var max = (int)(distro.MaxAbundance * 1000);
                //In case someone is silly
                if (min > max)
                    max = min + 1;
                var abundance = (rand.Next(min, max))/1000f;
                var baseAbuncance = abundance;
                var minAbundance = Math.Max(0.01f,min)/1000f;

                //Applies to all but interplanetary
                if (request.ResourceType != HarvestTypes.Interplanetary)
                {
                    //Lets add some noise...
                    float swing = abundance*(distro.Variance/100f);
                    abundance = abundance - swing + (swing*noise*2);
                    //You should only be able to hit zero if someohe sets their
                    //variance >= 100
                    if (abundance < 0)
                        abundance = 0;
                }
                //Altitude band - only applies to atmospheric and interplanetary
                if (
                    (request.ResourceType == HarvestTypes.Atmospheric || request.ResourceType == HarvestTypes.Interplanetary)
                    && distro.HasVariableAltitude())
                {
                    var rad = body.Radius;
                    var ideal = ((rad*distro.MinAltitude) + (rad*distro.MaxAltitude))/2;
                    //print("REGO: IDEAL = " + ideal);
                    var range = rand.Next((int)(rad * distro.MinRange), (int)(rad * distro.MaxRange));
                    var diff = Math.Abs(ideal - request.Altitude);
                    var rangePerc = diff / range;
                    var modifier = 1d - rangePerc;
                    abundance *= (float)modifier;
                }

                if (abundance <= Utilities.FLOAT_TOLERANCE)
                    return 0f;

                //Now for our return scenarios.
                var trueAbundance = abundance / 100;
                baseAbuncance = baseAbuncance / 100;
                minAbundance = minAbundance / 100;

                //Biome unlocked or no lock check
                if (!request.CheckForLock || RegolithScenario.Instance.gameSettings.IsBiomeUnlocked(request.BodyId, biomeName))
                {
                    return trueAbundance;
                }
                //Planet unlocked
                else if (RegolithScenario.Instance.gameSettings.IsPlanetUnlocked(request.BodyId))
                {
                    return baseAbuncance;
                }
                //Default is just our basic data
                else
                {
                    return minAbundance;
                }
            }
            catch (Exception e)
            {
                print("[REGO] - Error in - RegolithResourceMap_GetAbundance - " + e.Message);
                return 0f;
            }
        }
Example #27
0
		internal static float ResourceOverlay(double lat, double lon, string name, CelestialBody body)
		{
			float amount = 0f;
			var aRequest = new AbundanceRequest
			{
				Latitude = lat,
				Longitude = lon,
				BodyId = body.flightGlobalsIndex,
				ResourceName = name,
				ResourceType = HarvestTypes.Planetary,
				Altitude = 0,
				CheckForLock = SCANcontroller.controller.resourceBiomeLock,
				BiomeName = getBiomeName(body, lon, lat),
				ExcludeVariance = false,
			};

			amount = ResourceMap.Instance.GetAbundance(aRequest);
			return amount;
		}