diff --git a/README.txt b/README.txt index d00d7b9..bd559bc 100644 --- a/README.txt +++ b/README.txt @@ -98,6 +98,12 @@ v0.6 Upgraded GUI, Improved parts, and KSP .24 compatibility * Removed redundant fuel controller ("ON") v0.6.1 KSP .24.1 compatibility * KSP .24.1 compatibility +v0.6.2 KSP .24.2 compatibility + * KSP .24.2 compatibility +v2.0.2 Updated KSPAPIExtension and Real Fuels compatbility + * Updated KSPAPIExtension to 1.7.0 + * Auto stager now fully supports Real Fuels and will auto update on tank resource change + * No longer dependant on km_lib.dll diff --git a/Release/Release.zip b/Release/Release.zip index aef4ac3..205a884 100644 Binary files a/Release/Release.zip and b/Release/Release.zip differ diff --git a/Source/km_FlameoutChecker.cs b/Source/km_FlameoutChecker.cs index ad3f4d4..9dbc663 100644 --- a/Source/km_FlameoutChecker.cs +++ b/Source/km_FlameoutChecker.cs @@ -68,7 +68,7 @@ public override void OnUpdate(){ flameout = engines[0].getIgnitionState; if (!hasFired && engines[0].getFlameoutState && engines[0].getIgnitionState) { hasFired = true; - Utility.fireEvent (this.part, int.Parse(group)); + km_Helper.fireEvent(this.part, int.Parse(group)); } else if (!engines[0].getFlameoutState && engines[0].getIgnitionState) { diff --git a/Source/km_Helper.cs b/Source/km_Helper.cs new file mode 100644 index 0000000..ec9541b --- /dev/null +++ b/Source/km_Helper.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using UnityEngine; +using KSP.IO; + +namespace KM_Lib +{ + public static class km_Helper + { + #region Dictionary + + public static Dictionary KM_dictAG = new Dictionary + { + {0, KSPActionGroup.None}, + {1, KSPActionGroup.Custom01}, + {2, KSPActionGroup.Custom02}, + {3, KSPActionGroup.Custom03}, + {4, KSPActionGroup.Custom04}, + {5, KSPActionGroup.Custom05}, + {6, KSPActionGroup.Custom06}, + {7, KSPActionGroup.Custom07}, + {8, KSPActionGroup.Custom08}, + {9, KSPActionGroup.Custom09}, + {10, KSPActionGroup.Custom10}, + {11, KSPActionGroup.Light}, + {12, KSPActionGroup.RCS}, + {13, KSPActionGroup.SAS}, + {14, KSPActionGroup.Brakes}, + {15, KSPActionGroup.Abort} + }; + + public static Dictionary KM_dictAGNames = new Dictionary + { + {0, "Stage"}, + {1, "Custom01"}, + {2, "Custom02"}, + {3, "Custom03"}, + {4, "Custom04"}, + {5, "Custom05"}, + {6, "Custom06"}, + {7, "Custom07"}, + {8, "Custom08"}, + {9, "Custom09"}, + {10, "Custom10"}, + {11, "Light"}, + {12, "RCS"}, + {13, "SAS"}, + {14, "Brakes"}, + {15, "Abort"}, + {16, "Beep"}, + }; + + public static int maxEvent = 17; + + #endregion + + #region Animation Methods + + public static void switchLight(Part p, String lightName, bool state) { + Transform lightTransform = p.FindModelTransform(lightName); + if (lightTransform != null) { + Light light = lightTransform.GetComponent(); + if (light != null) + light.intensity = (state ? 1 : 0); + } + } + + public static void playAnimationSetToPosition(Part p, string animationName, float position) { + Animation anim; + anim = p.FindModelAnimators(animationName).FirstOrDefault(); + if (anim != null) { + anim[animationName].normalizedTime = position; + anim[animationName].speed = 0f; + anim.Play(animationName); + // anim [animationName].speed = 0; + } + } + + + public static void playAudio(Part p, string clipName) { + if (clipName != "") { + AudioSource sound; + sound = p.gameObject.AddComponent(); + sound.clip = GameDatabase.Instance.GetAudioClip(clipName); + if (sound.clip != null) { + sound.volume = 1; + sound.Stop(); + sound.Play(); + } + } + } + + #endregion + + #region Staging/AG Methods + + public static void fireEvent(Part p, int eventID) { + if (p == null) + return; + if (eventID == 0) { + MonoBehaviour.print("Fire Stage from part " + p); + fireNextNonEmptyStage(p.vessel); + return; + } + else if (eventID > 0 && eventID <= maxEvent) { + MonoBehaviour.print("Fire Event " + KM_dictAGNames[eventID] + " from part " + p); + p.vessel.ActionGroups.ToggleGroup(KM_dictAG[eventID]); + } + } + + public static void fireNextNonEmptyStage(Vessel v) { + // the parts to be fired + List resultList = new List(); + + int highestNextStage = getHighestNextStage(v.rootPart, v.currentStage); + traverseChildren(v.rootPart, highestNextStage, ref resultList); + + foreach (Part stageItem in resultList) { + MonoBehaviour.print("Activate:" + stageItem); + stageItem.activate(highestNextStage, stageItem.vessel); + stageItem.inverseStage = v.currentStage; + } + v.currentStage = highestNextStage; + //If this is the currently active vessel, activate the next, now empty, stage. This is an ugly, ugly hack but it's the only way to clear out the empty stage. + //Switching to a vessel that has been staged this way already clears out the empty stage, so this isn't required for those. + if (v.isActiveVessel) { + Staging.ActivateNextStage(); + } + } + + private static int getHighestNextStage(Part p, int currentStage) { + + int highestChildStage = 0; + + // if this is the root part and its a decoupler: ignore it. It was probably fired before. + // This is dirty guesswork but everything else seems not to work. KSP staging is too messy. + if (p.vessel.rootPart == p && + (p.name.IndexOf("ecoupl") != -1 || p.name.IndexOf("eparat") != -1)) { + } + else if (p.inverseStage < currentStage) { + highestChildStage = p.inverseStage; + } + + + // Check all children. If this part has no children, inversestage or current Stage will be returned + int childStage = 0; + foreach (Part child in p.children) { + childStage = getHighestNextStage(child, currentStage); + if (childStage > highestChildStage && childStage < currentStage) { + highestChildStage = childStage; + } + } + return highestChildStage; + } + + private static void traverseChildren(Part p, int nextStage, ref List resultList) { + if (p.inverseStage >= nextStage) { + resultList.Add(p); + } + foreach (Part child in p.children) { + traverseChildren(child, nextStage, ref resultList); + } + } + + #endregion + } +} diff --git a/Source/km_RadioControl.cs b/Source/km_RadioControl.cs index c1352d2..c0b706f 100644 --- a/Source/km_RadioControl.cs +++ b/Source/km_RadioControl.cs @@ -265,17 +265,17 @@ public void transmitThrottle() } private void indicateSend(){ - Utility.switchLight (this.part, "light-go", true); - Utility.playAnimationSetToPosition (this.part, "glow", 1); + km_Helper.switchLight (this.part, "light-go", true); + km_Helper.playAnimationSetToPosition(this.part, "glow", 1); fireTime = Time.fixedTime; print ("Fire Time:" + fireTime); } private void indicateReceive(bool playSound){ - Utility.switchLight (this.part, "light-go", true); - Utility.playAnimationSetToPosition (this.part, "glow", 1); + km_Helper.switchLight(this.part, "light-go", true); + km_Helper.playAnimationSetToPosition(this.part, "glow", 1); fireTime = Time.fixedTime; - if(playSound)Utility.playAudio(this.part, rcv_sound); + if (playSound) km_Helper.playAudio(this.part, rcv_sound); print ("Fire Time:" + fireTime); } @@ -284,8 +284,8 @@ public void receiveCommand(KM_RadioControl sender, int group, int transmitChanne MonoBehaviour.print ("I am the sender or channels are not equal:" + channel + ", " + transmitChannel); return; } - print ("Listener:" + vessel.vesselName + "received command" + group); - Utility.fireEvent (this.part, (int)group); + print ("Listener:" + vessel.vesselName + "received command" + group); + km_Helper.fireEvent(this.part, (int)group); indicateReceive (true); } @@ -339,8 +339,8 @@ public override void OnUpdate() updateCounter++; if (fireTime != 0 && fireTime + lightOnTime <= Time.time) { - Utility.switchLight (this.part, "light-go", false); - Utility.playAnimationSetToPosition (this.part, "glow", 0); + km_Helper.switchLight(this.part, "light-go", false); + km_Helper.playAnimationSetToPosition(this.part, "glow", 0); } //if (fireTime != 0 && fireTime + 10 <= Time.time) { diff --git a/Source/km_Stager.cs b/Source/km_Stager.cs index 0f53867..1050590 100644 --- a/Source/km_Stager.cs +++ b/Source/km_Stager.cs @@ -108,7 +108,7 @@ public override void OnUpdate() { if (isActive && observedPart != null && monitoredResource != "Empty") { //Check fuel percantage and compare it to target percentage if (((observedPart.Resources[monitoredResource].amount / observedPart.Resources[monitoredResource].maxAmount) * 100) <= activationPercentage) { - Utility.fireEvent(this.part, int.Parse(group)); + km_Helper.fireEvent(this.part, int.Parse(group)); print("KM Stager: Target percentage hit"); isActive = false; } diff --git a/Source/km_Timer.cs b/Source/km_Timer.cs index b170cde..5a5a831 100644 --- a/Source/km_Timer.cs +++ b/Source/km_Timer.cs @@ -163,14 +163,14 @@ public override void OnUpdate() //If the timer has been activated, start the countdown, activate the model's LED, and change the icon color if (triggerTime > 0 && armed) { remainingTime = triggerTime + (useSeconds ? triggerDelaySeconds : triggerDelayMinutes * 60) - Time.time; - Utility.switchLight(this.part, "light-go", true); - Utility.playAnimationSetToPosition(this.part, "glow", 1); + km_Helper.switchLight(this.part, "light-go", true); + km_Helper.playAnimationSetToPosition(this.part, "glow", 1); this.part.stackIcon.SetIconColor(XKCDColors.BrightYellow); //Once the timer hits 0 activate the stage/AG, disable the model's LED, and change the icon color if (remainingTime < 0) { - print ("Stage:"+Utility.KM_dictAGNames [int.Parse(group)]); - Utility.fireEvent (this.part, int.Parse(group)); + print("Stage:" + km_Helper.KM_dictAGNames[int.Parse(group)]); + km_Helper.fireEvent(this.part, int.Parse(group)); this.part.stackIcon.SetIconColor(XKCDColors.Red); triggerTime = 0; remainingTime = 0; @@ -224,8 +224,8 @@ private void reset() { triggerTime = 0; remainingTime = 0; //Switch off model lights - Utility.switchLight(this.part, "light-go", false); - Utility.playAnimationSetToPosition(this.part, "glow", 0); + km_Helper.switchLight(this.part, "light-go", false); + km_Helper.playAnimationSetToPosition(this.part, "glow", 0); //Reset icon color to white this.part.stackIcon.SetIconColor(XKCDColors.White); //Reset armed variable diff --git a/Source/km_altimeter.cs b/Source/km_altimeter.cs index 18125ff..3de7476 100644 --- a/Source/km_altimeter.cs +++ b/Source/km_altimeter.cs @@ -128,7 +128,7 @@ public override void OnUpdate() { } //In order for physics to take effect on jettisoned parts, the staging event has to be fired from OnUpdate if (fireNextupdate) { - Utility.fireEvent(this.part, int.Parse(group)); + km_Helper.fireEvent(this.part, int.Parse(group)); fireNextupdate = false; } } @@ -189,15 +189,15 @@ private void updateAltitude() { private void lightsOn() { //Switch off model lights - Utility.switchLight(this.part, "light-go", true); - Utility.playAnimationSetToPosition(this.part, "glow", 1); + km_Helper.switchLight(this.part, "light-go", true); + km_Helper.playAnimationSetToPosition(this.part, "glow", 1); illuminated = true; } private void lightsOff() { //Switch off model lights - Utility.switchLight(this.part, "light-go", false); - Utility.playAnimationSetToPosition(this.part, "glow", 0); + km_Helper.switchLight(this.part, "light-go", false); + km_Helper.playAnimationSetToPosition(this.part, "glow", 0); illuminated = false; } diff --git a/km_SmartParts.csproj b/km_SmartParts.csproj index 08f6fe8..b481fc3 100644 --- a/km_SmartParts.csproj +++ b/km_SmartParts.csproj @@ -39,10 +39,6 @@ C:\SteamPriority\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp-firstpass.dll False - - C:\SteamPriority\SteamApps\common\Kerbal Space Program\GameData\Klockheed_Martian\Plugins\km_Lib.dll - False - C:\SteamPriority\SteamApps\common\Kerbal Space Program\GameData\Klockheed_Martian_SmartParts\Plugins\KSPAPIExtensions.dll False @@ -57,6 +53,7 @@ + @@ -67,6 +64,7 @@ xcopy $(TargetPath) "C:\SteamPriority\SteamApps\common\Kerbal Space Program\GameData\Klockheed_Martian_SmartParts\Plugins" /y rd /s /q $(SolutionDir)obj +rd /s /q $(SolutionDir)bin del "$(TargetDir)km_SmartParts.pdb" del "$(SolutionDir)Release\Release.zip" "C:\Utilities\WinRar\winrar.exe" a -ep1 -IBCK -apGameData "$(SolutionDir)Release\Release.zip" "C:\SteamPriority\SteamApps\common\Kerbal Space Program\GameData\Klockheed_Martian_SmartParts"