Skip to content

Commit b3aa8e8

Browse files
Fix RemoteTechnologiesGroup#663 on autopilot commands not delayed
1 parent e78330c commit b3aa8e8

3 files changed

Lines changed: 126 additions & 10 deletions

File tree

src/RemoteTech/FlightComputer/Commands/AbstractCommand.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -109,16 +109,17 @@ public static ICommand LoadCommand(ConfigNode n, FlightComputer fc)
109109
// switch the different commands
110110
switch (n.name)
111111
{
112-
case "AttitudeCommand": { command = new AttitudeCommand(); break; }
113-
case "ActionGroupCommand": { command = new ActionGroupCommand(); break; }
114-
case "BurnCommand": { command = new BurnCommand(); break; }
115-
case "ManeuverCommand": { command = new ManeuverCommand(); break; }
116-
case "CancelCommand": { command = new CancelCommand(); break; }
117-
case "TargetCommand": { command = new TargetCommand(); break; }
118-
case "EventCommand": { command = new EventCommand(); break; }
119-
case "DriveCommand": { command = new DriveCommand(); break; }
120-
case "ExternalAPICommand": { command = new ExternalAPICommand(); break; }
121-
case "PartActionCommand": { command = new PartActionCommand(); break; }
112+
case "AttitudeCommand": { command = new AttitudeCommand(); break; }
113+
case "ActionGroupCommand": { command = new ActionGroupCommand(); break; }
114+
case "BurnCommand": { command = new BurnCommand(); break; }
115+
case "ManeuverCommand": { command = new ManeuverCommand(); break; }
116+
case "CancelCommand": { command = new CancelCommand(); break; }
117+
case "TargetCommand": { command = new TargetCommand(); break; }
118+
case "EventCommand": { command = new EventCommand(); break; }
119+
case "DriveCommand": { command = new DriveCommand(); break; }
120+
case "ExternalAPICommand": { command = new ExternalAPICommand(); break; }
121+
case "PartActionCommand": { command = new PartActionCommand(); break; }
122+
case "StockAutopilotCommand": { command = new StockAutopilotCommand(); break; }
122123
}
123124

124125
if (command != null)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System;
2+
using static VesselAutopilot;
3+
4+
namespace RemoteTech.FlightComputer.Commands
5+
{
6+
public class StockAutopilotCommand : AbstractCommand
7+
{
8+
[Persistent] public AutopilotMode AutopilotMode;
9+
public static VesselAutopilotUI UIreference = null;
10+
private static AutopilotMode savedAutopilotMode = AutopilotMode.StabilityAssist;
11+
12+
public override string ShortName
13+
{
14+
get
15+
{
16+
return AutopilotMode.ToString();
17+
}
18+
}
19+
20+
public override string Description
21+
{
22+
get
23+
{
24+
return "Autopilot: " + ShortName + Environment.NewLine + base.Description;
25+
}
26+
}
27+
28+
public override bool Pop(FlightComputer f)
29+
{
30+
if (f.Vessel.Autopilot.CanSetMode(AutopilotMode))
31+
{
32+
f.Vessel.Autopilot.SetMode(AutopilotMode);
33+
savedAutopilotMode = AutopilotMode; // be sure to update the saved mode after setting autpilot mode
34+
return false;
35+
}
36+
return true;
37+
}
38+
39+
public static StockAutopilotCommand WithNewMode(AutopilotMode newMode)
40+
{
41+
return new StockAutopilotCommand()
42+
{
43+
AutopilotMode = newMode,
44+
TimeStamp = RTUtil.GameTime,
45+
};
46+
}
47+
48+
/// <summary>
49+
/// Action to be called by a RT listener on KSP's autopilot buttons
50+
/// </summary>
51+
public static void AutopilotButtonClick(int index, FlightComputer flightCom)
52+
{
53+
var satellite = flightCom.Vessel;
54+
if (!satellite.HasLocalControl() && flightCom.InputAllowed)
55+
{
56+
//Note: the VesselAutopilotUI's OnClickButton is delayed by FlightComputer so no further action needed
57+
//Note: KSP bug #13199 (http://bugs.kerbalspaceprogram.com/issues/13199) on wrong-placed Radial In & Out buttons
58+
var currentMode = flightCom.Vessel.Autopilot.Mode;
59+
var nextMode = (AutopilotMode)index;
60+
61+
if (currentMode != nextMode)
62+
{
63+
savedAutopilotMode = currentMode; // autopilot's stock actionlistener will set to new mode so we need to roll back to prev mode via IsAutoPilotEngaged()
64+
var newCommand = WithNewMode(nextMode);
65+
flightCom.Enqueue(newCommand);
66+
67+
//Note: Timer of returning to prev mode doesn't really work too well in Unity and KSP architecture
68+
}
69+
}
70+
}
71+
72+
/// <summary>
73+
/// Check if KSP's autopilot is performing one SAS function in presence of long delay
74+
/// </summary>
75+
public static bool IsAutoPilotEngaged(FlightComputer flightCom)
76+
{
77+
if (!flightCom.Vessel.Autopilot.Enabled) // autopilot is off
78+
return false;
79+
80+
if (flightCom.Vessel.Autopilot.Mode != savedAutopilotMode && flightCom.Vessel.Autopilot.CanSetMode(savedAutopilotMode))
81+
flightCom.Vessel.Autopilot.SetMode(savedAutopilotMode); // purpose: return to the pre-click mode
82+
83+
if (GameSettings.PITCH_DOWN.GetKey() || GameSettings.PITCH_UP.GetKey() ||
84+
GameSettings.ROLL_LEFT.GetKey() || GameSettings.ROLL_RIGHT.GetKey() ||
85+
GameSettings.YAW_LEFT.GetKey() || GameSettings.YAW_RIGHT.GetKey()) // player trying to manually rotate
86+
return false;
87+
88+
return true;
89+
}
90+
}
91+
}

