internal override void Awake() { LogFormatted("Awakening the AlternateResourcePanel (ARP)"); LogFormatted("Loading Settings"); settings = new Settings("settings.cfg"); if (!settings.Load()) LogFormatted("Settings Load Failed"); //If the window is in the pre0.24 default then move it down so its not over the app launcher if (new Rect(Screen.width - 310, 0, 310, 40).Contains(settings.vectButtonPos)) { settings.vectButtonPos = new Vector3(Screen.width - 405, 0,0 ); settings.ButtonPosUpdatedv24 = true; settings.Save(); } if (!settings.WindowPosUpdatedv24 && settings.WindowPosition == new Rect(new Rect(Screen.width - 298, 19, 299, 20))) { MonoBehaviourExtended.LogFormatted("Moving window for 0.24"); settings.WindowPosUpdatedv24 = true; settings.Save(); blnResetWindow = true; } //Ensure settings.resources contains all the resources in the loaded game VerifyResources(); //get the sounds and set things up Resources.LoadSounds(); InitAudio(); //Get whether the toolbar is there settings.BlizzyToolbarIsAvailable = ToolbarManager.ToolbarAvailable; //convert blizzy bool to display enum if (settings.UseBlizzyToolbarIfAvailable) { settings.UseBlizzyToolbarIfAvailable = false; settings.ButtonStyleChosen = ARPWindowSettings.ButtonStyleEnum.Toolbar; } //setup the Toolbar button if necessary if (settings.ButtonStyleToDisplay==ARPWindowSettings.ButtonStyleEnum.Toolbar) { btnToolbar = InitToolbarButton(); } ////if requested use that button //if (settings.BlizzyToolbarIsAvailable && settings.UseBlizzyToolbarIfAvailable) // btnToolbar = InitToolbarButton(); //init the global variables lstPartWindows = new ARPPartWindowList(); lstResourcesVessel = new ARPResourceList(ARPResourceList.ResourceUpdate.AddValues, settings.Resources); lstResourcesLastStage = new ARPResourceList(ARPResourceList.ResourceUpdate.AddValues, settings.Resources); lstResourcesVesselPerStage = new Dictionary<Int32, ARPResourceList>(); lstPartsLastStageEngines = new ARPPartList(); lstResourcesToDisplay = new List<Int32>(); SelectedResources = new PartResourceVisibleList(); lstTransfers = new ARPTransferList(); SelectedResources.ResourceRemoved += SelectedResources_ResourceRemoved; lstResourcesVessel.OnMonitorStateChanged += lstResourcesVessel_OnMonitorStateChanged; lstResourcesVessel.OnAlarmStateChanged += lstResourcesVessel_OnAlarmStateChanged; //init the windows InitMainWindow(); InitSettingsWindow(); InitResourceConfigWindow(); InitDebugWindow(); //plug us in to the draw queue and start the worker RenderingManager.AddToPostDrawQueue(1, DrawGUI); StartRepeatingWorker(10); //register for stage separation events - so we can cancel the noise on a sep GameEvents.onStageActivate.Add(OnStageActivate); GameEvents.onFlightReady.Add(OnFlightReady); //Hook the App Launcher OnGUIAppLauncherReady(); //GameEvents.onGUIApplicationLauncherReady.Add(OnGUIAppLauncherReady); GameEvents.onGUIApplicationLauncherUnreadifying.Add(OnGUIAppLauncherUnreadifying); //do the daily version check if required if (settings.DailyVersionCheck) settings.VersionCheck(false); APIAwake(); }
/// <summary> /// Heres where the heavy lifting should occur /// </summary> internal override void RepeatingWorker() { if (StockAppToBeHidden) ReplaceStockAppButton(); if (AppLauncherToBeSetTrue && (settings.ButtonStyleToDisplay==ARPWindowSettings.ButtonStyleEnum.Launcher || settings.ButtonStyleToDisplay==ARPWindowSettings.ButtonStyleEnum.StockReplace) ) SetAppButtonToTrue(); Vessel active = FlightGlobals.ActiveVessel; LastStage = GetLastStage(active.parts); Double RatePeriod = RepeatingWorkerUTPeriod; if (!settings.RatesUseUT) RatePeriod = RepeatingWorkerUTPeriod / TimeWarp.CurrentRate; //trigger the start loop and store the UT that has passed - only calc rates where necessary lstResourcesVessel.StartUpdatingList(settings.ShowRates, RatePeriod); lstResourcesLastStage.StartUpdatingList(settings.ShowRates, RatePeriod); //sort out the per stage list for (int i = 0; i <= Staging.StageCount; i++) { if (!lstResourcesVesselPerStage.ContainsKey(i)) { lstResourcesVesselPerStage.Add(i, new ARPResourceList(ARPResourceList.ResourceUpdate.AddValues, settings.Resources)); } lstResourcesVesselPerStage[i].StartUpdatingList(settings.ShowRates, RatePeriod); } //flush the temporary lists lstPartsLastStageEngines = new ARPPartList(); lstParts = new ARPPartDefList(); List<Int32> lstVesselResourceIDs = new List<Int32>(); //Now loop through and update em foreach (Part p in active.parts) { //is the part decoupled in the last stage Boolean DecoupledInLastStage = (p.DecoupledAt()==LastStage); foreach (PartResource pr in p.Resources) { //store a list of all resources in vessel so we can nuke resources from the other lists later if (!lstVesselResourceIDs.Contains(pr.info.id)) lstVesselResourceIDs.Add(pr.info.id); //Is this resource set to split on disabled parts instead of staging if ((PartResourceLibrary.Instance.resourceDefinitions[pr.info.id].resourceFlowMode == ResourceFlowMode.ALL_VESSEL || PartResourceLibrary.Instance.resourceDefinitions[pr.info.id].resourceFlowMode == ResourceFlowMode.STAGE_PRIORITY_FLOW) && settings.Resources[pr.info.id].ShowReserveLevels) { if (pr.flowState) { //update the resource in the vessel list lstResourcesVessel.UpdateResource(pr);//,InitialSettings:settings.Resources[pr.info.id]); //if it dont exist in the last stage list - add a 0 value if (!lstResourcesLastStage.ContainsKey(pr.info.id)) { LogFormatted_DebugOnly("Adding 0 value into last stage"); PartResource prTemp = new PartResource() { info = pr.info, amount = 0, maxAmount = 0 }; lstResourcesLastStage.UpdateResource(prTemp); } } else { //and if it needs to go in the last stage list lstResourcesLastStage.UpdateResource(pr); } } else { //update the resource in the vessel list lstResourcesVessel.UpdateResource(pr);//,InitialSettings:settings.Resources[pr.info.id]); //and if it needs to go in the last stage list if (DecoupledInLastStage) { lstResourcesLastStage.UpdateResource(pr); } } //Update the whole vessel list lstResourcesVesselPerStage[p.DecoupledAt().Clamp(1,Staging.StageCount)].UpdateResource(pr); //is the resource in the selected list if (SelectedResources.ContainsKey(pr.info.id) && SelectedResources[pr.info.id].AllVisible && !settings.Resources[pr.info.id].ShowReserveLevels) lstPartWindows.AddPartWindow(p, pr, this, RatePeriod); else if (SelectedResources.ContainsKey(pr.info.id) && SelectedResources[pr.info.id].LastStageVisible && DecoupledInLastStage && !settings.Resources[pr.info.id].ShowReserveLevels) lstPartWindows.AddPartWindow(p, pr, this, RatePeriod); else if (SelectedResources.ContainsKey(pr.info.id) && SelectedResources[pr.info.id].AllVisible && settings.Resources[pr.info.id].ShowReserveLevels && pr.flowState) lstPartWindows.AddPartWindow(p, pr, this, RatePeriod); else if (SelectedResources.ContainsKey(pr.info.id) && SelectedResources[pr.info.id].LastStageVisible && settings.Resources[pr.info.id].ShowReserveLevels && !pr.flowState) lstPartWindows.AddPartWindow(p, pr, this, RatePeriod); else if (lstPartWindows.ContainsKey(p.GetInstanceID())) { //or not,but the window is in the list if (lstPartWindows[p.GetInstanceID()].ResourceList.ContainsKey(pr.info.id)) lstPartWindows[p.GetInstanceID()].ResourceList.Remove(pr.info.id); } } if(DecoupledInLastStage && (p.Modules.OfType<ModuleEngines>().Any() || p.Modules.OfType<ModuleEnginesFX>().Any())) { //Add the part to the engines list for the active stage lstPartsLastStageEngines.Add(p); } } //Destroy the windows that have no resources selected to display lstPartWindows.CleanWindows(); //Remove Resources that no longer exist in vessel lstResourcesVessel.CleanResources(lstVesselResourceIDs); lstResourcesLastStage.CleanResources(lstVesselResourceIDs); //Finalise the list updates - calc rates and set alarm flags lstResourcesVessel.EndUpdatingList(settings.ShowRates); lstResourcesLastStage.EndUpdatingList(settings.ShowRates); foreach (ARPResourceList lstStage in lstResourcesVesselPerStage.Values) { lstStage.CleanResources(lstVesselResourceIDs); lstStage.EndUpdatingList(settings.ShowRates); } //List<Int32> StagesToDelete = lstResourcesVesselPerStage.Select(x => x.Key).Where(x => x > Staging.StageCount).ToList(); //foreach (Int32 stageID in StagesToDelete) { // LogFormatted_DebugOnly("Removing Stage {0}", stageID); // lstResourcesVesselPerStage.Remove(stageID); //} //#if DEBUG // String File = ""; // File += String.Format("Stage,Name,Amount\r\n"); // for (int i = 0; i < lstResourcesVesselPerStage.Count; i++) // { // ARPResourceList tmp = lstResourcesVesselPerStage.OrderBy(x => x.Key).ToList()[i].Value; // foreach (ARPResource item in tmp.Values) // { // String strline = ""; // strline += String.Format("{0},{1},{2:0}", i, item.ResourceDef.name, item.Amount); // File += strline + "\r\n"; // } // } // System.IO.File.WriteAllText(String.Format("{0}/AllStages.csv", Resources.PathPlugin), File); //#endif //Set the alarm flags foreach (ARPResource r in lstResourcesVessel.Values) { r.SetMonitors(); } //work out if we have to kill the audio if (StageCheckAlarmAudio) { StageCheckAlarmAudio = false; if (KSPAlternateResourcePanel.audioController.isPlaying()) { Boolean AudioShouldBePlaying = false; foreach (ARPResource r in lstResourcesVessel.Values) { if (r.AlarmState== ARPResource.AlarmStateEnum.Unacknowledged && r.MonitorState!= ARPResource.MonitorStateEnum.None) { AudioShouldBePlaying = true; break; } } if (!AudioShouldBePlaying) KSPAlternateResourcePanel.audioController.Stop(); } } //Build the displayList lstResourcesToDisplay = new List<Int32>(); for (int i = 0; i < settings.Resources.Count; i++) { Int32 ResourceID = (Int32)settings.Resources.Keys.ElementAt(i); if (settings.Resources[ResourceID].IsSeparator) { if (lstResourcesToDisplay.Count > 0 && lstResourcesToDisplay.Last() != 0) //Dont add double seps lstResourcesToDisplay.Add(0); continue; } //only add resources in the vessel if (!lstResourcesVessel.ContainsKey(ResourceID)) continue; //skip to next item if this one is a) Hidden b) Set to threshold and not flagged c)Empty and empty timer is done //show everything of showall is enabled if (!ShowAll) { if (settings.Resources[ResourceID].Visibility == ResourceSettings.VisibilityTypes.Hidden) continue; else if (settings.Resources[ResourceID].Visibility == ResourceSettings.VisibilityTypes.Threshold) { if (lstResourcesVessel[ResourceID].MonitorState == ARPResource.MonitorStateEnum.None) continue; } else if (settings.HideEmptyResources && settings.Resources[ResourceID].HideWhenEmpty && lstResourcesVessel[ResourceID].IsEmpty) { //if the alarms not firing and the time has passed then hide it if (lstResourcesVessel[ResourceID].AlarmState != ARPResource.AlarmStateEnum.Unacknowledged && lstResourcesVessel[ResourceID].EmptyAt < DateTime.Now.AddSeconds(-settings.HideAfter)) continue; } else if (settings.HideFullResources && settings.Resources[ResourceID].HideWhenFull && lstResourcesVessel[ResourceID].IsFull) { //if the alarms not firing and the time has passed then hide it if (lstResourcesVessel[ResourceID].AlarmState != ARPResource.AlarmStateEnum.Unacknowledged && lstResourcesVessel[ResourceID].FullAt < DateTime.Now.AddSeconds(-settings.HideAfter)) continue; } } //if we get this far then add it to the list lstResourcesToDisplay.Add(ResourceID); } //remove starting or ending seps if (lstResourcesToDisplay.Count > 0) { while (lstResourcesToDisplay.First() == 0) lstResourcesToDisplay.RemoveAt(0); while (lstResourcesToDisplay.Last() == 0) lstResourcesToDisplay.RemoveAt(lstResourcesToDisplay.Count - 1); } //Calc window widths/heights windowMain.IconAlarmOffset = 12; if (!settings.AlarmsEnabled) windowMain.IconAlarmOffset = 0; windowMain.WindowRect.width = 329 + windowMain.IconAlarmOffset; //was 299 - adding 30 windowMain.Icon2BarOffset_Left = 40 + windowMain.IconAlarmOffset ; windowMain.Icon2BarOffset_Right = 40 + 140 + windowMain.IconAlarmOffset ; if (lstResourcesToDisplay.Count == 0) windowMain.WindowRect.height = (2 * windowMain.intLineHeight) + 16; else { //this is resources lines - separators diff + fixed value windowMain.WindowRect.height = ((lstResourcesToDisplay.Count + 1) * windowMain.intLineHeight) - (lstResourcesToDisplay.Count(x => x == 0) * (15 - (settings.SpacerPadding * 2))) + 12; } if (settings.AutoStagingEnabled) windowMain.WindowRect.height += 24; //now do the autostaging stuff lstLastStageEngineModules = lstPartsLastStageEngines.SelectMany(x => x.Modules.OfType<ModuleEngines>()).ToList(); lstLastStageEngineFXModules = lstPartsLastStageEngines.SelectMany(x => x.Modules.OfType<ModuleEnginesFX>()).ToList(); AutoStagingMaxStage = Mathf.Min(AutoStagingMaxStage, Staging.StageCount - 1); AutoStagingTerminateAt = Mathf.Min(AutoStagingTerminateAt, AutoStagingMaxStage); AutoStagingStatusColor = Color.white; if (settings.AutoStagingEnabled) { if (AutoStagingArmed) { if (!AutoStagingRunning) { AutoStagingStatusColor = Color.white; AutoStagingStatus = "Armed... waiting for stage"; //when to set it to running if (lstLastStageEngineModules.Any(x => x.staged) || lstLastStageEngineFXModules.Any(x => x.staged)) AutoStagingRunning = true; } else if (Staging.CurrentStage > AutoStagingTerminateAt) { //we are running, so now what AutoStagingStatusColor = new Color32(183, 254, 0, 255); AutoStagingStatus = "Running"; //are all the engines that are active flamed out in the last stage if (AutoStagingTriggeredAt == 0 && lstPartsLastStageEngines.Count > 0 && (lstLastStageEngineModules.Where(x => x.staged).All(x => x.getFlameoutState)) && (lstLastStageEngineFXModules.Where(x => x.staged).All(x => x.getFlameoutState))) { LogFormatted_DebugOnly("Engine Flameouts Detected"); AutoStagingTriggeredAt = Planetarium.GetUniversalTime(); } else if(AutoStagingTriggeredAt == 0 && lstResourcesLastStage.Sum(r=>r.Value.Amount)<=0 & lstPartsLastStageEngines.Count==0) { //or is the last stage just emoty tanks? LogFormatted_DebugOnly("Empty Resource Stage Detected"); AutoStagingTriggeredAt = Planetarium.GetUniversalTime(); } else if (AutoStagingTriggeredAt != 0){ if (Planetarium.GetUniversalTime() - AutoStagingTriggeredAt > ((Double)settings.AutoStagingDelayInTenths / 10)) { //if (!settings.StagingIgnoreLock || Staging.stackLocked || FlightInputHandler.fetch.stageLock) LogFormatted("Autostage Triggered: {0}->{1}", Staging.CurrentStage, Staging.CurrentStage - 1); Staging.ActivateNextStage(); AutoStagingTriggeredAt = 0; } else { AutoStagingStatusColor = new Color32(232, 232, 0, 255); AutoStagingStatus = String.Format("Delay:{0:0.0}s", ((Double)settings.AutoStagingDelayInTenths / 10) - (Planetarium.GetUniversalTime() -AutoStagingTriggeredAt )); } } } else { LogFormatted("Autostaging Run Complete"); AutoStagingTriggeredAt = Planetarium.GetUniversalTime(); AutoStagingRunning = false; AutoStagingArmed = false; } } else { if (AutoStagingTriggeredAt == 0) { AutoStagingStatusColor = new Color32(140, 140, 140,255); AutoStagingStatus = "Not Armed"; } else { if (Planetarium.GetUniversalTime() - AutoStagingTriggeredAt > 3) AutoStagingTriggeredAt = 0; else { AutoStagingStatus = "Run Complete"; AutoStagingStatusColor = new Color32(183, 254, 0, 255); } } } } //Transfers?? lstString = new List<string>(); if (lstTransfers.Count>1) { //look for matches foreach (IGrouping<Int32,ARPTransfer> item in lstTransfers.GroupBy(x=>x.ResourceID)) { String strTemp = item.First().resource.name; if (item.Any(x => x.transferState == TransferStateEnum.In) && item.Any(x => x.transferState == TransferStateEnum.Out)) { foreach (ARPTransfer t in item.Where(x=>x.transferState!= TransferStateEnum.None)) { t.Active = true; t.RatePerSec = (Single)lstPartWindows[t.partID].ResourceList[t.ResourceID].MaxAmount / 20; } strTemp += "Transfer"; } else { foreach (ARPTransfer t in item) { t.Active = false; } strTemp += "Waiting"; } lstString.Add(strTemp); } } }