// return true if at least a component has malfunctioned or had a critical failure public static bool HasMalfunction(Vessel v) { if (v.loaded) { foreach (Reliability m in Lib.FindModules <Reliability>(v)) { if (m.broken) { return(true); } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Reliability")) { if (Lib.Proto.GetBool(m, "broken")) { return(true); } } } return(false); }
static void Render_environment(Panel p, Vessel v, Vessel_info vi) { // don't show env panel in eva kerbals if (v.isEVA) return; // get all sensor readings HashSet<string> readings = new HashSet<string>(); if (v.loaded) { foreach (var s in Lib.FindModules<Sensor>(v)) { readings.Add(s.type); } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Sensor")) { readings.Add(Lib.Proto.GetString(m, "type")); } } readings.Remove(string.Empty); p.AddSection("ENVIRONMENT"); foreach (string type in readings) { p.AddContent(type, Sensor.Telemetry_content(v, vi, type), Sensor.Telemetry_tooltip(v, vi, type)); } if (readings.Count == 0) p.AddContent("<i>no sensors installed</i>"); }
// return total radiation emitted in a vessel public static double Total(Vessel v) { // get resource cache Resource_info ec = ResourceCache.Info(v, "ElectricCharge"); double tot = 0.0; if (v.loaded) { foreach (var emitter in Lib.FindModules <Emitter>(v)) { if (ec.amount > double.Epsilon || emitter.ec_rate <= double.Epsilon) { tot += emitter.running ? emitter.radiation : 0.0; } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Emitter")) { if (ec.amount > double.Epsilon || Lib.Proto.GetDouble(m, "ec_rate") <= double.Epsilon) { tot += Lib.Proto.GetBool(m, "running") ? Lib.Proto.GetDouble(m, "radiation") : 0.0; } } } return(tot); }
// cause a part at random to malfunction public static void CauseMalfunction(Vessel v) { // if vessel is loaded if (v.loaded) { // choose a module at random var modules = Lib.FindModules <Reliability>(v).FindAll(k => !k.broken); if (modules.Count == 0) { return; } var m = modules[Lib.RandomInt(modules.Count)]; // break it m.Break(); } // if vessel is not loaded else { // choose a module at random var modules = Lib.FindModules(v.protoVessel, "Reliability").FindAll(k => !Lib.Proto.GetBool(k, "broken")); if (modules.Count == 0) { return; } var m = modules[Lib.RandomInt(modules.Count)]; // find its part ProtoPartSnapshot p = v.protoVessel.protoPartSnapshots.Find(k => k.modules.Contains(m)); // break it ProtoBreak(v, p, m); } }
// remove one experiment at random from the vessel public static void RemoveData(Vessel v) { // stock science system if (!Features.Science) { // if vessel is loaded if (v.loaded) { // get all science containers/experiments with data List<IScienceDataContainer> modules = Lib.FindModules<IScienceDataContainer>(v).FindAll(k => k.GetData().Length > 0); // remove a data sample at random if (modules.Count > 0) { IScienceDataContainer container = modules[Lib.RandomInt(modules.Count)]; ScienceData[] data = container.GetData(); container.DumpData(data[Lib.RandomInt(data.Length)]); } } // if not loaded else { // get all science containers/experiments with data var modules = new List<ProtoPartModuleSnapshot>(); modules.AddRange(Lib.FindModules(v.protoVessel, "ModuleScienceContainer").FindAll(k => k.moduleValues.GetNodes("ScienceData").Length > 0)); modules.AddRange(Lib.FindModules(v.protoVessel, "ModuleScienceExperiment").FindAll(k => k.moduleValues.GetNodes("ScienceData").Length > 0)); // remove a data sample at random if (modules.Count > 0) { ProtoPartModuleSnapshot container = modules[Lib.RandomInt(modules.Count)]; ConfigNode[] data = container.moduleValues.GetNodes("ScienceData"); container.moduleValues.RemoveNode(data[Lib.RandomInt(data.Length)]); } } } // our own science system else { // select a file at random and remove it Drive drive = DB.Vessel(v).drive; if (drive.files.Count > 0) //< it should always be the case { string filename = string.Empty; int i = Lib.RandomInt(drive.files.Count); foreach (var pair in drive.files) { if (i-- == 0) { filename = pair.Key; break; } } drive.files.Remove(filename); } } }
internal void Update(Vessel v) { if (v == null || !v.loaded) { return; } if (habitats == null) { habitats = Lib.FindModules <Habitat>(v); maxPressure = 1.0; foreach (var habitat in habitats) { maxPressure = Math.Min(maxPressure, habitat.max_pressure); } } if (!Features.Radiation || habitats.Count == 0) { return; } // always do EVAs if (v.isEVA) { RaytraceToSun(v.rootPart); return; } if (habitatIndex < 0) { // first run, do them all foreach (var habitat in habitats) { RaytraceToSun(habitat.part); } habitatIndex = 0; } else { // only do one habitat at a time to preserve some performance // and check that part still exists if (habitats[habitatIndex].part == null) { habitats.RemoveAt(habitatIndex); } else { RaytraceToSun(habitats[habitatIndex].part); } habitatIndex = (habitatIndex + 1) % habitats.Count; } }
public static void Update(Vessel v) { // do nothing if not an eva kerbal if (!v.isEVA) return; // get KerbalEVA module KerbalEVA kerbal = Lib.FindModules<KerbalEVA>(v)[0]; Vessel_info vi = Cache.VesselInfo(v); // Stock KSP adds 5 units of monoprop to EVAs. We want to limit that amount // to whatever was available in the ship, so we don't magically create EVA prop out of nowhere if(Cache.HasVesselObjectsCache(v, "eva_prop")) { Lib.Log("### have eva_prop for " + v); var quantity = Cache.VesselObjectsCache<double>(v, "eva_prop"); Cache.RemoveVesselObjectsCache(v, "eva_prop"); Lib.Log("### adding " + quantity + " eva prop"); Lib.SetResource(kerbal.part, Lib.EvaPropellantName(), quantity, Lib.EvaPropellantCapacity()); } // get resource handler Resource_info ec = ResourceCache.Info(v, "ElectricCharge"); // determine if headlamps need ec // - not required if there is no EC capacity in eva kerbal (no ec supply in profile) // - not required if no EC cost for headlamps is specified (set by the user) bool need_ec = ec.capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon; // consume EC for the headlamps if (need_ec && kerbal.lampOn) { ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s, "headlamp"); } // force the headlamps on/off HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.amount > double.Epsilon)); // if dead if (IsDead(v)) { // enforce freezed state Freeze(kerbal); // disable modules DisableModules(kerbal); // remove plant flag action kerbal.flagItems = 0; } }
// return total radiation emitted in a vessel public static double Total(Vessel v) { // get resource cache ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge"); double tot = 0.0; if (v.loaded) { foreach (var emitter in Lib.FindModules <Emitter>(v)) { if (ec.Amount > double.Epsilon || emitter.ec_rate <= double.Epsilon) { if (emitter.running) { if (emitter.radiation > 0) { tot += emitter.radiation * emitter.radiation_impact; } else { tot += emitter.radiation; // always account for full shielding effect } } } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Emitter")) { if (ec.Amount > double.Epsilon || Lib.Proto.GetDouble(m, "ec_rate") <= double.Epsilon) { if (Lib.Proto.GetBool(m, "running")) { var rad = Lib.Proto.GetDouble(m, "radiation"); if (rad < 0) { tot += rad; } else { tot += rad * Lib.Proto.GetDouble(m, "radiation_factor"); } } } } } return(tot); }
static void Render_environment(Panel p, Vessel v, VesselData vd) { // don't show env panel in eva kerbals if (v.isEVA) { return; } // get all sensor readings HashSet <string> readings = new HashSet <string>(); if (v.loaded) { foreach (var s in Lib.FindModules <Sensor>(v)) { readings.Add(s.type); } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Sensor")) { readings.Add(Lib.Proto.GetString(m, "type")); } } readings.Remove(string.Empty); p.AddSection(Local.TELEMETRY_ENVIRONMENT); //"ENVIRONMENT" if (vd.SolarPanelsAverageExposure >= 0.0) { var exposureString = vd.SolarPanelsAverageExposure.ToString("P1"); if (vd.SolarPanelsAverageExposure < 0.2) { exposureString = Lib.Color(exposureString, Lib.Kolor.Orange); } p.AddContent(Local.TELEMETRY_SolarPanelsAverageExposure, exposureString, "<b>" + Local.TELEMETRY_Exposureignoringbodiesocclusion + "</b>\n<i>" + Local.TELEMETRY_Exposureignoringbodiesocclusion_desc + "</i>"); //"solar panels average exposure""Exposure ignoring bodies occlusion""Won't change on unloaded vessels\nMake sure to optimize it before switching } foreach (string type in readings) { p.AddContent(type.ToLower().Replace('_', ' '), Sensor.Telemetry_content(v, vd, type), Sensor.Telemetry_tooltip(v, vd, type)); } if (readings.Count == 0) { p.AddContent("<i>" + Local.TELEMETRY_nosensorsinstalled + "</i>"); //no sensors installed } }
static void Incentive_redundancy(Vessel v, string redundancy) { if (v.loaded) { foreach (Reliability m in Lib.FindModules <Reliability>(v)) { if (m.redundancy == redundancy) { m.next += m.next - m.last; } } } else { var PD = new Dictionary <string, Lib.Module_prefab_data>(); foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; var module_prefabs = part_prefab.FindModulesImplementing <PartModule>(); PD.Clear(); foreach (ProtoPartModuleSnapshot m in p.modules) { if (m.moduleName != "Reliability") { continue; } PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD); if (!module_prefab) { continue; } string r = Lib.Proto.GetString(m, "redundancy", string.Empty); if (r == redundancy) { double last = Lib.Proto.GetDouble(m, "last"); double next = Lib.Proto.GetDouble(m, "next"); Lib.Proto.Set(m, "next", next + (next - last)); } } } } }
public static Dictionary <uint, Drive> GetDriveParts(Vessel vessel) { Dictionary <uint, Drive> result = Cache.VesselObjectsCache <Dictionary <uint, Drive> >(vessel, "drives"); if (result != null) { return(result); } result = new Dictionary <uint, Drive>(); if (vessel.loaded) { foreach (var hd in vessel.FindPartModulesImplementing <HardDrive>()) { // Serenity/ModuleManager bug workaround (duplicate drives on EVAs) if (result.ContainsKey(hd.part.flightID)) { continue; } if (hd.hdId != 0 && DB.drives.ContainsKey(hd.hdId)) { result.Add(hd.part.flightID, DB.drives[hd.hdId]); } } } else { foreach (var p in vessel.protoVessel.protoPartSnapshots) { foreach (var pm in Lib.FindModules(p, "HardDrive")) { var hdId = Lib.Proto.GetUInt(pm, "hdId", 0); if (hdId != 0 && DB.drives.ContainsKey(hdId)) { result.Add(p.flightID, DB.drives[hdId]); } } } } Cache.SetVesselObjectsCache(vessel, "drives", result); return(result); }
/// <summary> /// get the total radiation emitted by nearby emitters (used for EVAs). only works for loaded vessels. /// </summary> public static double Nearby(Vessel v) { if (!v.loaded || !v.isEVA) { return(0.0); } var evaPosition = v.rootPart.transform.position; double result = 0.0; foreach (Vessel n in FlightGlobals.VesselsLoaded) { var vd = n.KerbalismData(); if (!vd.IsSimulated) { continue; } foreach (var emitter in Lib.FindModules <Emitter>(n)) { if (emitter.part == null || emitter.part.transform == null) { continue; } if (emitter.radiation <= 0) { continue; // ignore shielding effects here } if (!emitter.running) { continue; } var emitterPosition = emitter.part.transform.position; var vector = evaPosition - emitterPosition; var distance = vector.magnitude; result += Radiation.DistanceRadiation(emitter.radiation, distance); } } return(result); }
public static List <Data> Greenhouses(Vessel v) { List <Data> ret = new List <Data>(); if (v.loaded) { foreach (Greenhouse greenhouse in Lib.FindModules <Greenhouse>(v)) { if (greenhouse.active) { Data gd = new Data { growth = greenhouse.growth, natural = greenhouse.natural, artificial = greenhouse.artificial, tta = greenhouse.tta, issue = greenhouse.issue }; ret.Add(gd); } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Greenhouse")) { if (Lib.Proto.GetBool(m, "active")) { Data gd = new Data { growth = Lib.Proto.GetDouble(m, "growth"), natural = Lib.Proto.GetDouble(m, "natural"), artificial = Lib.Proto.GetDouble(m, "artificial"), tta = Lib.Proto.GetDouble(m, "tta"), issue = Lib.Proto.GetString(m, "issue") }; ret.Add(gd); } } } return(ret); }
public static void Update(Vessel v) { // do nothing if not an eva kerbal if (!v.isEVA) { return; } // get KerbalEVA module KerbalEVA kerbal = Lib.FindModules <KerbalEVA>(v)[0]; // get resource handler Resource_Info ec = ResourceCache.Info(v, "ElectricCharge"); // determine if headlamps need ec // - not required if there is no EC capacity in eva kerbal (no ec supply in profile) // - not required if no EC cost for headlamps is specified (set by the user) bool need_ec = ec.capacity > double.Epsilon && Settings.HeadLampsCost > double.Epsilon; // consume EC for the headlamps if (need_ec && kerbal.lampOn) { ec.Consume(Settings.HeadLampsCost * Kerbalism.elapsed_s); } // force the headlamps on/off HeadLamps(kerbal, kerbal.lampOn && (!need_ec || ec.amount > double.Epsilon)); // if dead if (IsDead(v)) { // enforce freezed state Freeze(kerbal); // disable modules DisableModules(kerbal); // remove plant flag action kerbal.flagItems = 0; } }
private static void RestoreSampleMass(Vessel v, SubjectData filename, double restoredAmount) { if (v.loaded) // loaded vessel { foreach (var experiment in v.FindPartModulesImplementing <Experiment>()) { restoredAmount -= experiment.RestoreSampleMass(restoredAmount, filename.ExpInfo.ExperimentId); } } else // unloaded vessel { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Experiment")) { restoredAmount -= Experiment.RestoreSampleMass(restoredAmount, m, filename.ExpInfo.ExperimentId); if (restoredAmount < double.Epsilon) { return; } } } }
static void Incentive_redundancy(Vessel v, string redundancy) { if (v.loaded) { foreach (Reliability m in Lib.FindModules <Reliability>(v)) { if (m.redundancy == redundancy) { m.next += m.next - m.last; } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Reliability")) { // find part ProtoPartSnapshot p = v.protoVessel.protoPartSnapshots.Find(k => k.modules.Contains(m)); // find module prefab string type = Lib.Proto.GetString(m, "type", string.Empty); Reliability reliability = p.partPrefab.FindModulesImplementing <Reliability>().Find(k => k.type == type); if (reliability == null) { continue; } // double time to next failure if (reliability.redundancy == redundancy) { double last = Lib.Proto.GetDouble(m, "last"); double next = Lib.Proto.GetDouble(m, "next"); Lib.Proto.Set(m, "next", next + (next - last)); } } } }
// return true if at least a component has a critical failure public static bool HasCriticalFailure(Vessel v) { if (v.loaded) { foreach (Reliability m in Lib.FindModules <Reliability>(v)) { if (m.critical) { return(true); } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Reliability")) { if (Lib.Proto.GetBool(m, "critical")) { return(true); } } } return(false); }
public void abort(Vessel v) { foreach (ScienceData data in queue) { foreach (ModuleScienceContainer container in Lib.FindModules <ModuleScienceContainer>(v)) { // add the data to the container container.ReturnData(data); // if, for some reasons, it wasn't possible to add the data, try the next container // note: this also deal with multiple versions of same data in the entire vessel if (!container.HasData(data)) { continue; } // data was added, process the next data break; } } queue.Clear(); transmitted.Clear(); }
private static void RestoreSampleMass(Vessel v, string filename, double restoredAmount) { int i = filename.IndexOf('@'); var id = i > 0 ? filename.Substring(0, i) : filename; if (v.loaded) // loaded vessel { foreach (var experiment in v.FindPartModulesImplementing <Experiment>()) { restoredAmount -= experiment.RestoreSampleMass(restoredAmount, id); } } else // unloaded vessel { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Experiment")) { restoredAmount -= Experiment.RestoreSampleMass(restoredAmount, m, id); if (restoredAmount < double.Epsilon) { return; } } } }
// return total radiation emitted in a vessel public static double Total(Vessel v) { // get resource cache ResourceInfo ec = ResourceCache.GetResource(v, "ElectricCharge"); double total = 0.0; if (v.loaded) { foreach (var shield in Lib.FindModules <PassiveShield>(v)) { if (ec.Amount > 0 || shield.ec_rate <= 0) { if (shield.deployed) { total += shield.radiation; } } } } else { foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "PassiveShield")) { if (ec.Amount > 0 || Lib.Proto.GetDouble(m, "ec_rate") <= 0) { if (Lib.Proto.GetBool(m, "deployed")) { var rad = Lib.Proto.GetDouble(m, "radiation"); total += rad; } } } } return(total); }
// return set of devices on a vessel // - the list is only valid for a single simulation step public static List <Device> GetModuleDevices(Vessel v) { List <Device> moduleDevices = Cache.VesselObjectsCache <List <Device> >(v, "computer"); if (moduleDevices != null) { return(moduleDevices); } moduleDevices = new List <Device>(); // store device being added Device device; // loaded vessel if (v.loaded) { foreach (PartModule m in Lib.FindModules <PartModule>(v)) { switch (m.moduleName) { case "ProcessController": device = new ProcessDevice(m as ProcessController); break; case "Sickbay": device = new SickbayDevice(m as Sickbay); break; case "Greenhouse": device = new GreenhouseDevice(m as Greenhouse); break; case "GravityRing": device = new RingDevice(m as GravityRing); break; case "Emitter": device = new EmitterDevice(m as Emitter); break; case "Laboratory": device = new LaboratoryDevice(m as Laboratory); break; case "Experiment": device = new ExperimentDevice(m as Experiment); break; case "SolarPanelFixer": device = new PanelDevice(m as SolarPanelFixer); break; case "ModuleGenerator": device = new GeneratorDevice(m as ModuleGenerator); break; case "ModuleResourceConverter": device = new ConverterDevice(m as ModuleResourceConverter); break; case "ModuleKPBSConverter": device = new ConverterDevice(m as ModuleResourceConverter); break; case "FissionReactor": device = new ConverterDevice(m as ModuleResourceConverter); break; case "ModuleResourceHarvester": device = new DrillDevice(m as ModuleResourceHarvester); break; case "ModuleLight": device = new LightDevice(m as ModuleLight); break; case "ModuleColoredLensLight": device = new LightDevice(m as ModuleLight); break; case "ModuleMultiPointSurfaceLight": device = new LightDevice(m as ModuleLight); break; case "SCANsat": device = new ScannerDevice(m); break; case "ModuleSCANresourceScanner": device = new ScannerDevice(m); break; case "ModuleRTAntenna": case "ModuleDataTransmitter": device = new AntennaDevice(m, m.moduleName); break; case "ModuleRTAntennaPassive": device = new AntennaDevice(m, "ModuleRTAntenna"); break; default: continue; } // add the device moduleDevices.Add(device); } } // unloaded vessel else { // store data required to support multiple modules of same type in a part var PD = new Dictionary <string, Lib.Module_prefab_data>(); // for each part foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; // get all module prefabs var module_prefabs = part_prefab.FindModulesImplementing <PartModule>(); // clear module indexes PD.Clear(); // for each module foreach (ProtoPartModuleSnapshot m in p.modules) { // get the module prefab // if the prefab doesn't contain this module, skip it PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD); if (!module_prefab) { continue; } // if the module is disabled, skip it // note: this must be done after ModulePrefab is called, so that indexes are right if (!Lib.Proto.GetBool(m, "isEnabled")) { continue; } // depending on module name switch (m.moduleName) { case "ProcessController": device = new ProtoProcessDevice(module_prefab as ProcessController, p, m); break; case "Sickbay": device = new ProtoSickbayDevice(module_prefab as Sickbay, p, m); break; case "Greenhouse": device = new ProtoGreenhouseDevice(module_prefab as Greenhouse, p, m); break; case "GravityRing": device = new ProtoRingDevice(module_prefab as GravityRing, p, m); break; case "Emitter": device = new ProtoEmitterDevice(module_prefab as Emitter, p, m); break; case "Laboratory": device = new ProtoLaboratoryDevice(module_prefab as Laboratory, p, m); break; case "Experiment": device = new ProtoExperimentDevice(module_prefab as Experiment, p, m, v); break; case "SolarPanelFixer": device = new ProtoPanelDevice(module_prefab as SolarPanelFixer, p, m); break; case "ModuleGenerator": device = new ProtoGeneratorDevice(module_prefab as ModuleGenerator, p, m); break; case "ModuleResourceConverter": case "ModuleKPBSConverter": case "FissionReactor": device = new ProtoConverterDevice(module_prefab as ModuleResourceConverter, p, m); break; case "ModuleResourceHarvester": device = new ProtoDrillDevice(module_prefab as ModuleResourceHarvester, p, m); break; case "ModuleLight": case "ModuleColoredLensLight": case "ModuleMultiPointSurfaceLight": device = new ProtoLightDevice(module_prefab as ModuleLight, p, m); break; case "SCANsat": device = new ProtoScannerDevice(module_prefab, p, m, v); break; case "ModuleSCANresourceScanner": device = new ProtoScannerDevice(module_prefab, p, m, v); break; case "ModuleRTAntenna": case "ModuleDataTransmitter": device = new ProtoAntennaDevice(module_prefab, p, m, m.moduleName); break; case "ModuleRTAntennaPassive": device = new ProtoAntennaDevice(module_prefab, p, m, "ModuleRTAntenna"); break; default: continue; } // add the device moduleDevices.Add(device); } } } // return all found module devices sorted by type, then by name // in reverse (the list will be presented from end to start in the UI) moduleDevices.Sort((b, a) => { int xdiff = a.DeviceType.CompareTo(b.DeviceType); if (xdiff != 0) { return(xdiff); } else { return(a.Name.CompareTo(b.Name)); } }); // now add vessel wide devices to the end of the list VesselData vd = v.KerbalismData(); moduleDevices.Add(new VesselDeviceTransmit(v, vd)); // vessel wide transmission toggle Cache.SetVesselObjectsCache(v, "computer", moduleDevices); return(moduleDevices); }
public Comforts(Vessel v, bool firm_ground, bool not_alone, bool call_home) { // environment factors this.firm_ground = firm_ground; this.not_alone = not_alone; this.call_home = call_home; // if loaded if (v.loaded) { // scan parts for comfort foreach (Comfort c in Lib.FindModules <Comfort>(v)) { switch (c.bonus) { case "firm-ground": this.firm_ground = true; break; case "not-alone": this.not_alone = true; break; case "call-home": this.call_home = true; break; case "exercise": this.exercise = true; break; case "panorama": this.panorama = true; break; } } // scan parts for gravity ring if (ResourceCache.Info(v, "ElectricCharge").amount >= 0.01) { this.firm_ground |= Lib.HasModule <GravityRing>(v, k => k.deployed); } } // if not loaded else { // scan parts for comfort foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Comfort")) { switch (Lib.Proto.GetString(m, "bonus")) { case "firm-ground": this.firm_ground = true; break; case "not-alone": this.not_alone = true; break; case "call-home": this.call_home = true; break; case "exercise": this.exercise = true; break; case "panorama": this.panorama = true; break; } } // scan parts for gravity ring if (ResourceCache.Info(v, "ElectricCharge").amount >= 0.01) { this.firm_ground |= Lib.HasModule(v.protoVessel, "GravityRing", k => Lib.Proto.GetBool(k, "deployed")); } } // calculate factor factor = 0.1; if (firm_ground) { factor += Settings.ComfortFirmGround; } if (not_alone) { factor += Settings.ComfortNotAlone; } if (call_home) { factor += Settings.ComfortCallHome; } if (exercise) { factor += Settings.ComfortExercise; } if (panorama) { factor += Settings.ComfortPanorama; } factor = Lib.Clamp(factor, 0.1, 1.0); }
public static List <ReliabilityInfo> BuildList(Vessel vessel) { var result = new List <ReliabilityInfo>(); if (vessel.loaded) { foreach (var r in Lib.FindModules <Reliability>(vessel)) { result.Add(new ReliabilityInfo(r)); } } else { var PD = new Dictionary <string, Lib.Module_prefab_data>(); foreach (ProtoPartSnapshot p in vessel.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; // get all module prefabs var module_prefabs = part_prefab.FindModulesImplementing <PartModule>(); // clear module indexes PD.Clear(); // for each module foreach (ProtoPartModuleSnapshot m in p.modules) { if (m.moduleName != "Reliability") { continue; } Reliability module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD) as Reliability; if (!module_prefab) { continue; } // if the module is disabled, skip it // note: this must be done after ModulePrefab is called, so that indexes are right if (!Lib.Proto.GetBool(m, "isEnabled")) { continue; } result.Add(new ReliabilityInfo(p, m, module_prefab)); } } } result.Sort((a, b) => { if (a.group != b.group) { return(string.Compare(a.group, b.group, StringComparison.Ordinal)); } return(string.Compare(a.title, b.title)); }); return(result); }
public Comforts(Vessel v, bool env_firm_ground, bool env_not_alone, bool env_call_home) { // environment factors firm_ground = env_firm_ground; not_alone = env_not_alone; call_home = env_call_home; // if loaded if (v.loaded) { // scan parts for comfort foreach (Comfort c in Lib.FindModules <Comfort>(v)) { switch (c.bonus) { case "firm-ground": firm_ground = true; break; case "not-alone": not_alone = true; break; case "call-home": call_home = true; break; case "exercise": exercise = true; break; case "panorama": panorama = true; break; case "plants": plants = true; break; } } // scan parts for gravity ring if (ResourceCache.Info(v, "ElectricCharge").amount >= 0.01) { firm_ground |= Lib.HasModule <GravityRing>(v, k => k.deployed); } } // if not loaded else { // scan parts for comfort foreach (ProtoPartModuleSnapshot m in Lib.FindModules(v.protoVessel, "Comfort")) { switch (Lib.Proto.GetString(m, "bonus")) { case "firm-ground": firm_ground = true; break; case "not-alone": not_alone = true; break; case "call-home": call_home = true; break; case "exercise": exercise = true; break; case "panorama": panorama = true; break; case "plants": plants = true; break; } } // scan parts for gravity ring if (ResourceCache.Info(v, "ElectricCharge").amount >= 0.01) { firm_ground |= Lib.HasModule(v.protoVessel, "GravityRing", k => Lib.Proto.GetBool(k, "deployed")); } } // calculate factor factor = 0.1; if (firm_ground) { factor += PreferencesComfort.Instance.firmGround; } if (not_alone) { factor += PreferencesComfort.Instance.notAlone; } if (call_home) { factor += PreferencesComfort.Instance.callHome; } if (exercise) { factor += PreferencesComfort.Instance.exercise; } if (panorama) { factor += PreferencesComfort.Instance.panorama; } if (plants) { factor += PreferencesComfort.Instance.plants; } factor = Lib.Clamp(factor, 0.1, 1.0); }
public static void BackgroundUpdate(Vessel vessel, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, KerbalismScansat kerbalismScansat, Part part_prefab, VesselData vd, Resource_info ec, double elapsed_s) { List <ProtoPartModuleSnapshot> scanners = Cache.VesselObjectsCache <List <ProtoPartModuleSnapshot> >(vessel, "scansat_" + p.flightID); if (scanners == null) { scanners = Lib.FindModules(p, "SCANsat"); if (scanners.Count == 0) { scanners = Lib.FindModules(p, "ModuleSCANresourceScanner"); } Cache.SetVesselObjectsCache(vessel, "scansat_" + p.flightID, scanners); } if (scanners.Count == 0) { return; } var scanner = scanners[0]; bool is_scanning = Lib.Proto.GetBool(scanner, "scanning"); if (is_scanning && kerbalismScansat.ec_rate > double.Epsilon) { ec.Consume(kerbalismScansat.ec_rate * elapsed_s, "scanner"); } if (!Features.Science) { if (is_scanning && ec.amount < double.Epsilon) { SCANsat.StopScanner(vessel, scanner, part_prefab); is_scanning = false; // remember disabled scanner vd.scansat_id.Add(p.flightID); // give the user some feedback if (vd.cfg_ec) { Message.Post(Lib.BuildString("SCANsat sensor was disabled on <b>", vessel.vesselName, "</b>")); } } else if (vd.scansat_id.Contains(p.flightID)) { // if there is enough ec // note: comparing against amount in previous simulation step // re-enable at 25% EC if (ec.level > 0.25) { // re-enable the scanner SCANsat.ResumeScanner(vessel, m, part_prefab); is_scanning = true; // give the user some feedback if (vd.cfg_ec) { Message.Post(Lib.BuildString("SCANsat sensor resumed operations on <b>", vessel.vesselName, "</b>")); } } } // forget active scanners if (is_scanning) { vd.scansat_id.Remove(p.flightID); } return; } // if(!Feature.Science) string body_name = Lib.Proto.GetString(m, "body_name"); int sensorType = (int)Lib.Proto.GetUInt(m, "sensorType"); double body_coverage = Lib.Proto.GetDouble(m, "body_coverage"); double warp_buffer = Lib.Proto.GetDouble(m, "warp_buffer"); double new_coverage = SCANsat.Coverage(sensorType, vessel.mainBody); if (body_name == vessel.mainBody.name && new_coverage < body_coverage) { // SCANsat sometimes reports a coverage of 0, which is wrong new_coverage = body_coverage; } if (vessel.mainBody.name != body_name) { body_name = vessel.mainBody.name; body_coverage = new_coverage; } else { double coverage_delta = new_coverage - body_coverage; body_coverage = new_coverage; if (is_scanning) { Science.Generate_subject(kerbalismScansat.experimentType, vessel); var subject_id = Science.Generate_subject_id(kerbalismScansat.experimentType, vessel); var exp = Science.Experiment(subject_id); double size = exp.max_amount * coverage_delta / 100.0; // coverage is 0-100% size += warp_buffer; if (size > double.Epsilon) { // store what we can foreach (var d in Drive.GetDrives(vessel)) { var available = d.FileCapacityAvailable(); var chunk = Math.Min(size, available); if (!d.Record_file(subject_id, chunk, true)) { break; } size -= chunk; if (size < double.Epsilon) { break; } } } if (size > double.Epsilon) { // we filled all drives up to the brim but were unable to store everything if (warp_buffer < double.Epsilon) { // warp buffer is empty, so lets store the rest there warp_buffer = size; size = 0; } else { // warp buffer not empty. that's ok if we didn't get new data if (coverage_delta < double.Epsilon) { size = 0; } // else we're scanning too fast. stop. } } // we filled all drives up to the brim but were unable to store everything // cancel scanning and annoy the user if (size > double.Epsilon || ec.amount < double.Epsilon) { warp_buffer = 0; SCANsat.StopScanner(vessel, scanner, part_prefab); vd.scansat_id.Add(p.flightID); if (vd.cfg_ec) { Message.Post(Lib.BuildString("SCANsat sensor was disabled on <b>", vessel.vesselName, "</b>")); } } } else if (vd.scansat_id.Contains(p.flightID)) { var vi = Cache.VesselInfo(vessel); if (ec.level >= 0.25 && (vi.free_capacity / vi.total_capacity > 0.9)) { SCANsat.ResumeScanner(vessel, scanner, part_prefab); vd.scansat_id.Remove(p.flightID); if (vd.cfg_ec) { Message.Post(Lib.BuildString("SCANsat sensor resumed operations on <b>", vessel.vesselName, "</b>")); } } } } Lib.Proto.Set(m, "warp_buffer", warp_buffer); Lib.Proto.Set(m, "body_coverage", body_coverage); Lib.Proto.Set(m, "body_name", body_name); }
public bool TestRequirements(Vessel v, out RequireResult[] results, bool testAll = false) { UnityEngine.Profiling.Profiler.BeginSample("Kerbalism.ExperimentRequirements.TestRequirements"); VesselData vd = v.KerbalismData(); results = new RequireResult[Requires.Length]; bool good = true; for (int i = 0; i < Requires.Length; i++) { results[i] = new RequireResult(Requires[i]); switch (Requires[i].require) { case Require.OrbitMinInclination: TestReq((c, r) => c >= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxInclination: TestReq((c, r) => c <= r, v.orbit.inclination, (double)Requires[i].value, results[i]); break; case Require.OrbitMinEccentricity: TestReq((c, r) => c >= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxEccentricity: TestReq((c, r) => c <= r, v.orbit.eccentricity, (double)Requires[i].value, results[i]); break; case Require.OrbitMinArgOfPeriapsis: TestReq((c, r) => c >= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break; case Require.OrbitMaxArgOfPeriapsis: TestReq((c, r) => c <= r, v.orbit.argumentOfPeriapsis, (double)Requires[i].value, results[i]); break; case Require.TemperatureMin: TestReq((c, r) => c >= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break; case Require.TemperatureMax: TestReq((c, r) => c <= r, vd.EnvTemperature, (double)Requires[i].value, results[i]); break; case Require.AltitudeMin: TestReq((c, r) => c >= r, v.altitude, (double)Requires[i].value, results[i]); break; case Require.AltitudeMax: TestReq((c, r) => c <= r, v.altitude, (double)Requires[i].value, results[i]); break; case Require.RadiationMin: TestReq((c, r) => c >= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break; case Require.RadiationMax: TestReq((c, r) => c <= r, vd.EnvRadiation, (double)Requires[i].value, results[i]); break; case Require.VolumePerCrewMin: TestReq((c, r) => c >= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break; case Require.VolumePerCrewMax: TestReq((c, r) => c <= r, vd.VolumePerCrew, (double)Requires[i].value, results[i]); break; case Require.SunAngleMin: TestReq((c, r) => c >= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break; case Require.SunAngleMax: TestReq((c, r) => c <= r, vd.EnvSunBodyAngle, (double)Requires[i].value, results[i]); break; case Require.SurfaceSpeedMin: TestReq((c, r) => c >= r, v.srfSpeed, (double)Requires[i].value, results[i]); break; case Require.SurfaceSpeedMax: TestReq((c, r) => c <= r, v.srfSpeed, (double)Requires[i].value, results[i]); break; case Require.VerticalSpeedMin: TestReq((c, r) => c >= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break; case Require.VerticalSpeedMax: TestReq((c, r) => c <= r, v.verticalSpeed, (double)Requires[i].value, results[i]); break; case Require.SpeedMin: TestReq((c, r) => c >= r, v.speed, (double)Requires[i].value, results[i]); break; case Require.SpeedMax: TestReq((c, r) => c <= r, v.speed, (double)Requires[i].value, results[i]); break; case Require.DynamicPressureMin: TestReq((c, r) => c >= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break; case Require.DynamicPressureMax: TestReq((c, r) => c <= r, v.dynamicPressurekPa, (double)Requires[i].value, results[i]); break; case Require.StaticPressureMin: TestReq((c, r) => c >= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break; case Require.StaticPressureMax: TestReq((c, r) => c <= r, v.staticPressurekPa, (double)Requires[i].value, results[i]); break; case Require.AtmDensityMin: TestReq((c, r) => c >= r, v.atmDensity, (double)Requires[i].value, results[i]); break; case Require.AtmDensityMax: TestReq((c, r) => c <= r, v.atmDensity, (double)Requires[i].value, results[i]); break; case Require.AltAboveGroundMin: TestReq((c, r) => c >= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break; case Require.AltAboveGroundMax: TestReq((c, r) => c <= r, v.heightFromTerrain, (double)Requires[i].value, results[i]); break; case Require.MaxAsteroidDistance: TestReq((c, r) => c <= r, TestAsteroidDistance(v), (double)Requires[i].value, results[i]); break; case Require.AtmosphereAltMin: TestReq((c, r) => c >= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break; case Require.AtmosphereAltMax: TestReq((c, r) => c <= r, v.mainBody.atmosphere ? v.altitude / v.mainBody.atmosphereDepth : double.NaN, (double)Requires[i].value, results[i]); break; case Require.CrewMin: TestReq((c, r) => c >= r, vd.CrewCount, (int)Requires[i].value, results[i]); break; case Require.CrewMax: TestReq((c, r) => c <= r, vd.CrewCount, (int)Requires[i].value, results[i]); break; case Require.CrewCapacityMin: TestReq((c, r) => c >= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break; case Require.CrewCapacityMax: TestReq((c, r) => c <= r, vd.CrewCapacity, (int)Requires[i].value, results[i]); break; case Require.AstronautComplexLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break; case Require.AstronautComplexLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.AstronautComplex), (int)Requires[i].value, results[i]); break; case Require.TrackingStationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break; case Require.TrackingStationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.TrackingStation), (int)Requires[i].value, results[i]); break; case Require.MissionControlLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break; case Require.MissionControlLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.MissionControl), (int)Requires[i].value, results[i]); break; case Require.AdministrationLevelMin: TestReq((c, r) => c >= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break; case Require.AdministrationLevelMax: TestReq((c, r) => c <= r, GetFacilityLevel(SpaceCenterFacility.Administration), (int)Requires[i].value, results[i]); break; case Require.Shadow: TestReq(() => vd.EnvInFullShadow, results[i]); break; case Require.Sunlight: TestReq(() => vd.EnvInSunlight, results[i]); break; case Require.Greenhouse: TestReq(() => vd.Greenhouses.Count > 0, results[i]); break; case Require.AbsoluteZero: TestReq(() => vd.EnvTemperature < 30.0, results[i]); break; case Require.InnerBelt: TestReq(() => vd.EnvInnerBelt, results[i]); break; case Require.OuterBelt: TestReq(() => vd.EnvOuterBelt, results[i]); break; case Require.MagneticBelt: TestReq(() => vd.EnvInnerBelt || vd.EnvOuterBelt, results[i]); break; case Require.Magnetosphere: TestReq(() => vd.EnvMagnetosphere, results[i]); break; case Require.InterStellar: TestReq(() => Lib.IsSun(v.mainBody) && vd.EnvInterstellar, results[i]); break; case Require.Part: TestReq(() => Lib.HasPart(v, (string)Requires[i].value), results[i]); break; case Require.Module: TestReq(() => Lib.FindModules(v.protoVessel, (string)Requires[i].value).Count > 0, results[i]); break; default: results[i].isValid = true; break; } if (!testAll && !results[i].isValid) { UnityEngine.Profiling.Profiler.EndSample(); return(false); } good &= results[i].isValid; } UnityEngine.Profiling.Profiler.EndSample(); return(good); }
public AntennaInfo(Vessel v) { // initialize data type = new List <AntennaType>(); cost = new List <double>(); rate = new List <double>(); dist = new List <double>(); relay = new List <bool>(); no_antenna = true; // get ec available // - this is the amount available at previous simulation step bool ec_available = ResourceCache.Info(v, "ElectricCharge").amount > double.Epsilon; // if the vessel is loaded if (v.loaded) { // get all antennas data foreach (Antenna a in Lib.FindModules <Antenna>(v)) { if (!Settings.ExtendedAntenna || a.extended) { type.Add(a.type); cost.Add(a.cost); rate.Add(a.rate); dist.Add(a.dist); relay.Add(ec_available && a.relay); is_relay |= ec_available && a.relay; direct_cost += a.cost; if (a.type == AntennaType.low_gain) { indirect_cost += a.cost; } } no_antenna = false; } } // if the vessel isn't loaded // - we don't support multiple antenna modules per-part else { // for each part foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; // get module prefab Antenna a = part_prefab.FindModuleImplementing <Antenna>(); // if there is none, skip the part if (a == null) { continue; } // for each module foreach (ProtoPartModuleSnapshot m in p.modules) { // we are only interested in antennas if (m.moduleName != "Antenna") { continue; } // if the module is disabled, skip it if (!Lib.Proto.GetBool(m, "isEnabled")) { continue; } // get antenna data if (!Settings.ExtendedAntenna || Lib.Proto.GetBool(m, "extended")) { bool antenna_is_relay = Lib.Proto.GetBool(m, "relay"); type.Add(a.type); cost.Add(a.cost); rate.Add(a.rate); dist.Add(a.dist); relay.Add(ec_available && antenna_is_relay); is_relay |= ec_available && antenna_is_relay; direct_cost += a.cost; if (a.type == AntennaType.low_gain) { indirect_cost += a.cost; } } no_antenna = false; } } } }
// return set of devices on a vessel // - the list is only valid for a single simulation step public static Dictionary <uint, Device> boot(Vessel v) { // store all devices var devices = new Dictionary <uint, Device>(); // store device being added Device dev; // loaded vessel if (v.loaded) { foreach (PartModule m in Lib.FindModules <PartModule>(v)) { switch (m.moduleName) { case "ProcessController": dev = new ProcessDevice(m as ProcessController); break; case "Greenhouse": dev = new GreenhouseDevice(m as Greenhouse); break; case "GravityRing": dev = new RingDevice(m as GravityRing); break; case "Emitter": dev = new EmitterDevice(m as Emitter); break; case "Harvester": dev = new HarvesterDevice(m as Harvester); break; case "Laboratory": dev = new LaboratoryDevice(m as Laboratory); break; case "Antenna": dev = new AntennaDevice(m as Antenna); break; case "Experiment": dev = new ExperimentDevice(m as Experiment); break; case "ModuleDeployableSolarPanel": dev = new PanelDevice(m as ModuleDeployableSolarPanel); break; case "ModuleGenerator": dev = new GeneratorDevice(m as ModuleGenerator); break; case "ModuleResourceConverter": dev = new ConverterDevice(m as ModuleResourceConverter); break; case "ModuleKPBSConverter": dev = new ConverterDevice(m as ModuleResourceConverter); break; case "FissionReactor": dev = new ConverterDevice(m as ModuleResourceConverter); break; case "ModuleResourceHarvester": dev = new DrillDevice(m as ModuleResourceHarvester); break; case "ModuleLight": dev = new LightDevice(m as ModuleLight); break; case "ModuleColoredLensLight": dev = new LightDevice(m as ModuleLight); break; case "ModuleMultiPointSurfaceLight": dev = new LightDevice(m as ModuleLight); break; case "SCANsat": dev = new ScannerDevice(m); break; case "ModuleSCANresourceScanner": dev = new ScannerDevice(m); break; default: continue; } // add the device // - multiple same-type components in the same part will have the same id, and are ignored if (!devices.ContainsKey(dev.id())) { devices.Add(dev.id(), dev); } } } // unloaded vessel else { // store data required to support multiple modules of same type in a part var PD = new Dictionary <string, Lib.module_prefab_data>(); // for each part foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; // get all module prefabs var module_prefabs = part_prefab.FindModulesImplementing <PartModule>(); // clear module indexes PD.Clear(); // for each module foreach (ProtoPartModuleSnapshot m in p.modules) { // get the module prefab // if the prefab doesn't contain this module, skip it PartModule module_prefab = Lib.ModulePrefab(module_prefabs, m.moduleName, PD); if (!module_prefab) { continue; } // if the module is disabled, skip it // note: this must be done after ModulePrefab is called, so that indexes are right if (!Lib.Proto.GetBool(m, "isEnabled")) { continue; } // depending on module name switch (m.moduleName) { case "ProcessController": dev = new ProtoProcessDevice(m, module_prefab as ProcessController, p.flightID); break; case "Greenhouse": dev = new ProtoGreenhouseDevice(m, p.flightID); break; case "GravityRing": dev = new ProtoRingDevice(m, p.flightID); break; case "Emitter": dev = new ProtoEmitterDevice(m, p.flightID); break; case "Harvester": dev = new ProtoHarvesterDevice(m, module_prefab as Harvester, p.flightID); break; case "Laboratory": dev = new ProtoLaboratoryDevice(m, p.flightID); break; case "Antenna": dev = new ProtoAntennaDevice(m, p.flightID); break; case "Experiment": dev = new ProtoExperimentDevice(m, module_prefab as Experiment, p.flightID); break; case "ModuleDeployableSolarPanel": dev = new ProtoPanelDevice(m, module_prefab as ModuleDeployableSolarPanel, p.flightID); break; case "ModuleGenerator": dev = new ProtoGeneratorDevice(m, module_prefab as ModuleGenerator, p.flightID); break; case "ModuleResourceConverter": dev = new ProtoConverterDevice(m, module_prefab as ModuleResourceConverter, p.flightID); break; case "ModuleKPBSConverter": dev = new ProtoConverterDevice(m, module_prefab as ModuleResourceConverter, p.flightID); break; case "FissionReactor": dev = new ProtoConverterDevice(m, module_prefab as ModuleResourceConverter, p.flightID); break; case "ModuleResourceHarvester": dev = new ProtoDrillDevice(m, module_prefab as ModuleResourceHarvester, p.flightID); break; case "ModuleLight": dev = new ProtoLightDevice(m, p.flightID); break; case "ModuleColoredLensLight": dev = new ProtoLightDevice(m, p.flightID); break; case "ModuleMultiPointSurfaceLight": dev = new ProtoLightDevice(m, p.flightID); break; case "SCANsat": dev = new ProtoScannerDevice(m, part_prefab, v, p.flightID); break; case "ModuleSCANresourceScanner": dev = new ProtoScannerDevice(m, part_prefab, v, p.flightID); break; default: continue; } // add the device // - multiple same-type components in the same part will have the same id, and are ignored if (!devices.ContainsKey(dev.id())) { devices.Add(dev.id(), dev); } } } } // return all devices found return(devices); }
public static string TestRequirements(string experiment_id, string requirements, Vessel v) { CelestialBody body = v.mainBody; Vessel_info vi = Cache.VesselInfo(v); List <string> list = Lib.Tokenize(requirements, ','); foreach (string s in list) { var parts = Lib.Tokenize(s, ':'); var condition = parts[0]; string value = string.Empty; if (parts.Count > 1) { value = parts[1]; } bool good = true; switch (condition) { case "OrbitMinInclination": good = Math.Abs(v.orbit.inclination) >= double.Parse(value); break; case "OrbitMaxInclination": good = Math.Abs(v.orbit.inclination) <= double.Parse(value); break; case "OrbitMinEccentricity": good = v.orbit.eccentricity >= double.Parse(value); break; case "OrbitMaxEccentricity": good = v.orbit.eccentricity <= double.Parse(value); break; case "OrbitMinArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis >= double.Parse(value); break; case "OrbitMaxArgOfPeriapsis": good = v.orbit.argumentOfPeriapsis <= double.Parse(value); break; case "TemperatureMin": good = vi.temperature >= double.Parse(value); break; case "TemperatureMax": good = vi.temperature <= double.Parse(value); break; case "AltitudeMin": good = v.altitude >= double.Parse(value); break; case "AltitudeMax": good = v.altitude <= double.Parse(value); break; case "RadiationMin": good = vi.radiation >= double.Parse(value); break; case "RadiationMax": good = vi.radiation <= double.Parse(value); break; case "Microgravity": good = vi.zerog; break; case "Body": good = TestBody(v.mainBody.name, value); break; case "Shadow": good = vi.sunlight < double.Epsilon; break; case "Sunlight": good = vi.sunlight > 0.5; break; case "CrewMin": good = vi.crew_count >= int.Parse(value); break; case "CrewMax": good = vi.crew_count <= int.Parse(value); break; case "CrewCapacityMin": good = vi.crew_capacity >= int.Parse(value); break; case "CrewCapacityMax": good = vi.crew_capacity <= int.Parse(value); break; case "VolumePerCrewMin": good = vi.volume_per_crew >= double.Parse(value); break; case "VolumePerCrewMax": good = vi.volume_per_crew <= double.Parse(value); break; case "Greenhouse": good = vi.greenhouses.Count > 0; break; case "Surface": good = Lib.Landed(v); break; case "Atmosphere": good = body.atmosphere && v.altitude < body.atmosphereDepth; break; case "AtmosphereBody": good = body.atmosphere; break; case "AtmosphereAltMin": good = body.atmosphere && (v.altitude / body.atmosphereDepth) >= double.Parse(value); break; case "AtmosphereAltMax": good = body.atmosphere && (v.altitude / body.atmosphereDepth) <= double.Parse(value); break; case "BodyWithAtmosphere": good = body.atmosphere; break; case "BodyWithoutAtmosphere": good = !body.atmosphere; break; case "SunAngleMin": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) >= double.Parse(value); break; case "SunAngleMax": good = Lib.IsSun(v.mainBody) || Lib.SunBodyAngle(v) <= double.Parse(value); break; case "Vacuum": good = !body.atmosphere || v.altitude > body.atmosphereDepth; break; case "Ocean": good = body.ocean && v.altitude < 0.0; break; case "PlanetarySpace": good = body.flightGlobalsIndex != 0 && !Lib.Landed(v) && v.altitude > body.atmosphereDepth; break; case "AbsoluteZero": good = vi.temperature < 30.0; break; case "InnerBelt": good = vi.inner_belt; break; case "OuterBelt": good = vi.outer_belt; break; case "MagneticBelt": good = vi.inner_belt || vi.outer_belt; break; case "Magnetosphere": good = vi.magnetosphere; break; case "Thermosphere": good = vi.thermosphere; break; case "Exosphere": good = vi.exosphere; break; case "InterPlanetary": good = body.flightGlobalsIndex == 0 && !vi.interstellar; break; case "InterStellar": good = body.flightGlobalsIndex == 0 && vi.interstellar; break; case "SurfaceSpeedMin": good = v.srfSpeed >= double.Parse(value); break; case "SurfaceSpeedMax": good = v.srfSpeed <= double.Parse(value); break; case "VerticalSpeedMin": good = v.verticalSpeed >= double.Parse(value); break; case "VerticalSpeedMax": good = v.verticalSpeed <= double.Parse(value); break; case "SpeedMin": good = v.speed >= double.Parse(value); break; case "SpeedMax": good = v.speed <= double.Parse(value); break; case "DynamicPressureMin": good = v.dynamicPressurekPa >= double.Parse(value); break; case "DynamicPressureMax": good = v.dynamicPressurekPa <= double.Parse(value); break; case "StaticPressureMin": good = v.staticPressurekPa >= double.Parse(value); break; case "StaticPressureMax": good = v.staticPressurekPa <= double.Parse(value); break; case "AtmDensityMin": good = v.atmDensity >= double.Parse(value); break; case "AtmDensityMax": good = v.atmDensity <= double.Parse(value); break; case "AltAboveGroundMin": good = v.heightFromTerrain >= double.Parse(value); break; case "AltAboveGroundMax": good = v.heightFromTerrain <= double.Parse(value); break; case "Part": good = Lib.HasPart(v, value); break; case "Module": good = Lib.FindModules(v.protoVessel, value).Count > 0; break; case "AstronautComplexLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) >= (double.Parse(value) - 1) / 2.0; break; case "AstronautComplexLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.AstronautComplex) <= (double.Parse(value) - 1) / 2.0; break; case "TrackingStationLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) >= (double.Parse(value) - 1) / 2.0; break; case "TrackingStationLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.TrackingStation) <= (double.Parse(value) - 1) / 2.0; break; case "MissionControlLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) >= (double.Parse(value) - 1) / 2.0; break; case "MissionControlLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.MissionControl) <= (double.Parse(value) - 1) / 2.0; break; case "AdministrationLevelMin": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) >= (double.Parse(value) - 1) / 2.0; break; case "AdministrationLevelMax": good = (ScenarioUpgradeableFacilities.Instance == null) || ScenarioUpgradeableFacilities.GetFacilityLevel(SpaceCenterFacility.Administration) <= (double.Parse(value) - 1) / 2.0; break; case "MaxAsteroidDistance": good = AsteroidDistance(v) <= double.Parse(value); break; } if (!good) { return(s); } } var subject_id = Science.Generate_subject_id(experiment_id, v); var exp = Science.Experiment(subject_id); var sit = GetExperimentSituation(v); if (!v.loaded && sit.AtmosphericFlight()) { return("Background flight"); } if (!sit.IsAvailable(exp)) { return("Invalid situation"); } // At this point we know the situation is valid and the experiment can be done // create it in R&D Science.Generate_subject(experiment_id, v); return(string.Empty); }
static bool Prefix(ref ProtoVessel pv, ref bool quick) { if (pv == null) { return(true); } // get a hard drive. any hard drive will do, no need to find a specific one. ProtoPartModuleSnapshot protoHardDrive = null; foreach (var p in pv.protoPartSnapshots) { foreach (var pm in Lib.FindModules(p, "HardDrive")) { protoHardDrive = pm; break; } if (protoHardDrive != null) { break; } } if (protoHardDrive == null) { return(true); // no drive on the vessel - nothing to do. } double scienceToCredit = 0.0; List <DialogGUIBase> labels = new List <DialogGUIBase>(); foreach (Drive drive in Drive.GetDrives(pv, true)) { foreach (File file in drive.files.Values) { double subjectValue = file.subjectData.ScienceValue(file.size); file.subjectData.RemoveScienceCollectedInFlight(subjectValue); if (file.useStockCrediting) { file.ConvertToStockData().Save(protoHardDrive.moduleValues.AddNode("ScienceData")); if (!file.subjectData.ExistsInRnD) { file.subjectData.CreateSubjectInRnD(); } file.subjectData.SetAsPersistent(); file.subjectData.UpdateSubjectCompletion(subjectValue); } else { scienceToCredit += file.subjectData.RetrieveScience(subjectValue, false, pv); labels.Add(new DialogGUILabel(Lib.BuildString( Lib.Color("+ " + subjectValue.ToString("F1"), Lib.Kolor.Science), " (", Lib.Color(file.subjectData.ScienceRetrievedInKSC.ToString("F1"), Lib.Kolor.Science, true), " / ", Lib.Color(file.subjectData.ScienceMaxValue.ToString("F1"), Lib.Kolor.Science, true), ") : ", file.subjectData.FullTitle ))); } } foreach (Sample sample in drive.samples.Values) { double subjectValue = sample.subjectData.ScienceValue(sample.size); sample.subjectData.RemoveScienceCollectedInFlight(subjectValue); if (sample.useStockCrediting) { sample.ConvertToStockData().Save(protoHardDrive.moduleValues.AddNode("ScienceData")); if (!sample.subjectData.ExistsInRnD) { sample.subjectData.CreateSubjectInRnD(); } sample.subjectData.SetAsPersistent(); sample.subjectData.UpdateSubjectCompletion(subjectValue); } else { scienceToCredit += sample.subjectData.RetrieveScience(subjectValue, false, pv); labels.Add(new DialogGUILabel(Lib.BuildString( Lib.Color("+ " + subjectValue.ToString("F1"), Lib.Kolor.Science), " (", Lib.Color(sample.subjectData.ScienceRetrievedInKSC.ToString("F1"), Lib.Kolor.Science, true), " / ", Lib.Color(sample.subjectData.ScienceMaxValue.ToString("F1"), Lib.Kolor.Science, true), ") : ", sample.subjectData.FullTitle ))); } } } protoHardDrive.moduleName = "ModuleScienceContainer"; if (scienceToCredit > 0.0) { // ideally we should hack the stock dialog to add the little science widgets to it but I'm lazy // plus it looks like crap anyway PopupDialog.SpawnPopupDialog ( new MultiOptionDialog ( "scienceResults", "", pv.vesselName + " " + Local.VesselRecovery_title, HighLogic.UISkin, new Rect(0.3f, 0.5f, 350f, 100f), //" recovery" new DialogGUIVerticalLayout ( new DialogGUIBox(Local.VesselRecovery_info + " : " + Lib.Color(scienceToCredit.ToString("F1") + " " + Local.VesselRecovery_CREDITS, Lib.Kolor.Science, true), 340f, 30f), //"SCIENCE RECOVERED"" CREDITS" new DialogGUIScrollList ( new Vector2(340f, 250f), false, true, new DialogGUIVerticalLayout(labels.ToArray()) ), new DialogGUIButton(Local.VesselRecovery_OKbutton, null, 340f, 30f, true, HighLogic.UISkin.button) //"OK" ) ), false, HighLogic.UISkin ); } return(true); // continue to the original code }