protected virtual List <ModuleDataTransmitter> GetTransmittersLoaded(Vessel v) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } // Disable all stock buttons // TODO : moved from the update method (AntennaInfo()) to here to save performance, but maybe that is called too early and doesn't work foreach (ModuleDataTransmitter mdt in transmitters) { mdt.Events["TransmitIncompleteToggle"].active = false; mdt.Events["StartTransmission"].active = false; mdt.Events["StopTransmission"].active = false; mdt.Actions["StartTransmissionAction"].active = false; } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } return(transmitters); }
protected virtual List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > GetTransmittersUnloaded(Vessel v) { List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; foreach (ModuleDataTransmitter t in part_prefab.FindModulesImplementing <ModuleDataTransmitter>()) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot>(t, p)); } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > >(v, "commnet_bg"); } return(transmitters); }
public static void BackgroundUpdate(Vessel v, ProtoPartModuleSnapshot m, KerbalismProcess process, Resource_info ec, Vessel_resources resources, double elapsed_s) { if (!process.unloaded) { return; } List <KeyValuePair <string, double> > resourcesProduced; List <KeyValuePair <string, double> > resourcesConsumed; if (!Cache.HasVesselObjectsCache(v, "kerbalism_process_produced_" + process.part.flightID)) { resourcesProduced = ParseResources(process.resources_produced, false); Cache.SetVesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_produced_" + process.part.flightID, resourcesProduced); } else { resourcesProduced = Cache.VesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_produced_" + process.part.flightID); } if (!Cache.HasVesselObjectsCache(v, "kerbalism_process_consumed_" + process.part.flightID)) { resourcesConsumed = ParseResources(process.resources_produced, false); Cache.SetVesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_consumed_" + process.part.flightID, resourcesConsumed); } else { resourcesConsumed = Cache.VesselObjectsCache <List <KeyValuePair <string, double> > >(v, "kerbalism_process_consumed_" + process.part.flightID); } RunProcessTick(v, elapsed_s, process.ec_produced, resourcesProduced, process.ec_consumed, resourcesConsumed, ec, resources); }
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>()) { if (DB.drives.ContainsKey(hd.part.flightID)) { result.Add(hd.part.flightID, DB.drives[hd.part.flightID]); } } } else { foreach (var hd in vessel.protoVessel.protoPartSnapshots) { if (DB.drives.ContainsKey(hd.flightID)) { result.Add(hd.flightID, DB.drives[hd.flightID]); } } } Cache.SetVesselObjectsCache(vessel, "drives", result); return(result); }
protected virtual List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > GetTransmittersUnloaded(Vessel v) { List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot pps in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = pps.partInfo.partPrefab; for (int i = 0; i < part_prefab.Modules.Count; i++) { if (part_prefab.Modules[i] is ModuleDataTransmitter mdt) { ProtoPartModuleSnapshot ppms; // We want to also get a possible ModuleDataTransmitter derivative but type checking isn't available // so we check a specific value present on the base class (See ModuleDataTransmitter.OnSave()) if (pps.modules[i].moduleValues.HasValue("canComm")) { ppms = pps.modules[i]; } // fallback in case the module indexes are messed up else { ppms = pps.FindModule("ModuleDataTransmitter"); Lib.LogDebug($"Could not find a ModuleDataTransmitter or derivative at index {i} on part {pps.partName} on vessel {v.protoVessel.vesselName}", Lib.LogLevel.Warning); } if (ppms != null) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot>(mdt, ppms)); } } } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartModuleSnapshot> > >(v, "commnet_bg"); } return(transmitters); }
public static ConnectionInfo Update(Vessel v, bool powered, bool storm) { var result = Cache.VesselObjectsCache <ConnectionInfo>(v, "connection_info"); var ts = Cache.VesselObjectsCache <double>(v, "connection_info_ts"); var maxAge = Math.Max(2, Kerbalism.elapsed_s * 2); if (result == null || Planetarium.GetUniversalTime() > ts + maxAge) { result = new ConnectionInfo(v, powered, storm); Cache.SetVesselObjectsCache(v, "connection_info", result); Cache.SetVesselObjectsCache(v, "connection_info_ts", Planetarium.GetUniversalTime()); } return(result); }
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); }
protected virtual List <ModuleDataTransmitter> GetTransmittersLoaded(Vessel v) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } return(transmitters); }
void ToEVA(GameEvents.FromToAction <Part, Part> data) { OnVesselModified(data.from.vessel); OnVesselModified(data.to.vessel); // get total crew in the origin vessel double tot_crew = Lib.CrewCount(data.from.vessel) + 1.0; // get vessel resources handler VesselResources resources = ResourceCache.Get(data.from.vessel); // setup supply resources capacity in the eva kerbal Profile.SetupEva(data.to); String prop_name = Lib.EvaPropellantName(); // for each resource in the kerbal for (int i = 0; i < data.to.Resources.Count; ++i) { // get the resource PartResource res = data.to.Resources[i]; // eva prop is handled differently if (res.resourceName == prop_name) { continue; } double quantity = Math.Min(resources.GetResource(data.from.vessel, res.resourceName).Amount / tot_crew, res.maxAmount); // remove resource from vessel quantity = data.from.RequestResource(res.resourceName, quantity); // add resource to eva kerbal data.to.RequestResource(res.resourceName, -quantity); } // take as much of the propellant as possible. just imagine: there are 1.3 units left, and 12 occupants // in the ship. you want to send out an engineer to fix the chemical plant that produces monoprop, // and have to get from one end of the station to the other with just 0.1 units in the tank... // nope. double evaPropQuantity = data.from.RequestResource(prop_name, Lib.EvaPropellantCapacity()); // We can't just add the monoprop here, because that doesn't always work. It might be related // to the fact that stock KSP wants to add 5 units of monoprop to new EVAs. Instead of fighting KSP here, // we just let it do it's thing and set our amount later in EVA.cs - which seems to work just fine. // don't put that into Cache.VesselInfo because that can be deleted before we get there Cache.SetVesselObjectsCache(data.to.vessel, "eva_prop", evaPropQuantity); // Airlock loss resources.Consume(data.from.vessel, "Nitrogen", Settings.LifeSupportAtmoLoss, ResourceBroker.Generic); // show warning if there is little or no EVA propellant in the suit if (evaPropQuantity <= 0.05 && !Lib.Landed(data.from.vessel)) { Message.Post(Severity.danger, Local.CallBackMsg_EvaNoMP.Format("<b>" + prop_name + "</b>"), Local.CallBackMsg_EvaNoMP2); //Lib.BuildString("There isn't any <<1>> in the EVA suit")"Don't let the ladder go!" } // turn off headlamp light, to avoid stock bug that show them for a split second when going on eva KerbalEVA kerbal = data.to.FindModuleImplementing <KerbalEVA>(); EVA.HeadLamps(kerbal, false); // execute script data.from.vessel.KerbalismData().computer.Execute(data.from.vessel, ScriptType.eva_out); }
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); }
// 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) { var devices = Cache.VesselObjectsCache <Dictionary <uint, Device> >(v, "computer"); if (devices != null) { return(devices); } 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 "Sickbay": dev = new SickbayDevice(m as Sickbay); 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 "Laboratory": dev = new LaboratoryDevice(m as Laboratory); 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; case "ModuleRTAntenna": case "ModuleDataTransmitter": dev = new Antenna(m, m.moduleName); break; case "ModuleRTAntennaPassive": dev = new Antenna(m, "ModuleRTAntenna"); 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>(); var experiments = new List <KeyValuePair <Experiment, ProtoPartModuleSnapshot> >(); // 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 "Sickbay": dev = new ProtoSickbayDevice(m, module_prefab as Sickbay, 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 "Laboratory": dev = new ProtoLaboratoryDevice(m, p.flightID); break; case "Experiment": experiments.Add(new KeyValuePair <Experiment, ProtoPartModuleSnapshot>(module_prefab as Experiment, m)); dev = new ProtoExperimentDevice(m, module_prefab as Experiment, p.flightID, experiments); 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; case "ModuleRTAntenna": case "ModuleDataTransmitter": dev = new ProtoPartAntenna(m, p, v, m.moduleName, p.flightID); break; case "ModuleRTAntennaPassive": dev = new ProtoPartAntenna(m, p, v, "ModuleRTAntenna", 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); } } } } devices = devices.OrderBy(k => k.Value.Name()).ToDictionary(pair => pair.Key, pair => pair.Value); //return all found devices sorted by name Cache.SetVesselObjectsCache(v, "computer", devices); return(devices); }
public AntennaInfoCommNet(Vessel v, bool powered, bool storm, bool transmitting) { int transmitterCount = 0; rate = 1; double ec_transmitter = 0; // if vessel is loaded if (v.loaded) { List <ModuleDataTransmitter> transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet")) { // find transmitters transmitters = v.FindPartModulesImplementing <ModuleDataTransmitter>(); if (transmitters == null) { transmitters = new List <ModuleDataTransmitter>(); } Cache.SetVesselObjectsCache(v, "commnet", transmitters); } else { transmitters = Cache.VesselObjectsCache <List <ModuleDataTransmitter> >(v, "commnet"); } foreach (ModuleDataTransmitter t in transmitters) { // Disable all stock buttons t.Events["TransmitIncompleteToggle"].active = false; t.Events["StartTransmission"].active = false; t.Events["StopTransmission"].active = false; t.Actions["StartTransmissionAction"].active = false; if (t.antennaType == AntennaType.INTERNAL) // do not include internal data rate, ec cost only { ec += t.DataResourceCost * t.DataRate; } else { // do we have an animation ModuleDeployableAntenna animation = t.part.FindModuleImplementing <ModuleDeployableAntenna>(); ModuleAnimateGeneric animationGeneric = t.part.FindModuleImplementing <ModuleAnimateGeneric>(); if (animation != null) { // only include data rate and ec cost if transmitter is extended if (animation.deployState == ModuleDeployablePart.DeployState.EXTENDED) { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } else if (animationGeneric != null) { // only include data rate and ec cost if transmitter is extended if (animationGeneric.animSpeed > 0) { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } // no animation else { rate *= t.DataRate; transmitterCount++; var e = t.DataResourceCost * t.DataRate; ec_transmitter += e; } } } } // if vessel is not loaded else { List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > transmitters; if (!Cache.HasVesselObjectsCache(v, "commnet_bg")) { transmitters = new List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> >(); // find proto transmitters foreach (ProtoPartSnapshot p in v.protoVessel.protoPartSnapshots) { // get part prefab (required for module properties) Part part_prefab = PartLoader.getPartInfoByName(p.partName).partPrefab; foreach (ModuleDataTransmitter t in part_prefab.FindModulesImplementing <ModuleDataTransmitter>()) { transmitters.Add(new KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot>(t, p)); } } Cache.SetVesselObjectsCache(v, "commnet_bg", transmitters); } else { // cache transmitters transmitters = Cache.VesselObjectsCache <List <KeyValuePair <ModuleDataTransmitter, ProtoPartSnapshot> > >(v, "commnet_bg"); } foreach (var pair in transmitters) { ModuleDataTransmitter t = pair.Key; ProtoPartSnapshot p = pair.Value; if (t.antennaType == AntennaType.INTERNAL) // do not include internal data rate, ec cost only { ec += t.DataResourceCost * t.DataRate; } else { // do we have an animation ProtoPartModuleSnapshot m = p.FindModule("ModuleDeployableAntenna") ?? p.FindModule("ModuleAnimateGeneric"); if (m != null) { // only include data rate and ec cost if transmitter is extended string deployState = Lib.Proto.GetString(m, "deployState"); float animSpeed = Lib.Proto.GetFloat(m, "animSpeed"); if (deployState == "EXTENDED" || animSpeed > 0) { rate *= t.DataRate; transmitterCount++; ec_transmitter += t.DataResourceCost * t.DataRate; } } // no animation else { rate *= t.DataRate; transmitterCount++; ec_transmitter += t.DataResourceCost * t.DataRate; } } } } if (transmitterCount > 1) { rate = Math.Pow(rate, 1.0 / transmitterCount); } else if (transmitterCount == 0) { rate = 0; } // when transmitting, transmitters need more EC for the signal amplifiers. // while not transmitting, transmitters only use 10-20% of that ec_transmitter *= transmitting ? Settings.TransmitterActiveEcFactor : Settings.TransmitterPassiveEcFactor; ec += ec_transmitter; Init(v, powered, storm); }
private static List <BackgroundPM> Background_PMs(Vessel v) { var result = Cache.VesselObjectsCache <List <BackgroundPM> >(v, "background"); if (result != null) { return(result); } result = new List <BackgroundPM>(); // 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) { // TODO : this is to migrate pre-3.1 saves using WarpFixer to the new SolarPanelFixer. At some point in the future we can remove this code. if (m.moduleName == "WarpFixer") { MigrateWarpFixer(v, part_prefab, p, m); } // 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; } // get module type // if the type is unknown, skip it Module_type type = ModuleType(m.moduleName); if (type == Module_type.Unknown) { var backgroundDelegate = BackgroundDelegate.Instance(module_prefab); if (backgroundDelegate != null) { type = Module_type.APIModule; } else { continue; } } var entry = new BackgroundPM(); entry.p = p; entry.m = m; entry.module_prefab = module_prefab; entry.part_prefab = part_prefab; entry.type = type; result.Add(entry); } } Cache.SetVesselObjectsCache(v, "background", result); return(result); }
// 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); }