diff --git a/doc/source/commands/flight/cooked.rst b/doc/source/commands/flight/cooked.rst index fc2fb4b60..265f090d8 100644 --- a/doc/source/commands/flight/cooked.rst +++ b/doc/source/commands/flight/cooked.rst @@ -21,6 +21,15 @@ For more information, check out the documentation for the :struct:`SteeringManag In this style of controlling the craft, you do not steer the craft directly, but instead select a goal direction and let kOS pick the way to steer toward that goal. This method of controlling the craft consists primarily of the following two commands: +CONFIG:SUPPRESSAUTOPILOT +------------------------ + +If :attr:`Config:SUPPRESSAUTOPILOT` is true, then none of the controls +on this page will have an effect. That setting is there to provide +the player with an emergency way to quickly click a toggle on the +toolbar window to force kOS to stop taking control, letting the player +move the controls manually. + The special LOCK variables for cooked steering ---------------------------------------------- diff --git a/doc/source/commands/flight/raw.rst b/doc/source/commands/flight/raw.rst index dba1c18d0..e129032c1 100644 --- a/doc/source/commands/flight/raw.rst +++ b/doc/source/commands/flight/raw.rst @@ -37,6 +37,15 @@ This will start pushing the ship to rotate a bit faster to the right, like pushi One can use :ref:`SHIP:CONTROL:ROTATION ` and :ref:`SHIP:CONTROL:TRANSLATION ` to see the ship's current situation. +CONFIG:SUPPRESSAUTOPILOT +------------------------ + +If :attr:`Config:SUPPRESSAUTOPILOT` is true, then none of the controls +on this page will have an effect. That setting is there to provide +the player with an emergency way to quickly click a toggle on the +toolbar window to force kOS to stop taking control, letting the player +move the controls manually. + Breaking Ground DLC ------------------- diff --git a/doc/source/structures/misc/config.rst b/doc/source/structures/misc/config.rst index 6e81d0d04..0923dbe1c 100644 --- a/doc/source/structures/misc/config.rst +++ b/doc/source/structures/misc/config.rst @@ -60,10 +60,6 @@ Configuration of kOS - :struct:`Boolean` - False - Print statistics to screen - * - :attr:`RT` - - :struct:`Boolean` - - False - - Enable RemoteTech2 integration * - :attr:`ARCH` - :struct:`Boolean` - False @@ -84,6 +80,10 @@ Configuration of kOS - :struct:`Boolean` - False - Enable verbose exceptions + * - :attr:`SUPPRESSAUTOPILOT` + - :struct:`Boolean` + - False + - If true, kOS's controls do nothing. * - :attr:`TELNET` - :struct:`Boolean` - False @@ -150,18 +150,6 @@ Configuration of kOS :ref:`ProfileResult() ` function available, for deep analysis of your program run, if you are so inclined. -.. attribute:: Config:RT - - :access: Get/Set - :type: :struct:`Boolean` - - Configures the ``enableRTIntegration`` setting. - - If true, then the kOS mod will attempt to interact with the Remote Tech 2 mod, letting RT2 make decisions about whether or not a vessel is within communications range rather than having kOS use its own more primitive algorithm for it. - - Due to a long stall in the development of the RT2 mod, this setting should still be considered experimental at this point. - - .. attribute:: Config:ARCH :access: Get/Set @@ -224,6 +212,22 @@ Configuration of kOS If true, then it enables a mode in which errors coming from kOS are very long and verbose, trying to explain every detail of the problem. +.. attribute:: Config:SUPPRESSAUTOPILOT + + :access: Get/Set + :type: :struct:`Boolean` + + When this is set to True, it suppresses all of kOS's attempts to + override the steering, throttle, or translation controls, leaving + them entirely under manual control. It is intended to be a way + to let you take manual control in an emergency quickly (through + the toolbar window where this setting appears) without having to + quit the running program or figure out which terminal window has + the program causing the control lock. + + While it does suppress steering, throttle, and translation, it cannot + suppress action groups or staging. + .. attribute:: Config:TELNET :access: Get/Set diff --git a/src/kOS.Safe.Test/Execution/Config.cs b/src/kOS.Safe.Test/Execution/Config.cs index ed7bace71..945881e26 100644 --- a/src/kOS.Safe.Test/Execution/Config.cs +++ b/src/kOS.Safe.Test/Execution/Config.cs @@ -187,6 +187,17 @@ public int TerminalDefaultHeight } } + public bool SuppressAutopilot + { + get + { + return true; + } + + set + { + } + } public DateTime TimeStamp { get diff --git a/src/kOS.Safe/Encapsulation/IConfig.cs b/src/kOS.Safe/Encapsulation/IConfig.cs index cbf4ee381..03a82b104 100644 --- a/src/kOS.Safe/Encapsulation/IConfig.cs +++ b/src/kOS.Safe/Encapsulation/IConfig.cs @@ -23,6 +23,7 @@ public interface IConfig: ISuffixed double TerminalBrightness {get; set; } int TerminalDefaultWidth { get; set; } int TerminalDefaultHeight { get; set; } + bool SuppressAutopilot { get; set; } /// diff --git a/src/kOS/Control/IFlightControlParameter.cs b/src/kOS/Control/IFlightControlParameter.cs index 345c717e3..301b4befb 100644 --- a/src/kOS/Control/IFlightControlParameter.cs +++ b/src/kOS/Control/IFlightControlParameter.cs @@ -18,7 +18,24 @@ public interface IFlightControlParameter /// /// The responsible vessel. Vessel GetResponsibleVessel(); + /// + /// Called each update in which kOS CONFIG has autopilot enabled, to + /// ask this controller how to set the controls. + /// + /// the flight control state it should try to alter void UpdateAutopilot(FlightCtrlState c); + /// + /// Called each update in which kOS CONFIG has autopilot disabled, to + /// ask this controller if it *would have* set the controls had it + /// been allowed to. The controller should leave the state neutral + /// and not set it in this case. It should also use this as a signal to + /// clear out integral windup from any PIDs it's using, since its + /// control is being temporarily suppressed. + /// + /// the flight control state it should try to alter + /// true if this controller thinks it *would have* wanted to move the + /// controls had it not been getting suppressed + bool SuppressAutopilot(FlightCtrlState c); void EnableControl(SharedObjects shared); void DisableControl(SharedObjects shared); void DisableControl(); diff --git a/src/kOS/Control/SteeringManager.cs b/src/kOS/Control/SteeringManager.cs index d78e4f797..b96ab3a6b 100644 --- a/src/kOS/Control/SteeringManager.cs +++ b/src/kOS/Control/SteeringManager.cs @@ -1325,6 +1325,23 @@ void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c) this.OnFlyByWire(c); } + bool IFlightControlParameter.SuppressAutopilot(FlightCtrlState c) + { + if (!Enabled || Value == null) + { + return false; + } + else + { + pitchPI.ResetI(); + yawPI.ResetI(); + rollPI.ResetI(); + pitchRatePI.ResetI(); + yawRatePI.ResetI(); + rollRatePI.ResetI(); + return true; + } + } void IFlightControlParameter.EnableControl(SharedObjects shared) { diff --git a/src/kOS/Control/ThrottleManager.cs b/src/kOS/Control/ThrottleManager.cs index b302106a1..b9b95295e 100644 --- a/src/kOS/Control/ThrottleManager.cs +++ b/src/kOS/Control/ThrottleManager.cs @@ -1,4 +1,4 @@ -using kOS.Safe.Encapsulation; +using kOS.Safe.Encapsulation; using kOS.Safe.Exceptions; using kOS.Safe.Utilities; using System; @@ -96,6 +96,11 @@ void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c) { c.mainThrottle = (float)Value; } + + bool IFlightControlParameter.SuppressAutopilot(FlightCtrlState c) + { + return Enabled; + } void IFlightControlParameter.UpdateValue(object value, SharedObjects shared) { diff --git a/src/kOS/Control/WheelSteeringManager.cs b/src/kOS/Control/WheelSteeringManager.cs index 31acc152d..6751d712a 100644 --- a/src/kOS/Control/WheelSteeringManager.cs +++ b/src/kOS/Control/WheelSteeringManager.cs @@ -1,4 +1,4 @@ -using kOS.Safe.Encapsulation; +using kOS.Safe.Encapsulation; using kOS.Safe.Exceptions; using kOS.Safe.Utilities; using kOS.Suffixed; @@ -111,6 +111,11 @@ void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c) } } + bool IFlightControlParameter.SuppressAutopilot(FlightCtrlState c) + { + return Enabled; + } + void IFlightControlParameter.UpdateValue(object value, SharedObjects shared) { if (!Enabled) diff --git a/src/kOS/Control/WheelThrottleManager.cs b/src/kOS/Control/WheelThrottleManager.cs index 06e282060..8a697007d 100644 --- a/src/kOS/Control/WheelThrottleManager.cs +++ b/src/kOS/Control/WheelThrottleManager.cs @@ -1,4 +1,4 @@ -using kOS.Safe.Encapsulation; +using kOS.Safe.Encapsulation; using kOS.Safe.Exceptions; using kOS.Safe.Utilities; using System; @@ -94,7 +94,15 @@ object IFlightControlParameter.GetValue() void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c) { - c.wheelThrottle = (float)KOSMath.Clamp(Value, -1, 1); + if (Enabled) + { + c.wheelThrottle = (float)KOSMath.Clamp(Value, -1, 1); + } + } + + bool IFlightControlParameter.SuppressAutopilot(FlightCtrlState c) + { + return Enabled; } void IFlightControlParameter.UpdateValue(object value, SharedObjects shared) diff --git a/src/kOS/Module/kOSVesselModule.cs b/src/kOS/Module/kOSVesselModule.cs index c114c6472..17efa407e 100644 --- a/src/kOS/Module/kOSVesselModule.cs +++ b/src/kOS/Module/kOSVesselModule.cs @@ -399,6 +399,11 @@ private void UpdateAutopilot(FlightCtrlState c) if (RP0Lock != 0) return; + bool isSuppressing = SafeHouse.Config.SuppressAutopilot; + + // Default it to false until it gets turned on below: + Screen.KOSToolbarWindow.ShowSuppressMessage = false; + if (Vessel != null) { if (childParts.Count > 0) @@ -416,7 +421,15 @@ private void UpdateAutopilot(FlightCtrlState c) parameter.GetShared().Vessel.id, Vessel.id)); foundWrongVesselAutopilot = true; } - parameter.UpdateAutopilot(c); + if (isSuppressing) + { + if (parameter.SuppressAutopilot(c)) + Screen.KOSToolbarWindow.ShowSuppressMessage = true; + } + else + { + parameter.UpdateAutopilot(c); + } } } } diff --git a/src/kOS/Screen/KOSToolbarWindow.cs b/src/kOS/Screen/KOSToolbarWindow.cs index e5e461db9..0b20760b1 100644 --- a/src/kOS/Screen/KOSToolbarWindow.cs +++ b/src/kOS/Screen/KOSToolbarWindow.cs @@ -90,6 +90,13 @@ public class KOSToolbarWindow : MonoBehaviour private bool uiGloballyHidden = false; + /// Timestamp (using Unity3d's Time.time) for when the suppression message cooldown is over and a new message should be emitted. + private static float suppressMessageCooldownEnd = 0; + private static string suppressMessageText = "kOS's config setting is preventing kOS control."; + private static ScreenMessage suppressMessage; + /// If true then the 'suppressing autopilot' message should be getting repeated to the screen right now. + public static bool ShowSuppressMessage { get; set; } + /// /// Unity hates it when a MonoBehaviour has a constructor, /// so all the construction work is here instead: @@ -134,10 +141,36 @@ public void Start() // Prevent multiple calls of this: if (alreadyAwake) return; alreadyAwake = true; + ShowSuppressMessage = false; SafeHouse.Logger.SuperVerbose("[kOSToolBarWindow] Start succesful"); } + public void Update() + { + // Handle the message and timeout of the message + if (ShowSuppressMessage) + { + if (Time.time > suppressMessageCooldownEnd) + { + suppressMessageCooldownEnd = Time.time + 5f; + suppressMessage = ScreenMessages.PostScreenMessage( + string.Format("{0}", suppressMessageText), + 4, ScreenMessageStyle.UPPER_CENTER); + } + } + else + { + suppressMessageCooldownEnd = 0f; + if (suppressMessage != null) + { + // Get it to stop right away even if the timer isn't over: + suppressMessage.duration = 0; + } + } + + } + public void AddButton() { if (!ApplicationLauncher.Ready) return; @@ -458,7 +491,7 @@ public void DrawWindow(int windowID) DrawActiveCPUsOnPanel(); - CountBeginVertical("", 150); + CountBeginVertical("", 155); GUILayout.Label("CONFIG VALUES", headingLabelStyle); GUILayout.Label("To access other settings, see the kOS section in KSP's difficulty settings.", smallLabelStyle); GUILayout.Label("Global VALUES", headingLabelStyle); diff --git a/src/kOS/Suffixed/Config.cs b/src/kOS/Suffixed/Config.cs index bad4005d7..f86a27c17 100644 --- a/src/kOS/Suffixed/Config.cs +++ b/src/kOS/Suffixed/Config.cs @@ -33,6 +33,7 @@ public class Config : Structure, IConfig public int TerminalDefaultHeight { get { return GetPropValue(PropId.TerminalDefaultHeight); } set { SetPropValue(PropId.TerminalDefaultHeight, value); } } public bool UseBlizzyToolbarOnly { get { return kOSCustomParameters.Instance.useBlizzyToolbarOnly; } set { kOSCustomParameters.Instance.useBlizzyToolbarOnly = value; } } public bool DebugEachOpcode { get { return kOSCustomParameters.Instance.debugEachOpcode; } set { kOSCustomParameters.Instance.debugEachOpcode = value; } } + public bool SuppressAutopilot { get { return GetPropValue(PropId.SuppressAutopilot); } set { SetPropValue(PropId.SuppressAutopilot, value); } } // NOTE TO FUTURE MAINTAINERS: If it looks like overkill to use a double instead of a float for this next field, you're right. // But KSP seems to have a bug where single-precision floats don't get saved in the config XML file. Doubles seem to work, though. @@ -65,6 +66,7 @@ private void InitializeSuffixes() AddSuffix("DEFAULTFONTSIZE", new ClampSetSuffix(() => TerminalFontDefaultSize, value => TerminalFontDefaultSize = value, 6f, 30f, 1f)); AddSuffix("DEFAULTWIDTH", new ClampSetSuffix(() => TerminalDefaultWidth, value => TerminalDefaultWidth = value, 15f, 255f, 1f)); AddSuffix("DEFAULTHEIGHT", new ClampSetSuffix(() => TerminalDefaultHeight, value => TerminalDefaultHeight = value, 3f, 160f, 1f)); + AddSuffix("SUPPRESSAUTOPILOT", new SetSuffix(() => SuppressAutopilot, value => SuppressAutopilot = value)); } private void BuildValuesDictionary() @@ -77,6 +79,7 @@ private void BuildValuesDictionary() AddConfigKey(PropId.TerminalBrightness, new ConfigKey("TerminalBrightness", "BRIGHTNESS", "Initial brightness setting for new terminals", 0.7d, 0d, 1d, typeof(double))); AddConfigKey(PropId.TerminalDefaultWidth, new ConfigKey("TerminalDefaultWidth", "DEFAULTWIDTH", "Initial Terminal:WIDTH when a terminal is first opened", 50, 15, 255, typeof(int))); AddConfigKey(PropId.TerminalDefaultHeight, new ConfigKey("TerminalDefaultHeight", "DEFAULTHEIGHT", "Initial Terminal:HEIGHT when a terminal is first opened", 36, 3, 160, typeof(int))); + AddConfigKey(PropId.SuppressAutopilot, new ConfigKey("SuppressAutopilot", "SUPPRESSAUTOPILOT", "Suppress all kOS autopiloting for emergency manual control", false, false, true, typeof(bool))); } private void AddConfigKey(PropId id, ConfigKey key) @@ -240,7 +243,8 @@ private enum PropId TerminalFontName = 16, TerminalBrightness = 17, TerminalDefaultWidth = 18, - TerminalDefaultHeight = 19 + TerminalDefaultHeight = 19, + SuppressAutopilot = 20 } } } diff --git a/src/kOS/Suffixed/FlightControl.cs b/src/kOS/Suffixed/FlightControl.cs index f2d9b9520..dd28ded45 100644 --- a/src/kOS/Suffixed/FlightControl.cs +++ b/src/kOS/Suffixed/FlightControl.cs @@ -371,6 +371,11 @@ void IFlightControlParameter.UpdateAutopilot(FlightCtrlState c) OnFlyByWire(c); } + bool IFlightControlParameter.SuppressAutopilot(FlightCtrlState c) + { + return !(IsNeutral()); + } + void IFlightControlParameter.EnableControl(SharedObjects shared) { // No need to enable control, it will automatically enable based on setting values