src/RemoteTech/FlightComputer/FlightComputer.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,15 @@ public FlightComputer(ISignalProcessor s)
161161

162162
RoverComputer = new RoverComputer();
163163
RoverComputer.SetVessel(Vessel);
164+
165+
// Add RT listeners from KSP Autopilot
166+
StockAutopilotCommand.UIreference = GameObject.FindObjectOfType<VesselAutopilotUI>();
167+
for (var index = 0; index < StockAutopilotCommand.UIreference.modeButtons.Length; index++)
168+
{
169+
var buttonIndex = index; // prevent compiler optimisation from assigning static final index value
170+
StockAutopilotCommand.UIreference.modeButtons[index].onClick.AddListener(delegate { StockAutopilotCommand.AutopilotButtonClick(buttonIndex, this); });
171+
// bad idea to use RemoveAllListeners() since no easy way to re-add the original stock listener to onClick
172+
}
164173
}
165174

166175
/// <summary>Called when a game switch is requested: close the current computer.</summary>
@@ -214,6 +223,17 @@ public void Dispose()
214223
}
215224

216225
_flightComputerWindow?.Hide();
226+
227+
// Remove RT listeners from KSP Autopilot
228+
if (StockAutopilotCommand.UIreference != null)
229+
{
230+
for (var index = 0; index < StockAutopilotCommand.UIreference.modeButtons.Length; index++)
231+
{
232+
var buttonIndex = index; // prevent compiler optimisation from assigning static final index value
233+
StockAutopilotCommand.UIreference.modeButtons[index].onClick.RemoveListener(delegate { StockAutopilotCommand.AutopilotButtonClick(buttonIndex, this); });
234+
}
235+
StockAutopilotCommand.UIreference = null;
236+
}
217237
}
218238

219239
/// <summary>Abort all active commands.</summary>
@@ -335,6 +355,10 @@ private void Enqueue(FlightCtrlState fs)
335355
{
336356
var dfs = new DelayedFlightCtrlState(fs);
337357
dfs.TimeStamp += Delay;
358+
359+
if(StockAutopilotCommand.IsAutoPilotEngaged(this)) // remove the delay if the autopilot is engaged
360+
dfs.TimeStamp -= Delay;
361+
338362
_flightCtrlQueue.Enqueue(dfs);
339363

340364
}

0 commit comments

Comments
 (0)