public static void BackgroundUpdate(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, Deploy deploy, Resource_info ec, double elapsed_s) { if (deploy.isConsuming) { ec.Consume(deploy.extra_Cost * elapsed_s); } }
/// <summary> /// This will be called by Kerbalism. See https://github.com/Kerbalism/Kerbalism/wiki/TechGuide-~-C%23-API /// </summary> public static string BackgroundUpdate(Vessel v, ProtoPartSnapshot part_snapshot, ProtoPartModuleSnapshot module_snapshot, PartModule proto_part_module, Part proto_part, Dictionary <string, double> availableResources, List <KeyValuePair <string, double> > resourceChangeRequest, double elapsed_s) { BVController controller = BonVoyage.Instance.GetControllerOfVessel(v); if (controller == null) { return(""); } if (controller.Active) { double requiredPower = Proto.GetDouble(module_snapshot, "requiredPower", 0); resourceChangeRequest.Add(new KeyValuePair <string, double>("ElectricCharge", -requiredPower / 10.0)); } double availableEc; if (availableResources.TryGetValue("ElectricCharge", out availableEc)) { controller.batteries.CurrentEC = availableEc; } if (string.IsNullOrEmpty(localizedTitle)) { localizedTitle = Localizer.Format("#LOC_BV_Autopilot"); } return(localizedTitle); }
public ProtoPartAntenna(ProtoPartModuleSnapshot antenna, ProtoPartSnapshot partSnap, Vessel v, string ModuleName, uint part_id) { this.protoPartSnap = partSnap; this.vessel = v; this.part_id = part_id; if (ModuleName == "ModuleDataTransmitter") { if (partSnap.FindModule("ModuleDeployableAntenna") != null) { this.ModuleName = "ModuleDeployableAntenna"; this.antenna = partSnap.FindModule("ModuleDeployableAntenna"); } else if (partSnap.FindModule("ModuleAnimateGeneric") != null) { this.ModuleName = "ModuleAnimateGeneric"; this.antenna = partSnap.FindModule("ModuleAnimateGeneric"); } else { this.ModuleName = "ModuleDataTransmitter"; this.antenna = antenna; } } else { this.antenna = antenna; this.ModuleName = ModuleName; } }
public ProtoAntenna(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot ppms) { ConfigNode n = new ConfigNode(); ppms.Save(n); Name = p.partInfo.title; try { mTarget = new Guid(n.GetValue("RTAntennaTarget")); DishRange = Single.Parse(n.GetValue("RTDishRange")); DishFactor = Double.Parse(n.GetValue("RTDishFactor")); OmniRange = Single.Parse(n.GetValue("RTOmniRange")); } catch (ArgumentException) { mTarget = Guid.Empty; DishRange = 0.0f; DishFactor = 1.0f; OmniRange = 0.0f; RTUtil.Log("ProtoAntenna parsing error. Default values assumed."); } mProtoPart = p; mProtoModule = ppms; Vessel = v; RTUtil.Log("ProtoAntenna: DishRange: {0}, OmniRange: {1}, Name: {2}, DishTarget: {3})", DishRange, OmniRange, Vessel.vesselName, DishTarget); }
void FindVesselsWithSkylab(Vessel vesselDestroyed = null) { Log.Info("Addon.FindVesselsWithSkylab"); vesselsWithSkylab.Clear(); for (int vesselIdx = 0; vesselIdx < FlightGlobals.Vessels.Count; vesselIdx++) { Vessel v = FlightGlobals.Vessels[vesselIdx]; Log.Info("vesselIdx[" + vesselIdx + "]: " + v.vesselName); if (vesselDestroyed != null && v.persistentId == vesselDestroyed.persistentId) { Log.Info("Ignoring destroyed vessel: " + vesselDestroyed.vesselName); continue; } if (v.packed) { for (int i2 = 0; i2 < v.protoVessel.protoPartSnapshots.Count; i2++) { ProtoPartSnapshot p = v.protoVessel.protoPartSnapshots[i2]; var pms = p.FindModule("SkylabExperiment"); if (pms != null) { vesselsWithSkylab.Add(v); break; } } } } }
/******************************************************************************************** * Function Name: Find_GNSS_Satellites * Parameters: void * Return: void * * Description: Checks if the number of vessels has changed and if so, finds GNSS satellites * among the list of existing vessels. * *********************************************************************************************/ public void Find_GNSS_Satellites() { if (GNSSacronym != NULL_ACRONYM) { return; } if (this.vessel == null) { return; } if (this.vessel.isActiveVessel) { if (FlightGlobals.Vessels.Count != giLastVesselCount) { GNSSSatteliteInfoList.Clear(); //GNSSSatelliteIDs.Clear(); //GNSSSatelliteNames.Clear(); giLastVesselCount = FlightGlobals.Vessels.Count; for (int i = FlightGlobals.Vessels.Count - 1; i >= 0; i--) //foreach (Vessel varVessel in FlightGlobals.Vessels) { Vessel varVessel = FlightGlobals.Vessels[i]; // proceed if vessel being checked has a command pod, is orbiting the same celestial object and is not the active vessel if ((varVessel.isCommandable) && (vessel.mainBody == varVessel.mainBody) && (varVessel != vessel)) { for (int x = varVessel.protoVessel.protoPartSnapshots.Count - 1; x >= 0; x--) //foreach (ProtoPartSnapshot varPart in varVessel.protoVessel.protoPartSnapshots) { ProtoPartSnapshot varPart = varVessel.protoVessel.protoPartSnapshots[x]; if (varPart.partName.GetHashCode() == giTransmitterID) { double gpsRange = 0; for (int im = varPart.modules.Count - 1; im >= 0; im--) //foreach (ProtoPartModuleSnapshot m in varPart.modules) { ProtoPartModuleSnapshot m = varPart.modules[im]; if (m.moduleName == "ModuleGPSTransmitter") { string r = "500000"; m.moduleValues.TryGetValue("gpsRange", ref r); gpsRange = Double.Parse(FileIO.SafeLoad(r, 500000f)); } } if (CheckForEC(varVessel)) { GNSSSatteliteInfoList.Add(new GNSSSatelliteInfo(varVessel.name, varVessel.id, gpsRange)); //GNSSSatelliteNames.Add(varVessel.name); //GNSSSatelliteIDs.Add(varVessel.id); break; } } } } } } } }
/// <summary> /// Add or remove crew from a part based on the part snapshot /// </summary> private static bool AdjustCrewMembersInPart(Part part, ProtoPartSnapshot partSnapshot) { if (part.protoModuleCrew.Count != partSnapshot.protoModuleCrew.Count) { MembersToAdd.Clear(); MembersToRemove.Clear(); MembersToAdd.AddRange(partSnapshot.protoModuleCrew.Where(mp => part.protoModuleCrew.All(m => m.name != mp.name))); MembersToRemove.AddRange(part.protoModuleCrew.Select(c => c.name).Except(partSnapshot.protoModuleCrew.Select(c => c.name))); foreach (var memberToAdd in MembersToAdd) { part.AddCrewmember(memberToAdd); } foreach (var memberToRemove in MembersToRemove) { var member = part.protoModuleCrew.First(c => c.name == memberToRemove); part.RemoveCrewmember(member); } return(true); } return(false); }
static double CurvedPanelOutput(Vessel vessel, ProtoPartSnapshot part, Part prefab, Vector3d sun_dir, double sun_dist, double atmo_factor) { // if, for whatever reason, sun_dist is zero (or negative), we do not return any output if (sun_dist <= double.Epsilon) return 0.0; // shortcuts Quaternion rot = part.rotation; // get values from part string transform_name = part.partData.GetValue("PanelTransformName"); float k = Convert.ToSingle(part.partData.GetValue("chargePerTransform")); // get components Transform[] components = prefab.FindModelTransforms(transform_name); if (components.Length == 0) return 0.0; // calculate solar flux double solar_flux = Sim.SolarFlux(sun_dist); // reduce solar flux inside atmosphere solar_flux *= atmo_factor; // normalize against solar flux at home solar_flux /= Sim.SolarFluxAtHome(); solar_flux *= k; // for each one of the components the curved panel is composed of double output = 0.0; foreach(Transform t in prefab.FindModelTransforms(transform_name)) { double cosine_factor = Math.Max(Vector3d.Dot(sun_dir, (vessel.transform.rotation * rot * t.forward).normalized), 0.0); output += cosine_factor * solar_flux; } return output; }
private static ConfigNode GetNodeForPart(ProtoPartSnapshot p) { ConfigNode node = new ConfigNode("PART"); p.Save(node); return(node); }
public SatSettingNode(ProtoPartModuleSnapshot s, Vessel v, ProtoPartSnapshot sn) { this.protoPartModule = s; this.vessel = v; this.snapshot = sn; isLoaded = false; ConfigNode n = new ConfigNode(); protoPartModule.Save(n); if (n.HasValue("pointedAt")) this.pointedAt = new Target(n.GetValue("pointedAt")); else this.pointedAt = new Target(); if (n.HasValue("dishRange")) this.dishRange = float.Parse(n.GetValue("dishRange")); else this.dishRange = 0; if (n.HasValue("antennaName")) this.antennaName = n.GetValue("antennaName"); for (int i = 0; i < RTGlobals.targets.Count; i++) { if (pointedAt.Equals(RTGlobals.targets[i])) { selectedTarget = i; break; } } }
public ProtoAntenna(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot ppms) { ConfigNode n = new ConfigNode(); ppms.Save(n); Name = p.partInfo.title; Consumption = 0; Guid = v.id; mProtoPart = p; mProtoModule = ppms; try { mDishTarget = new Guid(n.GetValue("RTAntennaTarget")); } catch (ArgumentException) { mDishTarget = Guid.Empty; } double temp_double; float temp_float; bool temp_bool; Dish = Single.TryParse(n.GetValue("RTDishRange"), out temp_float) ? temp_float : 0.0f; CosAngle = Double.TryParse(n.GetValue("RTDishCosAngle"), out temp_double) ? temp_double : 0.0; Omni = Single.TryParse(n.GetValue("RTOmniRange"), out temp_float) ? temp_float : 0.0f; Powered = Boolean.TryParse(n.GetValue("IsRTPowered"), out temp_bool) ? temp_bool : false; Activated = Boolean.TryParse(n.GetValue("IsRTActive"), out temp_bool) ? temp_bool : false; RTLog.Notify(ToString()); }
// 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); } }
public static void BackgroundUpdate(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, Reliability reliability) { // if it has not malfunctioned if (!Lib.Proto.GetBool(m, "broken")) { // get time of next failure double next = Lib.Proto.GetDouble(m, "next"); // get quality bool quality = Lib.Proto.GetBool(m, "quality"); // calculate epoch of failure if necessary if (next <= double.Epsilon) { double last = Planetarium.GetUniversalTime(); next = last + reliability.mtbf * (quality ? Settings.QualityScale : 1.0) * 2.0 * Lib.RandomDouble(); Lib.Proto.Set(m, "last", last); Lib.Proto.Set(m, "next", next); } // if it has failed, trigger malfunction if (Planetarium.GetUniversalTime() > next) { ProtoBreak(v, p, m); } } }
public static void BackgroundUpdate(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, Laboratory lab, resource_info ec, double elapsed_s) { // if enabled if (Lib.Proto.GetBool(m, "running")) { // if a researcher is not required, or the researcher is present CrewSpecs researcher_cs = new CrewSpecs(lab.researcher); if (!researcher_cs || researcher_cs.check(p.protoModuleCrew)) { // get sample to analyze string sample_filename = next_sample(v); // if there is a sample to analyze if (sample_filename.Length > 0) { // consume EC ec.Consume(lab.ec_rate * elapsed_s); // if there was ec // - comparing against amount in previous simulation step if (ec.amount > double.Epsilon) { // analyze the sample analyze(v, sample_filename, lab.analysis_rate * elapsed_s); } } } } }
static void ProcessLight(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleLight light, resource_info ec, double elapsed_s) { if (light.useResources && Lib.Proto.GetBool(m, "isOn")) { ec.Consume(light.resourceAmount * elapsed_s); } }
// 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. static void MigrateWarpFixer(Vessel v, Part prefab, ProtoPartSnapshot p, ProtoPartModuleSnapshot m) { ModuleDeployableSolarPanel panelModule = prefab.FindModuleImplementing <ModuleDeployableSolarPanel>(); ProtoPartModuleSnapshot protoPanelModule = p.modules.Find(pm => pm.moduleName == "ModuleDeployableSolarPanel"); if (panelModule == null || protoPanelModule == null) { Lib.Log("Vessel " + v.name + " has solar panels that can't be converted automatically following Kerbalism 3.1 update. Load it to fix the issue."); return; } SolarPanelFixer.PanelState state = SolarPanelFixer.PanelState.Unknown; string panelStateStr = Lib.Proto.GetString(protoPanelModule, "deployState"); if (!Enum.IsDefined(typeof(ModuleDeployablePart.DeployState), panelStateStr)) { return; } ModuleDeployablePart.DeployState panelState = (ModuleDeployablePart.DeployState)Enum.Parse(typeof(ModuleDeployablePart.DeployState), panelStateStr); if (panelState == ModuleDeployablePart.DeployState.BROKEN) { state = SolarPanelFixer.PanelState.Broken; } else if (!panelModule.isTracking) { state = SolarPanelFixer.PanelState.Static; } else { switch (panelState) { case ModuleDeployablePart.DeployState.EXTENDED: if (!panelModule.retractable) { state = SolarPanelFixer.PanelState.ExtendedFixed; } else { state = SolarPanelFixer.PanelState.Extended; } break; case ModuleDeployablePart.DeployState.RETRACTED: state = SolarPanelFixer.PanelState.Retracted; break; case ModuleDeployablePart.DeployState.RETRACTING: state = SolarPanelFixer.PanelState.Retracting; break; case ModuleDeployablePart.DeployState.EXTENDING: state = SolarPanelFixer.PanelState.Extending; break; default: state = SolarPanelFixer.PanelState.Unknown; break; } } m.moduleName = "SolarPanelFixer"; Lib.Proto.Set(m, "state", state); Lib.Proto.Set(m, "persistentFactor", 0.75); Lib.Proto.Set(m, "launchUT", Planetarium.GetUniversalTime()); Lib.Proto.Set(m, "nominalRate", panelModule.chargeRate); }
internal static bool vesselHasPart(Vessel v, List <string> titles) { if (v == null) { return(false); } if (titles.Count <= 0) { return(false); } if (v.loaded) { for (int i = 0; i < v.Parts.Count; i++) { Part p = v.Parts[i]; if (p == null) { continue; } for (int j = 0; j < titles.Count; j++) { string title = titles[j]; if (VesselUtilities.GetPartName(p) == title.Replace('_', '.')) { return(true); } } } } else { for (int i = 0; i < v.protoVessel.protoPartSnapshots.Count; i++) { ProtoPartSnapshot pp = v.protoVessel.protoPartSnapshots[i]; if (pp == null) { continue; } for (int j = 0; j < titles.Count; j++) { string title = titles[j]; if (pp.partName == title.Replace('_', '.')) { return(true); } } } } return(false); }
internal void LoadRootPart() { ProtoPartSnapshot rootProtoPart = protoVessel.protoPartSnapshots[rootIdx]; rootPart = (Part)GameObject.Instantiate(rootProtoPart.partPrefab, vessel.transform.position, vessel.transform.rotation); rootPart.gameObject.SetActive(true); allObjects.Add(rootPart); }
/// <summary> /// Initializes a new instance of the <see cref="AntennaRange.AntennaRelay"/> class. /// </summary> /// <param name="prefabRelay">The module reference underlying this AntennaRelay, /// as an <see cref="AntennaRange.IAntennaRelay"/></param> /// <param name="pps">The prototype partreference on which the module resides.</param> public ProtoAntennaRelay(IAntennaRelay prefabRelay, ProtoPartSnapshot pps) : base(prefabRelay) { this.protoPart = pps; this.Log("constructed ({0})", this.GetType().Name); this.RecalculateMaxRange(); }
static void ProcessConverter(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleResourceConverter converter, vessel_resources resources, double elapsed_s) { // note: ignore stock temperature mechanic of converters // note: ignore autoshutdown // note: using hard-coded crew bonus values from the wiki because the module data make zero sense (DERP ALERT) // note: non-mandatory resources 'dynamically scale the ratios', that is exactly what mandatory resources do too (DERP ALERT) // 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 // note: assume dump overboard is false for all outputs // if active if (Lib.Proto.GetBool(m, "IsActivated")) { // determine if vessel is full of all output resources // note: comparing against previous amount bool full = true; foreach (var or in converter.outputList) { resource_info res = resources.Info(v, or.ResourceName); full &= (res.level >= converter.FillAmount - double.Epsilon); } // if not full if (!full) { // deduce crew bonus int exp_level = -1; if (converter.UseSpecialistBonus) { foreach (ProtoCrewMember c in Lib.CrewList(v)) { if (c.experienceTrait.Effects.Find(k => k.Name == converter.ExperienceEffect) != null) { exp_level = Math.Max(exp_level, c.experienceLevel); } } } double exp_bonus = exp_level < 0 ? 1.0 : 5.0 + (double)exp_level * 4.0; // create and commit recipe resource_recipe recipe = new resource_recipe(); foreach (var ir in converter.inputList) { recipe.Input(ir.ResourceName, ir.Ratio * elapsed_s); } foreach (var or in converter.outputList) { recipe.Output(or.ResourceName, or.Ratio * exp_bonus * elapsed_s); } resources.Transform(recipe); } // undo stock behaviour by forcing last_update_time to now Lib.Proto.Set(m, "lastUpdateTime", Planetarium.GetUniversalTime()); } }
public BackgroundModule(BackgroundFunctionInfo functionInfo, Vessel vessel, ProtoPartSnapshot protoPartSnapshot, ProtoPartModuleSnapshot protoPartModuleSnapshot, Part part, PartModule partModule) { FunctionInfo = functionInfo; Vessel = vessel; ProtoPartSnapshot = protoPartSnapshot; ProtoPartModuleSnapshot = protoPartModuleSnapshot; Part = part; PartModule = partModule; }
public Resource_recipe(ProtoPartSnapshot p, string name) { this.inputs = new List <Entry>(); this.outputs = new List <Entry>(); this.cures = new List <Entry>(); this.left = 1.0; this.unloaded_part = p; this.name = name; }
public static void BackgroundUpdate(Vessel vessel, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, GravityRing ring, Resource_info ec, double elapsed_s) { // if the module is either non-deployable or deployed if (ring.deploy.Length == 0 || Lib.Proto.GetBool(m, "deployed")) { // consume ec ec.Consume(ring.ec_rate * elapsed_s); } }
internal Part LoadPart(ProtoPartSnapshot protoPart) { Part newPart = (Part)GameObject.Instantiate(protoPart.partPrefab, vessel.transform.position, vessel.transform.rotation); if (rootPart != null) { newPart.transform.parent = rootPart.transform; newPart.setParent(rootPart); } else { newPart.transform.parent = vessel.transform; } newPart.transform.localPosition = protoPart.position; newPart.transform.localRotation = protoPart.rotation; newPart.gameObject.SetActive(true); newPart.vessel = vessel; int index = 0; foreach (var module in protoPart.modules) { //if (!blacklist.Contains(module.moduleName)) //{ //Log.Normal("Loaded Module: " + (module.moduleName)); module.Load(newPart, ref index); //} } PartModule[] partModules = newPart.Modules.Cast <PartModule>().ToArray(); foreach (var module in partModules) { if (delayList.Contains(module.moduleName)) { StartCoroutine(CallbackUtil.DelayedCallback(10, DestroyDelayed, module)); } else { if (!blackList.Contains(module.moduleName)) { Log.Normal("Loaded Module: " + (module.moduleName)); module.OnAwake(); module.OnStart(PartModule.StartState.PreLaunch); } newPart.Modules.Remove(module); GameObject.DestroyImmediate(module); } } vessel.parts.Add(newPart); allObjects.Add(newPart); return(newPart); }
public static void BackgroundUpdate(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, Emitter emitter, Resource_info ec, double elapsed_s) { // if enabled, and EC is required if (Lib.Proto.GetBool(m, "running") && emitter.ec_rate > double.Epsilon) { // consume EC ec.Consume(emitter.ec_rate * elapsed_s); } }
public void BackgroundUpdate(VesselData vd, ProtoPartSnapshot protoPart, ProtoPartModuleSnapshot protoModule, double elapsed_s) { if (!ModuleData.TryGetModuleData <ModuleKsmContractEquipment, EquipmentData>(protoModule, out EquipmentData experimentData)) { return; } RunningUpdate(vd.Vessel, vd, experimentData, this, elapsed_s); }
public static Part LoadPartSnapshot(Vessel vessel, ConfigNode node, Vector3 position, Quaternion rotation) { ProtoPartSnapshot snapshot = KAS_Shared.LoadProtoPartSnapshot(node); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID)) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.flagURL = vessel.rootPart.flagURL; // Save properties that may be messed up by new colliders RigidbodyInertia rb_backup = new RigidbodyInertia(vessel.rootPart.rb); Part new_part = snapshot.Load(vessel, false); vessel.Parts.Add(new_part); if (vessel.packed) { GameEvents.onVesselWasModified.Fire(vessel); } else { // Request initialization as nonphysical to prevent explosions new_part.physicalSignificance = Part.PhysicalSignificance.NONE; // Disable all sub-objects with colliders List <Collider> re_enable = new List <Collider>(); foreach (var collider in new_part.GetComponentsInChildren <Collider>()) { if (collider.gameObject.activeSelf) { re_enable.Add(collider); collider.gameObject.SetActive(false); } } new_part.StartCoroutine(WaitAndUnpack(new_part, re_enable)); } rb_backup.Restore(vessel.rootPart.rb); return(new_part); }
public override void Ctrl(bool value) { if (!prefab.toggle) return; Lib.Proto.Set(process_ctrl, "running", value); ProtoPartSnapshot part_prefab = FlightGlobals.FindProtoPartByID(part_id); double capacity = prefab.capacity; var res = part_prefab.resources.Find(k => k.resourceName == prefab.resource); res.amount = value ? capacity : 0.0; }
public ProtoExperimentDevice(Experiment prefab, ProtoPartSnapshot protoPart, ProtoPartModuleSnapshot protoModule, Vessel vessel) : base(prefab, protoPart, protoModule) { this.vessel = vessel; expInfo = ScienceDB.GetExperimentInfo(prefab.experiment_id); icon = new DeviceIcon(expInfo.SampleMass > 0f ? Textures.sample_scicolor : Textures.file_scicolor, "open experiment info", () => new ExperimentPopup(vessel, prefab, protoPart.flightID, prefab.part.partInfo.title, protoModule)); sb = new StringBuilder(); OnUpdate(); }
static void ProcessFissionGenerator(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule fission_generator, resource_info ec, double elapsed_s) { // note: ignore heat double power = Lib.ReflectionValue <float>(fission_generator, "PowerGeneration"); var reactor = p.modules.Find(k => k.moduleName == "FissionReactor"); double tweakable = reactor == null ? 1.0 : Lib.ConfigValue(reactor.moduleValues, "CurrentPowerPercent", 100.0) * 0.01; ec.Produce(power * tweakable * elapsed_s); }
internal ProtoPartSnapshotNode(ProtoPartSnapshot protoPart, ProtoPartSnapshotNode parentNode) { part = protoPart; parent = parentNode; children = new List <ProtoPartSnapshotNode>(); if (parent != null) { parent.AddChild(this); } }
static void ProcessConverter(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, ModuleResourceConverter converter, VesselResources resources, double elapsed_s) { // note: ignore stock temperature mechanic of converters // note: ignore auto shutdown // note: non-mandatory resources 'dynamically scale the ratios', that is exactly what mandatory resources do too (DERP ALERT) // note: 'undo' stock behavior by forcing lastUpdateTime to now (to minimize overlapping calculations from this and stock post-facto simulation) // if active if (Lib.Proto.GetBool(m, "IsActivated")) { // determine if vessel is full of all output resources // note: comparing against previous amount bool full = true; foreach (var or in converter.outputList) { ResourceInfo res = resources.GetResource(v, or.ResourceName); full &= (res.Level >= converter.FillAmount - double.Epsilon); } // if not full if (!full) { // deduce crew bonus int exp_level = -1; if (converter.UseSpecialistBonus) { foreach (ProtoCrewMember c in Lib.CrewList(v)) { if (c.experienceTrait.Effects.Find(k => k.Name == converter.ExperienceEffect) != null) { exp_level = Math.Max(exp_level, c.experienceLevel); } } } double exp_bonus = exp_level < 0 ? converter.EfficiencyBonus * converter.SpecialistBonusBase : converter.EfficiencyBonus * (converter.SpecialistBonusBase + (converter.SpecialistEfficiencyFactor * (exp_level + 1))); // create and commit recipe ResourceRecipe recipe = new ResourceRecipe(ResourceBroker.StockConverter); foreach (var ir in converter.inputList) { recipe.AddInput(ir.ResourceName, ir.Ratio * exp_bonus * elapsed_s); } foreach (var or in converter.outputList) { recipe.AddOutput(or.ResourceName, or.Ratio * exp_bonus * elapsed_s, or.DumpExcess); } resources.AddRecipe(recipe); } // undo stock behavior by forcing last_update_time to now Lib.Proto.Set(m, "lastUpdateTime", Planetarium.GetUniversalTime()); } }
static void ProcessRadioisotopeGenerator(Vessel v, ProtoPartSnapshot p, ProtoPartModuleSnapshot m, PartModule radioisotope_generator, resource_info ec, double elapsed_s) { // note: doesn't support easy mode double power = Lib.ReflectionValue <float>(radioisotope_generator, "BasePower"); double half_life = Lib.ReflectionValue <float>(radioisotope_generator, "HalfLife"); double mission_time = v.missionTime / (3600.0 * Lib.HoursInDay() * Lib.DaysInYear()); double remaining = Math.Pow(2.0, (-mission_time) / half_life); ec.Produce(power * remaining * elapsed_s); }
InternalModel GetInternal(ProtoPartSnapshot ppart) { InternalModel ip = null; if (ppart.partInfo.internalConfig != null) { var iname = ppart.partInfo.internalConfig.GetValue ("name"); if (iname != null && iname != "") { ip = PartLoader.GetInternalPart (iname); } } return ip; }
//add some crew to a part public static bool addCrew(ProtoPartSnapshot p, List<ProtoCrewMember> crew) { if(crew.Count == 0) return false; if(p.partInfo.partPrefab.CrewCapacity <= p.protoModuleCrew.Count) return false; while(p.protoModuleCrew.Count < p.partInfo.partPrefab.CrewCapacity && crew.Count > 0) { var kerbal = crew[0]; kerbal.rosterStatus = ProtoCrewMember.RosterStatus.Assigned; p.protoCrewNames.Add(kerbal.name); p.protoModuleCrew.Add(kerbal); crew.RemoveAt(0); } return true; }
public static List<ResourceModuleHandler> GetResourceGenerationData( PartModule m, ProtoPartSnapshot part, Dictionary<String, List<ResourceModuleHandler>> resourceData, HashSet<String> interestingResources ) { List<ResourceModuleHandler> ret = new List<ResourceModuleHandler>(); ModuleCommand c = (ModuleCommand)m; foreach (ModuleResource mr in c.inputResources) { if (interestingResources.Contains(mr.name)) { ret.Add(new Command(mr.name, (float)-mr.rate)); } } return ret; }
public static Part SpawnPart(this AvailablePart availablePart, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 angularVelocity) { ProtoPartSnapshot snapshot = new ProtoPartSnapshot(availablePart.partPrefab, null); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.connected = true; Part newPart = snapshot.Load(FlightGlobals.ActiveVessel, false); newPart.transform.position = position; newPart.transform.rotation = rotation; FlightGlobals.ActiveVessel.Parts.Add(newPart); newPart.physicalSignificance = Part.PhysicalSignificance.NONE; newPart.PromoteToPhysicalPart(); newPart.Unpack(); newPart.InitializeModules(); newPart.rigidbody.velocity = velocity; newPart.rigidbody.angularVelocity = angularVelocity; newPart.decouple(); newPart.vessel.vesselType = VesselType.Unknown; newPart.vessel.vesselName = availablePart.title; return newPart; }
public static List<ResourceModuleHandler> GetResourceGenerationData( PartModule m, ProtoPartSnapshot part, Dictionary<String, List<ResourceModuleHandler>> resourceData, HashSet<String> interestingResources ) { List<ResourceModuleHandler> ret = new List<ResourceModuleHandler>(); ModuleGenerator g = (ModuleGenerator)m; if (g.inputList.Count <= 0) { foreach (ModuleResource gr in g.outputList) { if (interestingResources.Contains(gr.name)) { ret.Add(new Generator(gr.name, (float)gr.rate)); } } } return ret; }
private bool payloadCarrierFound(ProtoPartSnapshot payloadCarrier, AvailablePart experiment, CelestialBody targetBody, double contractAccepted) { NE_Helper.log("ProtoVessel recovery: payload carrier found"); string experiementModuleName = experimentModulname[experiment.name]; foreach (ProtoPartModuleSnapshot module in payloadCarrier.modules) { NE_Helper.log("ProtoVessel recovery Modulename: " + module.moduleName); if (module.moduleName == KAS_CONTAINER) { NE_Helper.log("KAS container found"); ConfigNode partConf = findExperimentModulInPC(module, experiment); if (partConf != null) { NE_Helper.log("Experiment module found"); float completed = getFloatValueFromConfigNode(partConf, OMSExperiment.COMPLETED); if (completed >= contractAccepted) { return containsDoneExperimentData(partConf, targetBody); } } } } return false; }
public static ConfigNode PartSnapshot(Part part) { ConfigNode node = new ConfigNode("PART"); ProtoPartSnapshot snapshot = null; try { // Seems fine with a null vessel in 0.23 if some empty lists are allocated below snapshot = new ProtoPartSnapshot(part, null); } catch { // workaround for command module KIS_Shared.DebugWarning("Error during part snapshot, spawning part for snapshot (workaround for command module)"); Part p = (Part)UnityEngine.Object.Instantiate(part.partInfo.partPrefab); p.gameObject.SetActive(true); p.name = part.partInfo.name; p.InitializeModules(); snapshot = new ProtoPartSnapshot(p, null); UnityEngine.Object.Destroy(p.gameObject); } snapshot.attachNodes = new List<AttachNodeSnapshot>(); snapshot.srfAttachNode = new AttachNodeSnapshot("attach,-1"); snapshot.symLinks = new List<ProtoPartSnapshot>(); snapshot.symLinkIdxs = new List<int>(); snapshot.Save(node); // Prune unimportant data node.RemoveValues("parent"); node.RemoveValues("position"); node.RemoveValues("rotation"); node.RemoveValues("istg"); node.RemoveValues("dstg"); node.RemoveValues("sqor"); node.RemoveValues("sidx"); node.RemoveValues("attm"); node.RemoveValues("srfN"); node.RemoveValues("attN"); node.RemoveValues("connected"); node.RemoveValues("attached"); node.RemoveValues("flag"); node.RemoveNodes("ACTIONS"); // Remove modules that are not in prefab since they won't load anyway var module_nodes = node.GetNodes("MODULE"); var prefab_modules = part.partInfo.partPrefab.GetComponents<PartModule>(); node.RemoveNodes("MODULE"); for (int i = 0; i < prefab_modules.Length && i < module_nodes.Length; i++) { var module = module_nodes[i]; var name = module.GetValue("name") ?? ""; node.AddNode(module); if (name == "KASModuleContainer") { // Containers get to keep their contents module.RemoveNodes("EVENTS"); } else if (name.StartsWith("KASModule")) { // Prune the state of the KAS modules completely module.ClearData(); module.AddValue("name", name); continue; } module.RemoveNodes("ACTIONS"); } return node; }
public static Part CreatePart(ConfigNode partConfig, Vector3 position, Quaternion rotation, Part fromPart, Part coupleToPart = null, string srcAttachNodeID = null, AttachNode tgtAttachNode = null, OnPartCoupled onPartCoupled = null) { ConfigNode node_copy = new ConfigNode(); partConfig.CopyTo(node_copy); ProtoPartSnapshot snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID) || snapshot.flightID == 0) { snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); } snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.connected = true; snapshot.flagURL = fromPart.flagURL; Part newPart = snapshot.Load(fromPart.vessel, false); newPart.transform.position = position; newPart.transform.rotation = rotation; newPart.missionID = fromPart.missionID; fromPart.vessel.Parts.Add(newPart); newPart.physicalSignificance = Part.PhysicalSignificance.NONE; newPart.PromoteToPhysicalPart(); newPart.Unpack(); newPart.InitializeModules(); if (coupleToPart) { newPart.rigidbody.velocity = coupleToPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = coupleToPart.rigidbody.angularVelocity; } else { if (fromPart.rigidbody) { newPart.rigidbody.velocity = fromPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = fromPart.rigidbody.angularVelocity; } else { // If fromPart is a carried container newPart.rigidbody.velocity = fromPart.vessel.rootPart.rigidbody.velocity; newPart.rigidbody.angularVelocity = fromPart.vessel.rootPart.rigidbody.angularVelocity; } } newPart.decouple(); if (coupleToPart) { newPart.StartCoroutine(WaitAndCouple(newPart, coupleToPart, srcAttachNodeID, tgtAttachNode, onPartCoupled)); } else { newPart.vessel.vesselType = VesselType.Unknown; //name container ModuleKISInventory inv = newPart.GetComponent<ModuleKISInventory>(); if (inv) { if (inv.invName != "") { newPart.vessel.vesselName = inv.part.partInfo.title + " | " + inv.invName; } else { newPart.vessel.vesselName = inv.part.partInfo.title; } } } return newPart; }
public static void AddPartToInventory(ProtoPartSnapshot part) { string name = part.partInfo.name; int amt = 1; if (KCT_Utilities.PartIsProcedural(part)) { float cost = part.partInfo.cost + part.moduleCosts; KCTDebug.Log("PP cost: " + cost); foreach (ProtoPartResourceSnapshot resource in part.resources) { cost -= (float)(PartResourceLibrary.Instance.GetDefinition(resource.resourceName).unitCost * float.Parse(resource.resourceValues.GetValue("amount"))); } KCTDebug.Log("After fuel costs: " + cost); amt = (int)(cost * 1000); AddPartToInventory(name, amt); return; } else { string tweakscale = GetTweakScaleSize(part); //partName,tweakscale name += tweakscale; AddPartToInventory(name, amt); return; } }
public float getPartRawPrice(ProtoPartSnapshot P) { float dryCost, fuelCost; ShipConstruction.GetPartCosts(P, P.partInfo, out dryCost, out fuelCost); return dryCost; }
public static ConfigNode SavePartSnapshot(Part part) { // Seems fine with a null vessel in 0.23 if some empty lists are allocated below ProtoPartSnapshot snapshot = new ProtoPartSnapshot(part, null); ConfigNode node = new ConfigNode("CONTENT_PART"); snapshot.attachNodes = new List<AttachNodeSnapshot>(); snapshot.srfAttachNode = new AttachNodeSnapshot("attach,-1"); snapshot.symLinks = new List<ProtoPartSnapshot>(); snapshot.symLinkIdxs = new List<int>(); snapshot.Save(node); node.AddValue("kas_total_mass", part.mass+part.GetResourceMass()); // Prune unimportant data node.RemoveValues("parent"); node.RemoveValues("position"); node.RemoveValues("rotation"); node.RemoveValues("istg"); node.RemoveValues("dstg"); node.RemoveValues("sqor"); node.RemoveValues("sidx"); node.RemoveValues("attm"); node.RemoveValues("srfN"); node.RemoveValues("attN"); node.RemoveValues("connected"); node.RemoveValues("attached"); node.RemoveValues("flag"); node.RemoveNodes("ACTIONS"); // Remove modules that are not in prefab since they won't load anyway var module_nodes = node.GetNodes("MODULE"); var prefab_modules = part.partInfo.partPrefab.GetComponents<PartModule>(); node.RemoveNodes("MODULE"); for (int i = 0; i < prefab_modules.Length && i < module_nodes.Length; i++) { var module = module_nodes[i]; var name = module.GetValue("name") ?? ""; node.AddNode(module); if (name == "KASModuleContainer") { // Containers get to keep their contents module.RemoveNodes("EVENTS"); } else if (name.StartsWith("KASModule")) { // Prune the state of the KAS modules completely module.ClearData(); module.AddValue("name", name); continue; } module.RemoveNodes("ACTIONS"); } return node; }
public static bool PartIsProcedural(ProtoPartSnapshot part) { if (part.modules != null) return part.modules.Find(m => m != null && m.moduleName != null && m.moduleName.ToLower().Contains("procedural")) != null; return false; }
private bool isKasContainerPart(ProtoPartSnapshot part) { foreach (ProtoPartModuleSnapshot module in part.modules) { NE_Helper.log("ProtoVessel recovery Modulename: " + module.moduleName); if (module.moduleName == KAS_CONTAINER) { return true; } } return false; }
protected bool experimentFound(ProtoPartSnapshot part, AvailablePart experiment, CelestialBody targetBody, double contractAccepted) { NE_Helper.log("ProtoVessel recovery: Experiment found"); string moduleName = experimentModulname[experiment.name]; foreach (ProtoPartModuleSnapshot module in part.modules) { NE_Helper.log("ProtoVessel recovery Modulename: " + module.moduleName); if (module.moduleName == moduleName) { ConfigNode partConf = module.moduleValues; float completed = getFloatValueFromConfigNode(partConf, OMSExperiment.COMPLETED); if (completed >= contractAccepted) { return containsDoneExperimentData(partConf, targetBody); } } } return false; }
public static Part LoadPartSnapshot(Vessel vessel, ConfigNode node, Vector3 position, Quaternion rotation) { ConfigNode node_copy = new ConfigNode(); node.CopyTo(node_copy); node_copy.RemoveValues("kas_total_mass"); ProtoPartSnapshot snapshot = new ProtoPartSnapshot(node_copy, null, HighLogic.CurrentGame); if (HighLogic.CurrentGame.flightState.ContainsFlightID(snapshot.flightID)) snapshot.flightID = ShipConstruction.GetUniqueFlightID(HighLogic.CurrentGame.flightState); snapshot.parentIdx = 0; snapshot.position = position; snapshot.rotation = rotation; snapshot.stageIndex = 0; snapshot.defaultInverseStage = 0; snapshot.seqOverride = -1; snapshot.inStageIndex = -1; snapshot.attachMode = (int)AttachModes.SRF_ATTACH; snapshot.attached = true; snapshot.connected = true; snapshot.flagURL = vessel.rootPart.flagURL; // Save properties that may be messed up by new colliders RigidbodyInertia rb_backup = new RigidbodyInertia(vessel.rootPart.rb); Part new_part = snapshot.Load(vessel, false); vessel.Parts.Add(new_part); if (vessel.packed) { GameEvents.onVesselWasModified.Fire(vessel); } else { // Request initialization as nonphysical to prevent explosions new_part.physicalSignificance = Part.PhysicalSignificance.NONE; // Disable all sub-objects with colliders List<Collider> re_enable = new List<Collider>(); foreach (var collider in new_part.GetComponentsInChildren<Collider>()) { if (collider.gameObject.activeSelf) { re_enable.Add(collider); collider.gameObject.SetActive(false); } } new_part.StartCoroutine(WaitAndUnpack(new_part, re_enable)); } rb_backup.Restore(vessel.rootPart.rb); return new_part; }
public string NameWithTS(ProtoPartSnapshot PPS) { string tweakscaleSize = GetTweakScaleSize(PPS); return PPS.partInfo.name + (tweakscaleSize != "" ? "," + tweakscaleSize : ""); }
public static string GetTweakScaleSize(ProtoPartSnapshot part) { string partSize = ""; if (part.modules != null) { ProtoPartModuleSnapshot tweakscale = part.modules.Find(mod => mod.moduleName == "TweakScale"); if (tweakscale != null) { ConfigNode tsCN = tweakscale.moduleValues; string defaultScale = tsCN.GetValue("defaultScale"); string currentScale = tsCN.GetValue("currentScale"); if (!defaultScale.Equals(currentScale)) partSize = "," + currentScale; } } return partSize; }
private ConfigNode GetNodeForPart(ProtoPartSnapshot p) { ConfigNode node = new ConfigNode("PART"); p.Save(node); return node; }
private void CrewTestProto(int REASON, ProtoPartSnapshot p, double l) { int CUR_CWLS = IFICWLS; CUR_CWLS += (Convert.ToInt16(l) * 10); float rand; ProtoCrewMember iCrew; for (int i = 0; i < p.protoModuleCrew.Count; i++) { rand = UnityEngine.Random.Range(0.0f, 100.0f); IFIDebug.IFIMess("!!!!!!!!"); IFIDebug.IFIMess("Testing Crew Death Crewmember=" + p.protoModuleCrew[i].name); IFIDebug.IFIMess("Crew Death Chance = " + Convert.ToString(CUR_CWLS)); IFIDebug.IFIMess("Crew Death Roll = " + Convert.ToString(rand)); IFIDebug.IFIMess("!!!!!!!!"); if (CUR_CWLS > rand) { iCrew = p.protoModuleCrew[i]; iCrew.rosterStatus = ProtoCrewMember.RosterStatus.Dead; p.RemoveCrew(iCrew); IFIDebug.IFIMess(p.pVesselRef.vesselName + " POD Kerbal Killed due to no LS - " + iCrew.name); string message = ""; message += p.pVesselRef.vesselName + "\n\n"; message += iCrew.name + "\n Was killed due to ::"; message += "No Life Support Remaining"; message += "::"; MessageSystem.Message m = new MessageSystem.Message("Kerbal Death from LifeSupport Failure", message, MessageSystemButton.MessageButtonColor.RED, MessageSystemButton.ButtonIcons.ALERT); MessageSystem.Instance.AddMessage(m); } } }