/// <summary> /// Update state of all experiment observers. If their status has /// changed, UpdateStatus will return true. /// </summary> /// <returns></returns> private System.Collections.IEnumerator UpdateObservers() { while (true) { if (!FlightGlobals.ready || FlightGlobals.ActiveVessel == null) { yield return(0); continue; } // if any new experiments become available, our state // changes (remember: observers return true only if their observed // experiment wasn't available before and just become available this update) var expSituation = ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel); foreach (var observer in observers) { try { #if PROFILE float start = Time.realtimeSinceStartup; #endif bool newReport = false; // Is exciting new research available? if (observer.UpdateStatus(expSituation, out newReport)) { // if we're timewarping, resume normal time if that setting // was used if (observer.StopWarpOnDiscovery || Settings.Instance.GlobalWarp == Settings.WarpSetting.GlobalOn) { if (Settings.Instance.GlobalWarp != Settings.WarpSetting.GlobalOff) { if (TimeWarp.CurrentRateIndex > 0) { // Simply setting warp index to zero causes some kind of // accuracy problem that can seriously affect the // orbit of the vessel. // // to avoid this, we'll take a snapshot of the orbit // pre-warp and then apply it again after we've changed // the warp rate OrbitSnapshot snap = new OrbitSnapshot(FlightGlobals.ActiveVessel.GetOrbitDriver().orbit); TimeWarp.SetRate(0, true); FlightGlobals.ActiveVessel.GetOrbitDriver().orbit = snap.Load(); FlightGlobals.ActiveVessel.GetOrbitDriver().orbit.UpdateFromUT(Planetarium.GetUniversalTime()); } } } // the button is important; if it's auto-hidden we should // show it to the player scienceAlert.Button.Important = true; if (observer.settings.AnimationOnDiscovery) { scienceAlert.Button.PlayAnimation(); } else if (scienceAlert.Button.IsNormal) { scienceAlert.Button.SetLit(); } switch (Settings.Instance.SoundNotification) { case Settings.SoundNotifySetting.ByExperiment: if (observer.settings.SoundOnDiscovery) { audio.PlayUI("bubbles", 2f); } break; case Settings.SoundNotifySetting.Always: audio.PlayUI("bubbles", 2f); break; } OnExperimentAvailable(observer.Experiment, observer.NextReportValue); } else if (!observers.Any(ob => ob.Available)) { // if no experiments are available, we should be looking // at a starless flask in the menu. Note that this is // in an else statement because if UpdateStatus just // returned true, we know there's at least one experiment // available this frame //Log.Debug("No observers available: resetting state"); scienceAlert.Button.SetUnlit(); scienceAlert.Button.Important = false; } #if PROFILE Log.Warning("Tick time ({1}): {0} ms", (Time.realtimeSinceStartup - start) * 1000f, observer.ExperimentTitle); #endif } catch (Exception e) { Log.Debug("ExperimentManager.UpdateObservers: exception {0}", e); } // if the user accelerated time it's possible to have some // experiments checked too late. If the user is time warping // quickly enough, then we'll go ahead and check every // experiment on every loop if (TimeWarp.CurrentRate < Settings.Instance.TimeWarpCheckThreshold) { yield return(0); // pause until next frame } } // end observer loop yield return(0); } // end infinite while loop }
ExperimentSituations currentSituation() { return(ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel)); }
protected override bool generateScienceData() { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(experimentID); if (experiment == null) { return(false); } if (science_to_add > 0) { result_title = experiment.experimentTitle; result_string = "Science experiments were conducted in the vicinity of " + vessel.mainBody.name + "."; transmit_value = science_to_add; recovery_value = science_to_add; data_size = science_to_add * 1.25f; xmit_scalar = 1; ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(vessel), vessel.mainBody, ""); subject.scienceCap = 167 * PluginHelper.getScienceMultiplier(vessel); //PluginHelper.getScienceMultiplier(vessel.mainBody.flightGlobalsIndex, false); ref_value = subject.scienceCap; science_data = new ScienceData(science_to_add, 1, 0, subject.id, "Science Lab Data"); return(true); } return(false); }
public bool CanRunExperiment(ModuleScienceExperiment baseExperiment, float currentScienceValue) { Log(baseExperiment.experimentID, ": CanRunExperiment"); if (!baseExperiment.experiment.IsAvailableWhile(ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), FlightGlobals.currentMainBody))// { Log(baseExperiment.experimentID, ": Experiment isn't available in the current situation: ", ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), "_", FlightGlobals.currentMainBody + "_", baseExperiment.experiment.situationMask); return(false); } if (baseExperiment.Inoperable) { Log(baseExperiment.experimentID, ": Experiment is inoperable"); return(false); } if (baseExperiment.Deployed && !baseExperiment.rerunnable) { Log(baseExperiment.experimentID, ": Experiment is deployed"); return(false); } if (!baseExperiment.rerunnable && !_AutomatedScienceSamplerInstance.craftSettings.oneTimeOnly) { Log(baseExperiment.experimentID, ": Runing rerunable experiments is disabled"); return(false); } if (currentScienceValue < _AutomatedScienceSamplerInstance.craftSettings.threshold) { Log(baseExperiment.experimentID, ": Science value is less than cutoff threshold: ", currentScienceValue, "<", _AutomatedScienceSamplerInstance.craftSettings.threshold); return(false); } if (baseExperiment.GetData().Length > 0) { Log(baseExperiment.experimentID, ": Experiment already contains results!"); return(false); } if (!baseExperiment.experiment.IsUnlocked()) { Log(baseExperiment.experimentID, ": Experiment is locked"); return(false); } return(true); }
private bool canConduct() { failMessage = ""; ExperimentSituations sit = ScienceUtil.GetExperimentSituation(vessel); if (handler == null) { SEP_Utilities.log("SEP Experiment Handler is null; Stopping any experiments...", logLevels.warning); failMessage = "Whoops, something went wrong with the SEP Experiment"; return(false); } if (Inoperable) { failMessage = "Experiment is no longer functional"; return(false); } else if (!handler.basicExperiment.IsAvailableWhile(sit, vessel.mainBody)) { if (!string.IsNullOrEmpty(situationFailMessage)) { failMessage = situationFailMessage; } return(false); } else if (excludeAtmosphere && vessel.mainBody.atmosphere) { if (!string.IsNullOrEmpty(excludeAtmosphereMessage)) { failMessage = excludeAtmosphereMessage; } return(false); } else if (handler.basicExperiment.requireAtmosphere && !vessel.mainBody.atmosphere) { failMessage = includeAtmosphereMessage; return(false); } else if (!string.IsNullOrEmpty(controllerModule)) { if (!VesselUtilities.VesselHasModuleName(controllerModule, vessel)) { failMessage = controllerModuleMessage; return(false); } } if (requiredPartList.Count > 0) { for (int i = 0; i < requiredPartList.Count; i++) { string partName = requiredPartList[i]; if (string.IsNullOrEmpty(partName)) { continue; } if (!VesselUtilities.VesselHasPartName(partName, vessel)) { failMessage = requiredPartsMessage; return(false); } } } if (requiredModuleList.Count > 0) { for (int i = 0; i < requiredModuleList.Count; i++) { string moduleName = requiredModuleList[i]; if (string.IsNullOrEmpty(moduleName)) { continue; } if (!VesselUtilities.VesselHasModuleName(moduleName, vessel)) { failMessage = requiredModulesMessage; return(false); } } } return(true); }
internal void SetUpActiveExperiment(string expId, string biome, ModuleScienceExperiment exp, string reqResource, double processedResource = 0) { activeExperiment = new ActiveExperiment(expId, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome, exp); ExpStatus es = new ExpStatus(expId, activeExperiment.Key, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome, reqResource, experiments[expId].resourceAmtRequired); es.processedResource = processedResource; es.active = true; expStatuses.Add(es.Key, es); experimentStarted = true; lastUpdateTime = Planetarium.GetUniversalTime(); StartCoroutine(FixedUpdate2()); }
private static string TestForIssues(Vessel v, ScienceExperiment exp, Resource_info ec, Experiment experiment, bool broken, double remainingSampleMass, bool didPrepare, bool isShrouded, string last_subject_id, out string subject_id) { var sit = ScienceUtil.GetExperimentSituation(v); var biome = ScienceUtil.GetExperimentBiome(v.mainBody, v.latitude, v.longitude); subject_id = Science.Generate_subject(exp, v.mainBody, sit, biome); if (broken) { return("broken"); } if (isShrouded && !experiment.allow_shrouded) { return("shrouded"); } bool needsReset = experiment.crew_reset.Length > 0 && !string.IsNullOrEmpty(last_subject_id) && subject_id != last_subject_id; if (needsReset) { return("reset required"); } if (ec.amount < double.Epsilon && experiment.ec_rate > double.Epsilon) { return("no <b>Electricity</b>"); } if (!string.IsNullOrEmpty(experiment.crew_operate)) { var cs = new CrewSpecs(experiment.crew_operate); if (!cs.Check(v)) { return(cs.Warning()); } } if (!experiment.sample_collecting && remainingSampleMass < double.Epsilon && experiment.sample_mass > double.Epsilon) { return("depleted"); } string situationIssue = Science.TestRequirements(experiment.requires, v); if (situationIssue.Length > 0) { return(Science.RequirementText(situationIssue)); } if (!exp.IsAvailableWhile(sit, v.mainBody)) { return("invalid situation"); } if (!didPrepare && !string.IsNullOrEmpty(experiment.crew_prepare)) { return("not prepared"); } var drive = DB.Vessel(v).BestDrive(); double available = experiment.sample_mass < float.Epsilon ? drive.FileCapacityAvailable() : drive.SampleCapacityAvailable(); if (experiment.data_rate * Kerbalism.elapsed_s > available) { return("insufficient storage"); } return(string.Empty); }
/** Determines whether the status of the vessel has changed */ private bool statusHasChanged() { return(FlightGlobals.ActiveVessel.loaded && (curVessel != FlightGlobals.ActiveVessel || curBiome != currentBiome() || expSituation != ScienceUtil.GetExperimentSituation(curVessel) || lastBody != curVessel.mainBody)); }
//This method handles generating the surface or asteroid sample ScienceData private ScienceData sampleData(ModuleAsteroid m) { ScienceExperiment exp = null; ScienceSubject sub = null; ExperimentSituations expSit; ScienceData data = null; string biome = ""; string displayBiome = ""; if (m != null) { exp = asteroidExp; } else { exp = surfaceExp; } if (exp == null) { return(null); } expSit = ScienceUtil.GetExperimentSituation(vessel); if (exp.IsAvailableWhile(expSit, vessel.mainBody)) { if (exp.BiomeIsRelevantWhile(expSit)) { if (!string.IsNullOrEmpty(vessel.landedAt)) { biome = Vessel.GetLandedAtString(vessel.landedAt); displayBiome = Localizer.Format(vessel.displaylandedAt); } else { biome = ScienceUtil.GetExperimentBiome(vessel.mainBody, vessel.latitude, vessel.longitude); displayBiome = Localizer.Format(ScienceUtil.GetExperimentBiomeLocalized(vessel.mainBody, vessel.latitude, vessel.longitude)); } } if (m != null) { sub = ResearchAndDevelopment.GetExperimentSubject(exp, expSit, m.part.partInfo.name + m.part.flightID, m.part.partInfo.title, vessel.mainBody, biome, displayBiome); } else { sub = ResearchAndDevelopment.GetExperimentSubject(exp, expSit, vessel.mainBody, biome, displayBiome); } if (sub == null) { return(null); } data = new ScienceData(exp.baseValue * exp.dataScale, this.xmitDataScalar, 0f, sub.id, sub.title, false, part.flightID); return(data); } return(null); }
public bool CanRunExperiment(ModuleScienceExperiment baseExperiment, float currentScienceValue) { var currentExperiment = baseExperiment as StationExperiment; var isActive = currentExperiment.Events["StartExperiment"].active; if (isActive) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": StationExperiment didn't start yet! You might want to start it manually!"); return(false); } if (StationExperiment.checkBoring(FlightGlobals.ActiveVessel, false)) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": StationExperiment says this location is boring!"); return(false); } if (!currentExperiment.finished() && !isActive) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": StationExperiment isn't finished yet!"); return(false); } if (!currentExperiment.experiment.IsAvailableWhile(ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), FlightGlobals.currentMainBody))// { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Experiment isn't available in the current situation: ", ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), "_", FlightGlobals.currentMainBody + "_", currentExperiment.experiment.situationMask); return(false); } if (currentExperiment.Inoperable) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Experiment is inoperable"); return(false); } if (currentExperiment.Deployed) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Experiment is deployed"); return(false); } if (!currentExperiment.rerunnable && !_AutomatedScienceSamplerInstance.craftSettings.oneTimeOnly) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Runing rerunable experiments is disabled"); return(false); } if (currentScienceValue < _AutomatedScienceSamplerInstance.craftSettings.threshold) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Science value is less than cutoff threshold: ", currentScienceValue, "<", _AutomatedScienceSamplerInstance.craftSettings.threshold); return(false); } if (!currentExperiment.experiment.IsUnlocked()) { _AutomatedScienceSamplerInstance.Log(currentExperiment.experimentID, ": Experiment is locked"); return(false); } return(true); }
public ScienceSubject GetScienceSubject(ModuleScienceExperiment baseExperiment) { //experiment.BiomeIsRelevantWhile return(ResearchAndDevelopment.GetExperimentSubject(baseExperiment.experiment, ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), FlightGlobals.currentMainBody, CurrentBiome(baseExperiment.experiment))); }
private void StartExperiment() { if (clickToDel && Planetarium.GetUniversalTime() - clicktoDelTime > 5) { clickToDel = false; } try { ExperimentSituations vesselSit = ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel); string result = ""; switch (vesselSit) { case ExperimentSituations.InSpaceHigh: result = Localizer.Format("In space high over <<1>>", FlightGlobals.ActiveVessel.mainBody.displayName); break; case ExperimentSituations.InSpaceLow: result = Localizer.Format("In space near <<1>>", FlightGlobals.ActiveVessel.mainBody.displayName); break; } GUILayout.Label("Situation: " + result); exitWarpWhenDone = GUILayout.Toggle((bool)exitWarpWhenDone, "Stop Warp when completed"); GUILayout.Space(height); foreach (Experiment e in Addon.experiments.Values) { double percent = 0; if (_labExp.activeExperiment != null) { if (_labExp.activeExperiment.Key != null && _labExp.expStatuses.ContainsKey(_labExp.activeExperiment.Key) && _labExp.expStatuses[_labExp.activeExperiment.Key].active && _labExp.expStatuses[_labExp.activeExperiment.Key].expId == e.name) { percent = 0.001 + _labExp.expStatuses[_labExp.activeExperiment.Key].processedResource / Addon.experiments[_labExp.activeExperiment.activeExpid].resourceAmtRequired * 100; if (percent < 100f) { if (clickToDel) { _guiLabel = new GUIContent("Click to Cancel: " + e.label + " - " + percent.ToString("F2") + " % completed", e.tooltip); } else { _guiLabel = new GUIContent(e.label + " - " + percent.ToString("F2") + " % completed", e.tooltip); } } else { _guiLabel = new GUIContent(e.label + " - Completed, Click to Finalize", e.tooltip); } GUI.enabled = true; } else { _guiLabel = new GUIContent(e.label, e.tooltip); GUI.enabled = false; } } else { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(e.name); string title = ScienceUtil.GenerateScienceSubjectTitle(experiment, vesselSit, FlightGlobals.ActiveVessel.mainBody); _guiLabel = new GUIContent(e.label, e.tooltip); //var key1 = e.name + "@" + FlightGlobals.ActiveVessel.mainBody.name + vesselSit.ToString(); //var m = ResearchAndDevelopment.GetResults(key1); //if (m == null) m = "(null)"; //Log.Info("Experiment.Key: " + key1 + ", result: " + m); ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, vesselSit, FlightGlobals.ActiveVessel.mainBody, null, null); #if false float maxScience, availScience; Debug.Log("WindowSkylab, subject: " + subject.id); Debug.Log("key1: " + key1); Debug.Log("WindowSkylab, checkExperiment: " + checkExperiment(e.name, experiment.id, vesselSit, FlightGlobals.ActiveVessel.mainBody, "", out maxScience, out availScience)); Debug.Log("maxScience: " + maxScience + ", availScience: " + availScience); #endif } if (GUILayout.Button(_guiLabel, GUILayout.Height(height))) { if (percent == 0) { _labExp.DoScience(e.name); } else { if (percent < 100) { if (clickToDel) { _labExp.expStatuses.Remove(_labExp.activeExperiment.Key); _labExp.activeExperiment = null; clickToDel = false; } else { clickToDel = true; clicktoDelTime = Planetarium.GetUniversalTime(); } } else { _labExp.FinalizeExperiment(); } } } GUI.enabled = true; } } catch (Exception ex) { Log.Error($"WindowSkylab.DisplayExperiments. Error: {ex.Message}\r\n\r\n{ex.StackTrace}"); } }
ExperimentSituations currentSituation() { return(ScienceUtil.GetExperimentSituation(vessel)); }
/// <inheritdoc /> public override ScienceSubject GetScienceSubject(ModuleScienceExperimentWrapper <T> baseExperimentWrapper) { var scienceExperiment = ResearchAndDevelopment.GetExperiment(baseExperimentWrapper.BaseObject.experimentID); Log($"{nameof(GetScienceSubject)} => changed from '{baseExperimentWrapper.BaseObject.experiment?.id ?? "null"}' to '{scienceExperiment.id}')"); var currentBiome = CurrentBiome(baseExperimentWrapper.experiment); var result = ResearchAndDevelopment.GetExperimentSubject(scienceExperiment, ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), FlightGlobals.currentMainBody, currentBiome, ScienceUtil.GetBiomedisplayName(FlightGlobals.currentMainBody, currentBiome)); Log($"{nameof(GetScienceSubject)} results in '{result.id}' / '{result.title}'"); return(result); }
public void Do_SlowUpdate() { if (activeExperiment != null) { double curTime = Planetarium.GetUniversalTime(); double delta = curTime - lastUpdateTime; // Tasks // 1. Make sure experiment situation hasn't changed, if it has, then return // 2. calcualte resource usage // 3. Check to see if exeriment is completed, if so, set a flag string biome, displayBiome; if (vessel.landedAt != string.Empty) { biome = Vessel.GetLandedAtString(vessel.landedAt); displayBiome = Localizer.Format(vessel.displaylandedAt); } else { biome = ScienceUtil.GetExperimentBiome(vessel.mainBody, vessel.latitude, vessel.longitude); displayBiome = ScienceUtil.GetBiomedisplayName(vessel.mainBody, biome); } var curExp = new ActiveExperiment(activeExperiment.activeExpid, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome); if ((object)curExp != null && curExp.Key == activeExperiment.Key) { if (!expStatuses.ContainsKey(activeExperiment.Key)) { Log.Error("Key missing from expStatuses, key: " + activeExperiment.Key); foreach (var e in expStatuses.Keys) { Log.Error("key: " + e); } } double resourceRequest = delta / Planetarium.fetch.fixedDeltaTime; double amtNeeded = Math.Min( experiments[activeExperiment.activeExpid].resourceUsageRate * resourceRequest, experiments[activeExperiment.activeExpid].resourceAmtRequired - expStatuses[activeExperiment.Key].processedResource); amtNeeded = amtNeeded * KCT_Interface.ResearchTimeAdjustment(); //Log.Info("SkylabExperiment, amtNeeded: " + amtNeeded.ToString("F3") + ", activeExperiment.Key: " + activeExperiment.Key + // ", processedResource: " + expStatuses[activeExperiment.Key].processedResource + // ", resourceAmtRequired: " + Addon.experiments[activeExperiment.activeExpid].resourceAmtRequired); double resource = part.RequestResource(experiments[activeExperiment.activeExpid].neededResourceName, amtNeeded); expStatuses[activeExperiment.Key].processedResource += resource; int resourceID = GetResourceID(expStatuses[activeExperiment.Key].reqResource); // part.GetConnectedResourceTotals(resourceID, out double amount, out double maxAmount); expStatuses[activeExperiment.Key].lastTimeUpdated = Planetarium.GetUniversalTime(); if (HighLogic.CurrentGame.Parameters.CustomParams <LTech_1>().exitWarpWhenDone) { var percent = 0.001 + expStatuses[activeExperiment.Key].processedResource / Addon.experiments[activeExperiment.activeExpid].resourceAmtRequired * 100; if (percent >= 100f) { if (TimeWarp.CurrentRateIndex > 0) { StartCoroutine(CancelWarp()); //TimeWarp.fetch.CancelAutoWarp(); //TimeWarp.SetRate(0, true); } } } // var experiment = experiments[activeExperiment.activeExpid]; } else { Log.Info("Situation changed"); Utils.DisplayScreenMsg("Vessel Situation Changed, Experiment Paused"); } // need to decide what to do if something changed lastUpdateTime = curTime; } else if (experimentStarted) { Log.Info("FixedUpdate, activeExperiment is null"); } }
public void Update() { if (Input.GetMouseButtonUp(0)) { resizingWindow = false; } if (resizingWindow) { windowPosition.width = Input.mousePosition.x - windowPosition.x + 10; windowPosition.height = (Screen.height - Input.mousePosition.y) - windowPosition.y + 10; } // using "while" for possibility to "break". So we dont have to use GOTO. using timer to skip frames. while (drawWindow && (lateUpdateTimer < Time.time || lateUpdateTimerCounter > 3)) { lateUpdateTimer = Time.time + 1; ExperimentSituations experimentSituation = ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel); CelestialBody mainbody = FlightGlobals.ActiveVessel.mainBody; string biome; if (FlightGlobals.ActiveVessel.landedAt != string.Empty) { biome = FlightGlobals.ActiveVessel.landedAt; } else { biome = ScienceUtil.GetExperimentBiome(FlightGlobals.ActiveVessel.mainBody, FlightGlobals.ActiveVessel.latitude, FlightGlobals.ActiveVessel.longitude); } if (mainbody == lastMainBody && biome == lastBiome && lastExperimentSituation == experimentSituation && lateUpdateTimerCounter <= 3) { lateUpdateTimer = 0; lateUpdateTimerCounter++; break; } lateUpdateTimerCounter = 0; lastBiome = biome; lastMainBody = mainbody; lastExperimentSituation = experimentSituation; Output.Clear(); OnShip.Clear(); //List<ScienceExperiment> PossibleExperiments = new List<ScienceExperiment>(); //Search for all Science Experiment Modules on vessel, Check experiment available and add in "Output" and "OnShip" foreach (ModuleScienceExperiment moduleScienceExperiment in FlightGlobals.ActiveVessel.FindPartModulesImplementing <ModuleScienceExperiment>()) { string firstExperimentId = moduleScienceExperiment.experimentID; ScienceExperiment scienceExperiment = ResearchAndDevelopment.GetExperiment(firstExperimentId); bool available = scienceExperiment.IsAvailableWhile(experimentSituation, mainbody); if (available) { if (moduleScienceExperiment.Deployed) { foreach (ScienceData scienceData in moduleScienceExperiment.GetData()) { ExperimentView experimentView = new ExperimentView(scienceData); if (!Output.Contains(experimentView)) { Output.Add(experimentView); } OnShip.Add(experimentView); } } { ScienceSubject scienceSubject = LibraryUtils.GetExperimentSubject(scienceExperiment, experimentSituation, mainbody, scienceExperiment.BiomeIsRelevantWhile(experimentSituation) ? biome : ""); ExperimentView experimentView = new ExperimentView(scienceSubject); if (!Output.Contains(experimentView)) { Output.Add(experimentView); } } } } // Check for Kerbals on board. That means we can also use "evaReport", "surfaceSample", "asteroidSample" in EVA. if (FlightGlobals.ActiveVessel.GetCrewCount() > 0) { { string firstExperimentId = "evaReport"; ScienceExperiment scienceExperiment = ResearchAndDevelopment.GetExperiment(firstExperimentId); bool available = scienceExperiment.IsAvailableWhile(experimentSituation, mainbody); if (available) { ScienceSubject scienceSubject = LibraryUtils.GetExperimentSubject(scienceExperiment, experimentSituation, mainbody, scienceExperiment.BiomeIsRelevantWhile(experimentSituation) ? biome : ""); ExperimentView experimentView = new ExperimentView(scienceSubject); if (!Output.Contains(experimentView)) { Output.Add(experimentView); } } } { string firstExperimentId = "surfaceSample"; ScienceExperiment scienceExperiment = ResearchAndDevelopment.GetExperiment(firstExperimentId); bool available = scienceExperiment.IsAvailableWhile(experimentSituation, mainbody); if (available) { ScienceSubject scienceSubject = LibraryUtils.GetExperimentSubject(scienceExperiment, experimentSituation, mainbody, scienceExperiment.BiomeIsRelevantWhile(experimentSituation) ? biome : ""); ExperimentView experimentView = new ExperimentView(scienceSubject); if (!Output.Contains(experimentView)) { Output.Add(experimentView); } } } // Find asteroid that could be used for science. (I hope it will not be too many asteroids, because of linear complexity of this code) ModuleAsteroid[] asteroids = FindObjectsOfType <ModuleAsteroid>(); foreach (ModuleAsteroid asteroid in asteroids) { Vector3 destination3 = asteroid.gameObject.transform.position - FlightGlobals.ActiveVessel.gameObject.transform.position; float unfocusedRange = asteroid.Events["TakeSampleEVAEvent"].unfocusedRange; unfocusedRange *= unfocusedRange; if (destination3.sqrMagnitude < unfocusedRange) { string firstExperimentId = "asteroidSample"; ScienceExperiment scienceExperiment = ResearchAndDevelopment.GetExperiment(firstExperimentId); bool available = scienceExperiment.IsAvailableWhile(experimentSituation, mainbody); if (available) { string asteroidname = asteroid.part.partInfo.name + asteroid.part.flightID; ScienceSubject scienceSubject = LibraryUtils.GetExperimentSubject(scienceExperiment, experimentSituation, asteroidname, "", mainbody, scienceExperiment.BiomeIsRelevantWhile(experimentSituation) ? biome : ""); ExperimentView experimentView = new ExperimentView(scienceSubject); if (!Output.Contains(experimentView)) { Output.Add(experimentView); } } } } } //Search for all Science Containers on vessel and write all found experiments into OnShip list foreach (ModuleScienceContainer moduleScienceContainer in FlightGlobals.ActiveVessel.FindPartModulesImplementing <ModuleScienceContainer>()) { foreach (ScienceData scienceData in moduleScienceContainer.GetData()) { ExperimentView experimentView = new ExperimentView(scienceData); //if (!Output.Contains(experimentView)) Output.Add(experimentView); OnShip.Add(experimentView); } } Output.Sort(); break; } }
internal void DoScience(string expId) { string step = "Start"; string reqResource = experiments[expId].neededResourceName; float reqAmount = 1; try { string msg = string.Empty; //Vessel ves = FlightGlobals.ActiveVessel; Part prt = FlightGlobals.ActiveVessel.rootPart; ModuleScienceExperiment exp = new ModuleScienceExperiment(); if (experiments[expId].xmitDataScalar > 0) { exp.xmitDataScalar = experiments[expId].xmitDataScalar; } Log.Info("DoScience, expId: " + expId + ", xmitDataScalar: " + exp.xmitDataScalar); // Checks step = "Check Boring"; if (Utils.CheckBoring(vessel, true)) { return; } step = "Check CanRun"; if (!Utils.CanRunExperiment(vessel, expId, ref msg)) { Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_LTech_Experiment_002", msg)); return; } #if false step = "Check Insight"; if (Utils.ResourceAvailable(prt, "Insight") < reqInsight) { double current = Utils.ResourceAvailable(prt, "Insight"); double needed = reqInsight - current; Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_LTech_Experiment_003", (int)needed)); return; } #endif step = "Check Resource"; if (Utils.ResourceAvailable(prt, reqResource) < reqAmount) { double current = Utils.ResourceAvailable(prt, reqResource); double needed = reqAmount - current; Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_LTech_Experiment_004", (int)needed, reqResource)); return; } // Experiment step = "Get Experiment"; exp.experimentID = expId; ScienceExperiment labExp = ResearchAndDevelopment.GetExperiment(exp.experimentID); if (labExp == null) { Log.Warning(Localizer.Format("#autoLOC_LTech_Experiment_005", exp.experimentID)); Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_LTech_Experiment_006")); return; } step = "Get Situation"; ExperimentSituations vesselSit = ScienceUtil.GetExperimentSituation(vessel); if (labExp.IsAvailableWhile(vesselSit, vessel.mainBody)) { step = "Get Biome"; string biome, displayBiome; if (vessel.landedAt != string.Empty) { biome = Vessel.GetLandedAtString(vessel.landedAt); displayBiome = Localizer.Format(vessel.displaylandedAt); } else { biome = ScienceUtil.GetExperimentBiome(vessel.mainBody, vessel.latitude, vessel.longitude); displayBiome = ScienceUtil.GetBiomedisplayName(vessel.mainBody, biome); } Log.Info("DoScience, expId: " + expId + "body: " + vessel.mainBody.bodyName + ", ScienceUtil.GetExperimentSituation: " + ScienceUtil.GetExperimentSituation(vessel) + ", biome: " + biome); SetUpActiveExperiment(expId, biome, exp, reqResource); #if false activeExperiment = new ActiveExperiment(expId, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome, exp); // need to add to // internal ExperimentSituations vesselSit; // internal string biome; ExpStatus es = new ExpStatus(expId, activeExperiment.Key, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome, reqResource, experiments[expId].resourceAmtRequired); es.active = true; expStatuses.Add(es.Key, es); experimentStarted = true; StartCoroutine(FixedUpdate2()); #endif } else { Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_238424", labExp.experimentTitle)); Utils.DisplayScreenMsg(Localizer.Format("#autoLOC_LTech_Experiment_007", vesselSit.displayDescription())); } step = "End"; } catch (Exception ex) { Log.Error($"SkylabExperiment.DoScience at step \"{step}\";. Error: {ex}"); } }
// Recalculates the current situation of the active vessel. private void RecalculateSituation( ) { //_logger.Trace( "RecalculateSituation Start" ); var vessel = FlightGlobals.ActiveVessel; if (vessel == null) { if (_currentSituation != null) { _currentSituation = null; if (SituationChanged != null) { SituationChanged(this, null); } } return; } var body = vessel.mainBody; var situation = ScienceUtil.GetExperimentSituation(vessel); var biome = ScienceUtil.GetExperimentBiome(body, vessel.latitude, vessel.longitude); var subBiome = string.IsNullOrEmpty(vessel.landedAt) ? null : Vessel.GetLandedAtString(vessel.landedAt).Replace(" ", ""); var Parts = vessel.FindPartModulesImplementing <IScienceDataContainer>( ); var dataCount = 0; for (var x = 0; x < Parts.Count; x++) { dataCount += Parts[x].GetData( ).Length; } if (_lastDataCount != dataCount) { // _logger.Trace( "Collected new science!" ); _lastDataCount = dataCount; ScheduleExperimentUpdate( ); } if ( _currentSituation != null && _currentSituation.Biome == biome && _currentSituation.ExperimentSituation == situation && _currentSituation.Body.CelestialBody == body && _currentSituation.SubBiome == subBiome ) { return; } var Body = new Body(body); _currentSituation = new Situation(Body, situation, biome, subBiome); if (SituationChanged != null) { SituationChanged(this, new NewSituationData(Body, situation, biome, subBiome)); } //_logger.Trace( "RecalculateSituation Done" ); }
protected void CreateDelegates() { // Filter for celestial bodies if (targetBody != null) { AddParameter(new ParameterDelegate <Vessel>("Destination: " + targetBody.theName, v => VesselExperimentMet(v) && !testMode || v.mainBody == targetBody, true)); } // Filter for biome if (!string.IsNullOrEmpty(biome)) { AddParameter(new ParameterDelegate <Vessel>("Biome: " + biome, v => VesselExperimentMet(v) && !testMode || CheckBiome(v))); } // Filter for situation if (situation != null) { AddParameter(new ParameterDelegate <Vessel>("Situation: " + situation.Value.Print(), v => VesselExperimentMet(v) && !testMode || ScienceUtil.GetExperimentSituation(v) == situation)); } // Filter for location if (location != null) { AddParameter(new ParameterDelegate <Vessel>("Location: " + location, v => VesselExperimentMet(v) && !testMode || (location != BodyLocation.Surface ^ v.LandedOrSplashed), true)); } // Add the actual data collection string experimentStr = string.IsNullOrEmpty(experiment) ? "Any" : ExperimentName(experiment); AddParameter(new ParameterDelegate <Vessel>("Experiment: " + experimentStr, v => testMode || VesselExperimentMet(v), string.IsNullOrEmpty(experiment))); // Filter for recovery if (recoveryMethod != RecoveryMethod.None) { AddParameter(new ParameterDelegate <Vessel>("Recovery: " + recoveryMethod.Print(), v => testMode || (vesselData.ContainsKey(v.id) && vesselData[v.id].recovery))); } }
public static float GetScienceCap(Part part) { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(kBiomeAnalysisID); ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(part.vessel), part.vessel.mainBody, Utils.GetCurrentBiome(part.vessel).name); return(subject.scienceCap); }
public void ShowResults(string experimentID, float amount, ModuleScienceLab lab = null) { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(experimentID); ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(part.vessel), part.vessel.mainBody, Utils.GetCurrentBiome(part.vessel).name); //Kerbin low orbit has a science multiplier of 1. ScienceSubject subjectLEO = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.InSpaceLow, FlightGlobals.GetHomeBody(), ""); //This ensures you can re-run the experiment. subjectLEO.science = 0f; subjectLEO.scientificValue = 1f; //Create science data ScienceData data = new ScienceData(amount, 1f, 0f, subjectLEO.id, subject.title); ShowResults(data, lab); }
public static ScienceData CreateData(Part part, float amount) { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(kBiomeAnalysisID); ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(part.vessel), part.vessel.mainBody, Utils.GetCurrentBiome(part.vessel).name); //Kerbin low orbit has a science multiplier of 1. ScienceSubject subjectLEO = ResearchAndDevelopment.GetExperimentSubject(experiment, ExperimentSituations.InSpaceLow, FlightGlobals.GetHomeBody(), ""); //This ensures you can re-run the experiment. subjectLEO.science = 0f; subjectLEO.scientificValue = 1f; //Create science data ScienceData data = new ScienceData(amount, 1f, 0f, subjectLEO.id, subject.title); return(data); }
public ScienceSubject GetScienceSubject(ModuleScienceExperiment baseExperiment) { string currentBiome = CurrentBiome(baseExperiment.experiment); return(ResearchAndDevelopment.GetExperimentSubject(baseExperiment.experiment, ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel), FlightGlobals.currentMainBody, currentBiome, ScienceUtil.GetBiomedisplayName(FlightGlobals.currentMainBody, currentBiome))); }
protected bool generateScienceData() { Debug.Log("Generating Science Data"); ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(experimentID); if (experiment == null) { Debug.Log("Experiment is null"); return(false); } if (sciencetoadd > 0) { resultTitle = experiment.experimentTitle; resultString = "You keep a very close eye on one of the scoops, counting it's rotations carefully."; transmitValue = sciencetoadd; recoveryValue = sciencetoadd * 0.1f; dataSize = 100f; xmitDataScalar = 1f; ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(vessel), vessel.mainBody, ""); subject.scienceCap = 167 * getScienceMultiplier(vessel.mainBody.flightGlobalsIndex); refValue = subject.scienceCap; scienceData = new ScienceData(sciencetoadd, 1f, 1f, subject.id, "Anemometer Data"); return(true); } return(false); }
public virtual bool CheckCompletion() { float resultRoll = 100f; int totalCount; int index; Part testPart; if (HighLogic.LoadedSceneIsFlight == false) { return(false); } //Might already been completed or failed if (isCompleted) { status = "Completed"; return(true); } else if (experimentFailed) { status = "Failed to yield results"; return(false); } else if (isRunning == false) { status = "Paused"; return(false); } //Default experiment if (experimentID == defaultExperiment) { isCompleted = false; isRunning = false; experimentFailed = false; finalTransfer = false; notificationSent = false; return(false); } //Mininum Crew if (minCrew > 0) { if (this.part.vessel.GetCrewCount() < minCrew) { status = "Needs " + minCrew.ToString() + " crew"; return(false); } } //Celestial bodies if (string.IsNullOrEmpty(celestialBodies) == false) { if (celestialBodies.Contains(this.part.vessel.mainBody.displayName) == false) { status = "Needs one: " + celestialBodies; return(false); } } //Solar orbit if (solarOrbitRequired) { if (this.part.vessel.mainBody.scaledBody.GetComponentsInChildren <SunShaderController>(true).Length == 0) { return(false); } } //Flight states if (string.IsNullOrEmpty(situations) == false) { string situation = this.part.vessel.situation.ToString().ToUpper(); string experimentSituations = this.situations.ToUpper(); if (experimentSituations.Contains(situation) == false) { status = "Needs one: " + situations; return(false); } } //Space situations if (string.IsNullOrEmpty(spaceSituations) == false) { string expSit = ScienceUtil.GetExperimentSituation(this.part.vessel).ToString().ToUpper(); if (spaceSituations.Contains(expSit) == false) { if (spaceSituations.Contains("INSPACELOW")) { status = "Needs In Space Low"; } else if (spaceSituations.Contains("INSPACEHIGH")) { status = "Needs In Space High"; } return(false); } } //Min altitude if (minAltitude > 0.001f) { if (this.part.vessel.altitude <= minAltitude) { status = string.Format("Needs min altitude: {0:f2}m", minAltitude); return(false); } } //Max altitude if (maxAltitude > 0.001f) { if (this.part.vessel.altitude >= maxAltitude) { status = string.Format("Max acceptable altitude: {0:f2}m", maxAltitude); return(false); } } //Asteroid Mass if (minimumAsteroidMass > 0.001f) { List <ModuleAsteroid> asteroidList = this.part.vessel.FindPartModulesImplementing <ModuleAsteroid>(); ModuleAsteroid[] asteroids = asteroidList.ToArray(); ModuleAsteroid asteroid; float largestAsteroidMass = 0f; //No asteroids? That's a problem! if (asteroidList.Count == 0) { status = string.Format("Needs Asteroid of {0:f2}mt", minimumAsteroidMass); return(false); } //Find the most massive asteroid for (index = 0; index < asteroids.Length; index++) { asteroid = asteroids[index]; if (asteroid.part.mass > largestAsteroidMass) { largestAsteroidMass = asteroid.part.mass; } } //Make sure we have an asteroid of sufficient mass. if (largestAsteroidMass < minimumAsteroidMass) { status = string.Format("Needs Asteroid of {0:f2}mt", minimumAsteroidMass); return(false); } } //Required parts if (string.IsNullOrEmpty(partsList) == false) { int partCount = this.part.vessel.Parts.Count; if (currentPartCount != partCount) { currentPartCount = partCount; hasRequiredParts = false; totalCount = this.part.vessel.parts.Count; for (index = 0; index < totalCount; index++) { testPart = this.part.vessel.parts[index]; if (partsList.Contains(testPart.partInfo.title)) { hasRequiredParts = true; break; } } } if (hasRequiredParts == false) { StringBuilder requirements = new StringBuilder(); requirements.Append("Needs one: "); for (index = 0; index < requiredParts.Length; index++) { requirements.Append(requiredParts[index] + "\r\n"); } status = requirements.ToString(); return(false); } } //Required anomalies if (!string.IsNullOrEmpty(requiredAnomalies)) { if (!isNearAnomaly()) { status = "Needs to be near " + requiredAnomalies.Replace(";", ", "); return(false); } } //Required resources if (string.IsNullOrEmpty(requiredResources) == false) { //for each resource, see if we still need more totalCount = resourceMapKeys.Length; SExperimentResource experimentResource; PartResource partResource = null; for (index = 0; index < totalCount; index++) { experimentResource = resourceMap[resourceMapKeys[index]]; if (!checkPartResources) { //If necessary, pull the resource from the vessel instead of waiting for the resource //to come to the lab. if (experimentResource.transferFromVessel && (experimentResource.currentAmount / experimentResource.targetAmount) < 0.999f) { double amountObtained = this.part.RequestResource(experimentResource.name, experimentResource.targetAmount - experimentResource.currentAmount, ResourceFlowMode.ALL_VESSEL); TakeShare(experimentResource.name, amountObtained); } //Check to see if we're done. if ((experimentResource.currentAmount / experimentResource.targetAmount) < 0.999f) { status = "Needs " + experimentResource.name + string.Format(" ({0:f3}/{1:f3})", experimentResource.currentAmount, experimentResource.targetAmount); return(false); } } else //Check the part for the required resources { // Debug.Log("[WBIModuleScienceExperiment] - Checking part for " + experimentResource.name); if (this.part.Resources.Contains(experimentResource.name)) { partResource = this.part.Resources[experimentResource.name]; if ((partResource.amount / experimentResource.targetAmount) < 0.999f) { status = "Needs " + experimentResource.name + string.Format(" ({0:f3}/{1:f3})", partResource.amount, experimentResource.targetAmount); return(false); } } } } } //chanceOfSuccess if (chanceOfSuccess > 0.001f && isCompleted == false && experimentFailed == false) { resultRoll = performAnalysisRoll(); if (resultRoll < chanceOfSuccess) { experimentFailed = true; status = "Failed to yield results"; runCompletionHandler(experimentID, chanceOfSuccess, resultRoll); sendResultsMessage(); return(false); } } //AOK isCompleted = true; if (xmitDataScalar < 0.001f) { status = "Completed, send home for science"; } else { status = "Completed"; } runCompletionHandler(experimentID, chanceOfSuccess, resultRoll); sendResultsMessage(); if (checkPartResources) { totalCount = resourceMapKeys.Length; SExperimentResource experimentResource; for (index = 0; index < totalCount; index++) { experimentResource = resourceMap[resourceMapKeys[index]]; if (this.part.Resources.Contains(experimentResource.name)) { if (this.rerunnable) { this.part.Resources[experimentResource.name].amount = 0; } else { this.part.Resources.Remove(experimentResource.name); } } } //Dirty the GUI MonoUtilities.RefreshContextWindows(this.part); } if (Deployed == false) { DeployExperiment(); } return(true); }
protected void CreateDelegates() { // Filter for celestial bodies if (targetBody != null && string.IsNullOrEmpty(biome)) { AddParameter(new ParameterDelegate <Vessel>("Destination: " + targetBody.CleanDisplayName(), subj => FlightGlobals.currentMainBody == targetBody, true)); } // Filter for biome if (!string.IsNullOrEmpty(biome)) { Biome b = new Biome(targetBody, biome); string title = b.IsKSC() ? "Location: " : "Biome: "; AddParameter(new ParameterDelegate <Vessel>(title + b, subj => CheckBiome(FlightGlobals.ActiveVessel))); } // Filter for situation if (situation != null) { AddParameter(new ParameterDelegate <Vessel>("Situation: " + situation.Value.Print(), subj => FlightGlobals.ActiveVessel != null && ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel) == situation)); } // Filter for location if (location != null) { AddParameter(new ParameterDelegate <Vessel>("Location: " + location, subj => FlightGlobals.ActiveVessel != null && ((location != BodyLocation.Surface) ^ FlightGlobals.ActiveVessel.LandedOrSplashed))); } // Add the experiments foreach (string exp in experiment) { string experimentStr = string.IsNullOrEmpty(exp) ? "Any" : ExperimentName(exp); ContractParameter experimentParam = AddParameter(new ParameterDelegate <Vessel>("Experiment: " + experimentStr, subj => recoveryDone.ContainsKey(exp))); // Add the subject ContractParameter subjectParam = new ParameterDelegate <Vessel>("", subj => true); subjectParam.ID = exp + "Subject"; experimentParam.AddParameter(subjectParam); // Filter for recovery if (recoveryMethod != ScienceRecoveryMethod.None) { ContractParameter recoveryParam = experimentParam.AddParameter(new ParameterDelegate <Vessel>("Recovery: " + RecoveryMethod(exp).Print(), subj => false)); } } }
protected override bool generateScienceData() { ScienceExperiment experiment = ResearchAndDevelopment.GetExperiment(experimentID); if (experiment == null) { return(false); } if (science_to_add > 0) { ScienceSubject subject = ResearchAndDevelopment.GetExperimentSubject(experiment, ScienceUtil.GetExperimentSituation(vessel), vessel.mainBody, "", ""); if (subject == null) { return(false); } subject.subjectValue = PluginHelper.getScienceMultiplier(vessel); subject.scienceCap = 167 * subject.subjectValue; subject.dataScale = 1.25f; double remaining_base_science = (subject.scienceCap - subject.science) / subject.subjectValue; science_to_add = Math.Min(science_to_add, remaining_base_science); // transmission of zero data breaks the experiment result dialog box data_size = Math.Max(float.Epsilon, science_to_add * subject.dataScale); science_data = new ScienceData((float)data_size, 1, 0, subject.id, "Science Lab Data"); result_title = experiment.experimentTitle; result_string = this.nameStr + " " + getRandomExperimentResult(); recovery_value = science_to_add; transmit_value = recovery_value; xmit_scalar = 1; ref_value = subject.scienceCap; return(true); } return(false); }
public void Do_SlowUpdate() { if ((object)activeExperiment != null) { var curTime = Planetarium.GetUniversalTime(); var delta = curTime - lastUpdateTime; // Tasks // 1. Make sure experiment situation hasn't changed, if it has, then return // 2. calcualte resource usage // 3. Check to see if exeriment is completed, if so, set a flag string biome, displayBiome; if (vessel.landedAt != string.Empty) { biome = Vessel.GetLandedAtString(vessel.landedAt); displayBiome = Localizer.Format(vessel.displaylandedAt); } else { biome = ScienceUtil.GetExperimentBiome(vessel.mainBody, vessel.latitude, vessel.longitude); displayBiome = ScienceUtil.GetBiomedisplayName(vessel.mainBody, biome); } var curExp = new ActiveExperiment(activeExperiment.activeExpid, vessel.mainBody.bodyName, ScienceUtil.GetExperimentSituation(vessel), biome); if ((object)curExp != null && curExp.Key == activeExperiment.Key) { if (!expStatuses.ContainsKey(activeExperiment.Key)) { Log.Info("Key missing from expStatuses, key: " + activeExperiment.Key); foreach (var e in expStatuses.Keys) { Log.Info("key: " + e); } } double resourceRequest = delta / Planetarium.fetch.fixedDeltaTime; double amtNeeded = Math.Min( experiments[activeExperiment.activeExpid].resourceUsageRate * resourceRequest, experiments[activeExperiment.activeExpid].resourceAmtRequired - expStatuses[activeExperiment.Key].processedResource); amtNeeded = amtNeeded * KCT_Interface.ResearchTimeAdjustment(); double resource = part.RequestResource(experiments[activeExperiment.activeExpid].neededResourceName, amtNeeded); expStatuses[activeExperiment.Key].processedResource += resource; int resourceID = GetResourceID(expStatuses[activeExperiment.Key].reqResource); part.GetConnectedResourceTotals(resourceID, out double amount, out double maxAmount); expStatuses[activeExperiment.Key].lastTimeUpdated = Planetarium.GetUniversalTime(); // var experiment = experiments[activeExperiment.activeExpid]; } else { Log.Info("Situation changed"); Utils.DisplayScreenMsg("Vessel Situation Changed, Experiment Paused"); } // need to decide what to do if something changed lastUpdateTime = curTime; } else if (experimentStarted) { Log.Info("FixedUpdate, activeExperiment is null"); } }
private System.Collections.IEnumerator UpdateObservers() { //Log.Write("ExperimentManager.UpdateObservers", Log.LEVEL.INFO); while (true) { while (!FlightGlobals.ready || FlightGlobals.ActiveVessel == null) { yield return(0); //continue; } var expSituation = ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel); if (observers.Count == 0) { ScienceAlert.Instance.SetUnlit(); } else { for (int i = observers.Count - 1; i >= 0; i--) { ExperimentObserver observer = observers[i]; try { #if PROFILE float start = Time.realtimeSinceStartup; #endif bool newReport = false; // Is exciting new research available? if (observer.UpdateStatus(expSituation, out newReport)) { // if we're timewarping, resume normal time if that setting was used if (observer.StopWarpOnDiscovery || Settings.Instance.GlobalWarp == Settings.WarpSetting.GlobalOn) { if (Settings.Instance.GlobalWarp != Settings.WarpSetting.GlobalOff) { if (TimeWarp.CurrentRateIndex > 0) { //OrbitSnapshot snap = new OrbitSnapshot(FlightGlobals.ActiveVessel.GetOrbitDriver().orbit); TimeWarp.fetch.CancelAutoWarp(); TimeWarp.SetRate(0, true); //FlightGlobals.ActiveVessel.GetOrbitDriver().orbit = snap.Load(); //FlightGlobals.ActiveVessel.GetOrbitDriver().orbit.UpdateFromUT(Planetarium.GetUniversalTime()); } } } #if false scienceAlert.Button.Important = true; #endif if (observer.settings.AnimationOnDiscovery) { ScienceAlert.Instance.PlayAnimation(); } else { ScienceAlert.Instance.SetLit(); // if (scienceAlert.Button.IsNormal) scienceAlert.Button.SetLit(); } switch (Settings.Instance.SoundNotification) { case Settings.SoundNotifySetting.ByExperiment: if (observer.settings.SoundOnDiscovery) { audio.PlayUI("bubbles", 2f); } break; case Settings.SoundNotifySetting.Always: audio.PlayUI("bubbles", 2f); break; } OnExperimentAvailable(observer.Experiment, observer.NextReportValue); } else if (!observers.Any(ob => ob.Available)) { ScienceAlert.Instance.SetUnlit(); #if false scienceAlert.Button.Important = false; #endif } #if PROFILE Log.Warning("Tick time ({1}): {0} ms", (Time.realtimeSinceStartup - start) * 1000f, observer.ExperimentTitle); #endif } catch (Exception e) { Log.Debug("ExperimentManager.UpdateObservers: exception {0}", e); } if (TimeWarp.CurrentRate < Settings.Instance.TimeWarpCheckThreshold) { yield return(0); // pause until next frame } } // end observer loop } yield return(0); } // end infinite while loop }
public void Update() { string canCommText; double altitude = FlightGlobals.ActiveVessel.altitude; double distanceTraveled = FlightGlobals.ActiveVessel.distanceTraveled; double externalTemperature = FlightGlobals.ActiveVessel.externalTemperature; double GForce = FlightGlobals.ActiveVessel.geeForce_immediate; bool isLanded = FlightGlobals.ActiveVessel.Landed; double verticalSpeed = FlightGlobals.ActiveVessel.verticalSpeed; double timeToPe = FlightGlobals.ActiveVessel.GetCurrentOrbit().timeToPe; double timeToAp = FlightGlobals.ActiveVessel.GetCurrentOrbit().timeToAp; double orbitSpeed = FlightGlobals.ActiveVessel.obt_speed; double orbitIncl = FlightGlobals.ActiveVessel.GetCurrentOrbit().inclination; double orbitEcc = FlightGlobals.ActiveVessel.GetCurrentOrbit().eccentricity; bool canComm = FlightGlobals.ActiveVessel.connection.CanComm; double ApA = FlightGlobals.ActiveVessel.GetOrbit().ApA; double PeA = FlightGlobals.ActiveVessel.GetOrbit().PeA; string targetName = ""; double targetSpeed = 0; double distance = 0; double targetLat = 0; double targetLong = 0; try { ITargetable target = FlightGlobals.fetch.VesselTarget; targetName = target.GetDisplayName(); var vessel = target.GetVessel(); var targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit(); var originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun || FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody) ? FlightGlobals.ship_orbit : FlightGlobals.ship_orbit.referenceBody.orbit; targetSpeed = FlightGlobals.ship_obtSpeed - targetOrbit.orbitalSpeed; distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos); targetLat = vessel.latitude; targetLong = vessel.longitude; } catch (Exception) { targetName = "NON"; targetSpeed = 0; distance = 0; } string planetName = FlightGlobals.ActiveVessel.mainBody.bodyName; Vector3d centreOfMass = FlightGlobals.ActiveVessel.CoMD; Vector3d up = (centreOfMass - FlightGlobals.ActiveVessel.mainBody.position).normalized; Vector3d north = Vector3.ProjectOnPlane((FlightGlobals.ActiveVessel.mainBody.position + FlightGlobals.ActiveVessel.mainBody.transform.up * (float)FlightGlobals.ActiveVessel.mainBody.Radius) - centreOfMass, up).normalized; Quaternion surfaceRotation = Quaternion.Inverse(Quaternion.Euler(90.0f, 0.0f, 0.0f) * Quaternion.Inverse(FlightGlobals.ActiveVessel.transform.rotation) * Quaternion.LookRotation(north, up)); double yaw = surfaceRotation.eulerAngles.y; double pitch = surfaceRotation.eulerAngles.x > 180.0f ? 360.0f - surfaceRotation.eulerAngles.x : -surfaceRotation.eulerAngles.x; double roll = surfaceRotation.eulerAngles.z > 180.0f ? 360.0f - surfaceRotation.eulerAngles.z : -surfaceRotation.eulerAngles.z; if (canComm) { canCommText = "TRUE"; } else { canCommText = "FALSE"; } double lat = FlightGlobals.ActiveVessel.latitude; double ConvectionFlux = 0.0; double RadiationFlux = 0.0; double InternalFlux = 0.0; double HottestTemperature = 0.0; double HottestSkinTemperature = 0.0; double CoolestTemperature = double.MaxValue; double CoolestSkinTemperature = double.MaxValue; double CriticalTemperature = double.MaxValue; double CriticalSkinTemperature = double.MaxValue; double CriticalTemperaturePercentage = 0.0; string HottestPartName = ""; string CoolestPartName = ""; string CriticalPartName = ""; for (int i = 0; i < FlightGlobals.ActiveVessel.parts.Count; ++i) { Part part = FlightGlobals.ActiveVessel.parts[i]; ConvectionFlux = ConvectionFlux + part.thermalConvectionFlux; RadiationFlux = RadiationFlux + part.thermalRadiationFlux; InternalFlux = InternalFlux + part.thermalInternalFluxPrevious; if (part.temperature > HottestTemperature || part.skinTemperature > HottestSkinTemperature) { HottestTemperature = part.temperature; //HottestTemperatureMax = part.maxTemp; HottestSkinTemperature = part.skinTemperature; //HottestSkinTemperatureMax = part.skinMaxTemp; HottestPartName = part.partInfo.title.Replace("\"", "\\\""); } if (part.temperature < CoolestTemperature || part.skinTemperature < CoolestSkinTemperature) { CoolestTemperature = part.temperature; //CoolestTemperatureMax = part.maxTemp; CoolestSkinTemperature = part.skinTemperature; //CoolestSkinTemperatureMax = part.skinMaxTemp; CoolestPartName = part.partInfo.title.Replace("\"", "\\\""); } if (part.temperature / part.maxTemp > CriticalTemperaturePercentage || part.skinTemperature / part.skinMaxTemp > CriticalTemperaturePercentage) { CriticalTemperature = part.temperature; //CriticalTemperatureMax = part.maxTemp; CriticalSkinTemperature = part.skinTemperature; //CriticalSkinTemperatureMax = part.skinMaxTemp; CriticalTemperaturePercentage = Math.Max(part.temperature / part.maxTemp, part.skinTemperature / part.skinMaxTemp); CriticalPartName = part.partInfo.title.Replace("\"", "\\\""); } } double lon = FlightGlobals.ActiveVessel.longitude; double missionTime = FlightGlobals.ActiveVessel.missionTime; double speed = FlightGlobals.ActiveVessel.speed; string name = FlightGlobals.ActiveVessel.vesselName; double atmDensity = FlightGlobals.ActiveVessel.atmDensity; int currentStage = FlightGlobals.ActiveVessel.currentStage; double deltaV = FlightGlobals.ActiveVessel.VesselDeltaV.TotalDeltaVActual; double mass = FlightGlobals.ActiveVessel.totalMass; double acceleration = FlightGlobals.ActiveVessel.acceleration_immediate.magnitude; int partCount = FlightGlobals.ActiveVessel.parts.Count; string situation = ""; double horizSpeed = FlightGlobals.ActiveVessel.horizontalSrfSpeed; time += Time.deltaTime; switch (ScienceUtil.GetExperimentSituation(FlightGlobals.ActiveVessel)) { case ExperimentSituations.SrfLanded: situation = "Landed"; break; case ExperimentSituations.SrfSplashed: situation = "Splashed"; break; case ExperimentSituations.FlyingLow: situation = "Flying Low"; break; case ExperimentSituations.FlyingHigh: situation = "Flying High"; break; case ExperimentSituations.InSpaceLow: situation = "In Space Low"; break; case ExperimentSituations.InSpaceHigh: situation = "In Space High"; break; } if (time >= interpolationPeriod) { time = time - interpolationPeriod; if (situation != "Landed" && altitude < 90000) { altOverTime.Add(altitude); fPOverTime.Add(altitude); apogeeOverTime.Add(ApA); velOverTime.Add(speed); dVOverTime.Add(deltaV); string altOverTimeData = ""; string fPOverTimeData = ""; string apogeeOverTimeData = ""; string velOverTimeData = ""; string dVOverTimeData = ""; for (var i = 0; i < altOverTime.Count; i++) { altOverTimeData += altOverTime[i] + ", "; fPOverTimeData += fPOverTime[i] + ", "; apogeeOverTimeData += apogeeOverTime[i] + ", "; velOverTimeData += velOverTime[i] + ", "; dVOverTimeData += dVOverTime[i] + ", "; } altOverTimeData = altOverTimeData.Remove(altOverTimeData.Length - 2); fPOverTimeData = fPOverTimeData.Remove(fPOverTimeData.Length - 2); apogeeOverTimeData = apogeeOverTimeData.Remove(apogeeOverTimeData.Length - 2); velOverTimeData = velOverTimeData.Remove(velOverTimeData.Length - 2); dVOverTimeData = dVOverTimeData.Remove(dVOverTimeData.Length - 2); string finalAltOverTime = "{ \"data\": [" + altOverTimeData + "]}"; string finalFPOverTime = "{ \"data\": [" + fPOverTimeData + "]}"; string finalApogeeOverTime = "{ \"data\": [" + apogeeOverTimeData + "]}"; string finalVelOverTime = "{ \"data\": [" + velOverTimeData + "]}"; string finalDVOverTimee = "{ \"data\": [" + dVOverTimeData + "]}"; File.WriteAllText(@"GameData\Kerbal Telemetry\static\altOverTime.json", finalAltOverTime); File.WriteAllText(@"GameData\Kerbal Telemetry\static\fPOverTimeData.json", finalFPOverTime); File.WriteAllText(@"GameData\Kerbal Telemetry\static\apogeeOverTimeData.json", finalApogeeOverTime); File.WriteAllText(@"GameData\Kerbal Telemetry\static\velOverTimeData.json", finalVelOverTime); File.WriteAllText(@"GameData\Kerbal Telemetry\static\dVOverTimeData.json", finalDVOverTimee); } } string serializeData = "\"altitude\":{0},\"distanceTraveled\":{1},\"externalTemperature\":{2},\"GForce\":{3},\"canComm\":\"{4}\",\"situation\":\"{5}\",\"timeToPe\":{6},\"lat\":{7},\"lon\":{8},\"verticalSpeed\":{9},\"missionTime\":{10},\"speed\":{11},\"name\":\"{12}\",\"atmDensity\":{13},\"currentStage\":{14},\"deltaV\":{15},\"timeToAp\":{16},\"orbitSpeed\":{17},\"orbitIncl\":{18},\"orbitEcc\":{19},\"ApA\":{20},\"PeA\":{21},\"horizSpeed\":{22},\"partCount\":{23},\"mass\":{24},\"acceleration\":{25},\"convFlux\":{26},\"radFlux\":{27},\"intFlux\":{28},\"planetName\":\"{29}\",\"yaw\":{30},\"pitch\":{31},\"roll\":{32},\"coolTemp\":{33},\"coolSkinTemp\":{34},\"coolSkinName\":\"{35}\",\"hotTemp\":{36},\"hotSkinTemp\":{37},\"hotSkinName\":\"{38}\",\"critTemp\":{39},\"critSkinTemp\":{40},\"critSkinName\":\"{41}\",\"targetName\":\"{42}\",\"distance\":{43},\"targetSpeed\":{44},\"targetLat\":{45},\"targetLong\":{46}"; string data = String.Format(serializeData, altitude, distanceTraveled, externalTemperature - 273, GForce, canCommText, situation, timeToPe, lat, lon, verticalSpeed, missionTime, speed, name, atmDensity, currentStage, deltaV, timeToAp, orbitSpeed, orbitIncl, orbitEcc, ApA, PeA, horizSpeed, partCount, mass, acceleration, ConvectionFlux, RadiationFlux, InternalFlux, planetName, yaw, pitch, roll, CoolestTemperature - 273, CoolestSkinTemperature - 273, CoolestPartName, HottestTemperature - 273, HottestSkinTemperature - 273, HottestPartName, CriticalTemperature - 273, CriticalSkinTemperature - 273, CriticalPartName, targetName, distance, targetSpeed, targetLat, targetLong); data = "{" + data + "}"; File.WriteAllText(@"GameData\Kerbal Telemetry\static\data.json", data); }