diff --git a/.idea/.idea.MechJeb2/.idea/.name b/.idea/.idea.MechJeb2/.idea/.name new file mode 100644 index 000000000..43692dea2 --- /dev/null +++ b/.idea/.idea.MechJeb2/.idea/.name @@ -0,0 +1 @@ +MechJeb2 \ No newline at end of file diff --git a/MechJeb2.sln.DotSettings b/MechJeb2.sln.DotSettings index feb718a5d..3bb805e6a 100644 --- a/MechJeb2.sln.DotSettings +++ b/MechJeb2.sln.DotSettings @@ -24,6 +24,7 @@ KSP LAN LD + LH LQR MET MJ @@ -32,6 +33,8 @@ PVG RC RCS + RH + RHS RK RO SI diff --git a/MechJeb2/Maneuver/TransferCalculator.cs b/MechJeb2/Maneuver/TransferCalculator.cs index e94e8897e..cc8ae8027 100644 --- a/MechJeb2/Maneuver/TransferCalculator.cs +++ b/MechJeb2/Maneuver/TransferCalculator.cs @@ -351,11 +351,11 @@ private void AdjustPeriapsis(ManeuverParameters maneuver, ref double utArrival) Debug.Log("maneuver guess dV: " + maneuver.dV); Debug.Log("maneuver guess UT: " + maneuver.UT); Debug.Log("arrival guess UT: " + utArrival); - _initialOrbit.GetOrbitalStateVectorsAtUT(maneuver.UT, out Vector3d r1, out Vector3d v1); + _initialOrbit.FixedGetOrbitalStateVectorsAtUT(maneuver.UT, out Vector3d r1, out Vector3d v1); Debug.Log($"initial orbit at {maneuver.UT} x = {r1}; v = {v1}"); - _initialOrbit.referenceBody.orbit.GetOrbitalStateVectorsAtUT(maneuver.UT, out Vector3d r2, out Vector3d v2); + _initialOrbit.referenceBody.orbit.FixedGetOrbitalStateVectorsAtUT(maneuver.UT, out Vector3d r2, out Vector3d v2); Debug.Log($"source at {maneuver.UT} x = {r2}; v = {v2}"); - _targetBody.orbit.GetOrbitalStateVectorsAtUT(utArrival, out Vector3d r3, out Vector3d v3); + _targetBody.orbit.FixedGetOrbitalStateVectorsAtUT(utArrival, out Vector3d r3, out Vector3d v3); Debug.Log($"source at {utArrival} x = {r3}; v = {v3}"); _impulseScale = maneuver.dV.magnitude; diff --git a/MechJeb2/MechJebCore.cs b/MechJeb2/MechJebCore.cs index 36f6f2881..cf9333768 100644 --- a/MechJeb2/MechJebCore.cs +++ b/MechJeb2/MechJebCore.cs @@ -787,7 +787,7 @@ public override void OnLoad(ConfigNode sfsNode) LoadComputerModules(); var global = new ConfigNode("MechJebGlobalSettings"); - if (File.Exists("mechjeb_settings_global.cfg")) + if (MuUtils.FileExistsCreateDirectory(MuUtils.GetCfgPath("mechjeb_settings_global.cfg"))) { try { @@ -809,7 +809,7 @@ public override void OnLoad(ConfigNode sfsNode) vessel != null ? string.Join("_", vessel.vesselName.Split(Path.GetInvalidFileNameChars())) : ""; // Strip illegal char from the filename - if (vessel != null && File.Exists("mechjeb_settings_type_" + vesselName + ".cfg")) + if (vessel != null && MuUtils.FileExistsCreateDirectory(MuUtils.GetCfgPath("mechjeb_settings_type_" + vesselName + ".cfg"))) { try { diff --git a/MechJeb2/MechJebModuleAscentMenu.cs b/MechJeb2/MechJebModuleAscentMenu.cs index 92ae1c1ec..d8f1117da 100644 --- a/MechJeb2/MechJebModuleAscentMenu.cs +++ b/MechJeb2/MechJebModuleAscentMenu.cs @@ -49,18 +49,11 @@ private bool _launchingToLan private bool _launchingWithAnyPlaneControl => _launchingToPlane || _launchingToRendezvous || _launchingToMatchLan || _launchingToLan; - private MechJebModuleAscentBaseAutopilot _autopilot => Core.Ascent; - private MechJebModuleAscentSettings _ascentSettings => Core.AscentSettings; - private MechJebModuleAscentClassicPathMenu _classicPathMenu; - private MechJebModuleAscentPVGSettingsMenu _pvgSettingsMenu; - private MechJebModuleAscentSettingsMenu _settingsMenu; - - public override void OnStart(PartModule.StartState state) - { - _pvgSettingsMenu = Core.GetComputerModule(); - _settingsMenu = Core.GetComputerModule(); - _classicPathMenu = Core.GetComputerModule(); - } + private MechJebModuleAscentBaseAutopilot _autopilot => Core.Ascent; + private MechJebModuleAscentSettings _ascentSettings => Core.AscentSettings; + private MechJebModuleAscentClassicPathMenu _classicPathMenu => Core.GetComputerModule(); + private MechJebModuleAscentPVGSettingsMenu _pvgSettingsMenu => Core.GetComputerModule(); + private MechJebModuleAscentSettingsMenu _settingsMenu => Core.GetComputerModule(); [UsedImplicitly] [Persistent(pass = (int)Pass.GLOBAL)] diff --git a/MechJeb2/MechJebModuleNodeExecutor.cs b/MechJeb2/MechJebModuleNodeExecutor.cs index 83473513a..dffee32e2 100644 --- a/MechJeb2/MechJebModuleNodeExecutor.cs +++ b/MechJeb2/MechJebModuleNodeExecutor.cs @@ -300,7 +300,7 @@ private void StateBurn() private void SetAttitude() { - Core.Attitude.attitudeTo(_worldDirection, AttitudeReference.INERTIAL, this, killRollRotation:KillRollRotation); + Core.Attitude.attitudeTo(_worldDirection, AttitudeReference.INERTIAL_COT, this, killRollRotation:KillRollRotation); } private bool ShouldTerminatePrincipia() diff --git a/MechJeb2/MechJebModuleStagingController.cs b/MechJeb2/MechJebModuleStagingController.cs index 9ef5e7c1b..ef3364a31 100644 --- a/MechJeb2/MechJebModuleStagingController.cs +++ b/MechJeb2/MechJebModuleStagingController.cs @@ -684,7 +684,7 @@ private bool HasFairingUncached(int inverseStage) // payload fairing now (fixing payload fairings causing stacks to not decouple). // if a user requires an interstage fairing that is alone in a stage with no stack decoupler, engine, or // anything else in the stage (for cinematics?) then the user MUST use proc fairings. - return _partsInStage.Slinq().All(p => p.IsDecoupler() && !p.IsLaunchClamp() && p.children.Count == 0); + return _partsInStage.Slinq().All(p => ((p.IsDecoupler() && p.children.Count == 0) || p.HasModule() ) && !p.IsLaunchClamp()); } } } diff --git a/MechJeb2/MechJebModuleWaypointWindow.cs b/MechJeb2/MechJebModuleWaypointWindow.cs index 5e3a50dca..de00bfff7 100644 --- a/MechJeb2/MechJebModuleWaypointWindow.cs +++ b/MechJeb2/MechJebModuleWaypointWindow.cs @@ -366,7 +366,7 @@ public override void OnLoad(ConfigNode local, ConfigNode type, ConfigNode global if (!FlightGlobals.ready) return; // bodies not loaded yet var wps = new ConfigNode("Routes"); - if (File.Exists("mechjeb_routes.cfg")) + if (MuUtils.FileExistsCreateDirectory(MuUtils.GetCfgPath("mechjeb_routes.cfg"))) { try { diff --git a/MechJeb2/MuUtils.cs b/MechJeb2/MuUtils.cs index b7fbdf829..4458776cb 100644 --- a/MechJeb2/MuUtils.cs +++ b/MechJeb2/MuUtils.cs @@ -11,6 +11,15 @@ public static class MuUtils public static string GetCfgPath(string file) => Path.Combine(_cfgPath, file); + // Duplicates the KSP.IO.File.Exist style API where it creates the directory if it doesn't exist + public static bool FileExistsCreateDirectory(string path) + { + string directoryName = Path.GetDirectoryName(path); + if (directoryName != null && !Directory.Exists(directoryName)) + Directory.CreateDirectory(directoryName); + return File.Exists(path); + } + public static string PadPositive(double x, string format = "F3") { string s = x.ToString(format); diff --git a/MechJeb2/OrbitExtensions.cs b/MechJeb2/OrbitExtensions.cs index 26cae7de2..6450e0163 100644 --- a/MechJeb2/OrbitExtensions.cs +++ b/MechJeb2/OrbitExtensions.cs @@ -71,10 +71,21 @@ public static class OrbitExtensions [MethodImpl(MethodImplOptions.AggressiveInlining)] public static (V3 pos, V3 vel) RightHandedStateVectorsAtUT(this Orbit o, double ut) { - o.GetOrbitalStateVectorsAtUT(ut, out Vector3d pos, out Vector3d vel); + // GetOrbitalStateVectorsAtUT() uses a crazy future-rotation-at-UT to rotate vectors, so carefully avoid it. + o.GetOrbitalStateVectorsAtTrueAnomaly(o.TrueAnomalyAtT(o.getObtAtUT(ut)), ut, false, out Vector3d pos, out Vector3d vel); + pos = Planetarium.Zup.WorldToLocal(pos); + vel = Planetarium.Zup.WorldToLocal(vel); return (pos.ToV3(), vel.ToV3()); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void FixedGetOrbitalStateVectorsAtUT(this Orbit o, double ut, out Vector3d pos, out Vector3d vel) + { + o.GetOrbitalStateVectorsAtTrueAnomaly(o.TrueAnomalyAtT(o.getObtAtUT(ut)), ut, false, out pos, out vel); + pos = Planetarium.Zup.WorldToLocal(pos); + vel = Planetarium.Zup.WorldToLocal(vel); + } + //normalized vector perpendicular to the orbital plane //convention: as you look down along the orbit normal, the satellite revolves counterclockwise [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -120,51 +131,6 @@ public static Vector3d North(this Orbit o, double ut) => public static Orbit PerturbedOrbit(this Orbit o, double ut, Vector3d dV) => MuUtils.OrbitFromStateVectors(o.WorldPositionAtUT(ut), o.WorldOrbitalVelocityAtUT(ut) + dV, o.referenceBody, ut); - // returns a new orbit that is identical to the current one (although the epoch will change) - // (i tried many different APIs in the orbit class, but the GetOrbitalStateVectors/UpdateFromStateVectors route was the only one that worked) - public static Orbit Clone(this Orbit o, double ut = double.NegativeInfinity) - { - // hack up a dynamic default value to the current time - if (double.IsNegativeInfinity(ut)) - ut = Planetarium.GetUniversalTime(); - - var newOrbit = new Orbit(); - o.GetOrbitalStateVectorsAtUT(ut, out Vector3d pos, out Vector3d vel); - newOrbit.UpdateFromStateVectors(pos, vel, o.referenceBody, ut); - - return newOrbit; - } - - // calculate the next patch, which makes patchEndTransition be valid - // - public static Orbit CalculateNextOrbit(this Orbit o, double ut = double.NegativeInfinity) - { - var solverParameters = new PatchedConics.SolverParameters(); - - // hack up a dynamic default value to the current time - if (double.IsNegativeInfinity(ut)) - ut = Planetarium.GetUniversalTime(); - - o.StartUT = ut; - o.EndUT = o.eccentricity >= 1.0 ? o.period : ut + o.period; - var nextOrbit = new Orbit(); - PatchedConics.CalculatePatch(o, nextOrbit, ut, solverParameters, null); - - return nextOrbit; - } - - // This does not allocate a new orbit object and the caller should call new Orbit if/when required - public static void MutatedOrbit(this Orbit o, double periodOffset = double.NegativeInfinity) - { - double ut = Planetarium.GetUniversalTime(); - - if (!periodOffset.IsFinite()) - return; - - o.GetOrbitalStateVectorsAtUT(ut + o.period * periodOffset, out Vector3d pos, out Vector3d vel); - o.UpdateFromStateVectors(pos, vel, o.referenceBody, ut); - } - // circular orbital speed at this instant [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double CircularOrbitSpeed(this Orbit o) => Astro.CircularVelocity(o.referenceBody.gravParameter, o.radius); diff --git a/MechJeb2/Properties/AssemblyInfo.cs b/MechJeb2/Properties/AssemblyInfo.cs index b70c7f70d..0a1df9a5d 100644 --- a/MechJeb2/Properties/AssemblyInfo.cs +++ b/MechJeb2/Properties/AssemblyInfo.cs @@ -23,18 +23,9 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("a903d9fe-4604-47b8-b9d9-95728538f769")] -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("2.5.1.0")] // We should not change it anymore. It break mods that links MJ ( cf http://support.microsoft.com/kb/556041 ) -[assembly: AssemblyFileVersion("2.15.2.0")] // this one we can change all we want +// We use a 2.[Major].[Minor/Patch].0 naming convention +[assembly: AssemblyVersion("2.15.0.0")] // This should be bumped for major versions/breaking changes when the 2nd number changes +[assembly: AssemblyFileVersion("2.15.3.0")] // this one is bumped every single time for both minor/patch [assembly: AssemblyInformationalVersion("")] // Displayed in the window title if not empty (used to display dev #) -[assembly: KSPAssembly("MechJeb2", 2, 5)] +[assembly: KSPAssembly("MechJeb2", 2, 15, 3)] // this one is bumped every single time for both minor/patch