Merge branch 'master' into dev-EditorTWR
Merge branch 'master' into dev-EditorTWR

<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup> <PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug_win</Configuration>
<ProductVersion>8.0.30703</ProductVersion> <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion> <SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{45ACC1CC-942C-4A66-BFC7-8BE375938B18}</ProjectGuid> <ProjectGuid>{45ACC1CC-942C-4A66-BFC7-8BE375938B18}</ProjectGuid>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>VOID</RootNamespace> <RootNamespace>VOID</RootNamespace>
<AssemblyName>VOID</AssemblyName> <AssemblyName>VOID</AssemblyName>
<CodePage>65001</CodePage> <CodePage>65001</CodePage>
<UseMSBuildEngine>False</UseMSBuildEngine> <UseMSBuildEngine>False</UseMSBuildEngine>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion> <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ReleaseVersion>0.11</ReleaseVersion> <ReleaseVersion>0.11</ReleaseVersion>
<SynchReleaseVersion>false</SynchReleaseVersion> <SynchReleaseVersion>false</SynchReleaseVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_win|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG; TRACE</DefineConstants> <DefineConstants>DEBUG; TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_win|AnyCPU' ">
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" /> <Command type="AfterBuild" command="xcopy /Y ${TargetFile} ..\..\..\Games\KSP_win\GameData\VOID\Plugins\" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug_linux|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType> <DebugType>full</DebugType>
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath> <OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG; TRACE</DefineConstants> <DefineConstants>DEBUG; TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release_linux|AnyCPU' ">
<Optimize>false</Optimize> <Optimize>false</Optimize>
<OutputPath>bin\Release</OutputPath> <OutputPath>bin\Release</OutputPath>
<DefineConstants>TRACE</DefineConstants> <DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause> <ConsolePause>false</ConsolePause>
<CustomCommands> <CustomCommands>
<CustomCommands> <CustomCommands>
<Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" /> <Command type="AfterBuild" command="cp -afv ${TargetFile} /opt/games/KSP_linux/GameData/${ProjectName}/Plugins/" />
</CustomCommands> </CustomCommands>
</CustomCommands> </CustomCommands>
</PropertyGroup> </PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>
<Compile Include="IVOID_Module.cs" /> <Compile Include="IVOID_Module.cs" />
<Compile Include="VOIDFlightMaster.cs" /> <Compile Include="VOIDFlightMaster.cs" />
<Compile Include="VOID_Core.cs" /> <Compile Include="VOID_Core.cs" />
<Compile Include="VOID_Module.cs" /> <Compile Include="VOID_Module.cs" />
<Compile Include="VOID_HUD.cs" /> <Compile Include="VOID_HUD.cs" />
<Compile Include="VOID_SaveValue.cs" /> <Compile Include="VOID_SaveValue.cs" />
<Compile Include="VOID_Orbital.cs" /> <Compile Include="VOID_Orbital.cs" />
<Compile Include="VOID_SurfAtmo.cs" /> <Compile Include="VOID_SurfAtmo.cs" />
<Compile Include="VOID_VesselInfo.cs" /> <Compile Include="VOID_VesselInfo.cs" />
<Compile Include="VOID_Transfer.cs" /> <Compile Include="VOID_Transfer.cs" />
<Compile Include="VOID_CBInfoBrowser.cs" /> <Compile Include="VOID_CBInfoBrowser.cs" />
<Compile Include="VOID_Rendezvous.cs" /> <Compile Include="VOID_Rendezvous.cs" />
<Compile Include="VOID_VesselRegister.cs" /> <Compile Include="VOID_VesselRegister.cs" />
<Compile Include="VOID_DataLogger.cs" /> <Compile Include="VOID_DataLogger.cs" />
<Compile Include="VOID_EditorCore.cs" /> <Compile Include="VOID_EditorCore.cs" />
<Compile Include="VOID_EditorHUD.cs" /> <Compile Include="VOID_EditorHUD.cs" />
<Compile Include="VOID_DataValue.cs" /> <Compile Include="VOID_DataValue.cs" />
<Compile Include="VOIDEditorMaster.cs" /> <Compile Include="VOIDEditorMaster.cs" />
<Compile Include="VOID_Tools.cs" /> <Compile Include="VOID_Tools.cs" />
<Compile Include="VOID_Localization.cs" /> <Compile Include="VOID_Localization.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VOID_HUDAdvanced.cs" /> <Compile Include="VOID_HUDAdvanced.cs" />
  <Compile Include="VOID_EditorTWR.cs" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>
<Properties> <Properties>
<Policies> <Policies>
<TextStylePolicy FileWidth="120" TabsToSpaces="False" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" /> <TextStylePolicy FileWidth="120" TabsToSpaces="False" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
</Policies> </Policies>
</Properties> </Properties>
</MonoDevelop> </MonoDevelop>
</ProjectExtensions> </ProjectExtensions>
<ItemGroup> <ItemGroup>
<Reference Include="System"> <Reference Include="System">
<HintPath>..\_KSPAssemblies\System.dll</HintPath> <HintPath>..\_KSPAssemblies\System.dll</HintPath>
</Reference> </Reference>
<Reference Include="Assembly-CSharp"> <Reference Include="Assembly-CSharp">
<HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath> <HintPath>..\_KSPAssemblies\Assembly-CSharp.dll</HintPath>
</Reference> </Reference>
<Reference Include="UnityEngine"> <Reference Include="UnityEngine">
<HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath> <HintPath>..\_KSPAssemblies\UnityEngine.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj"> <ProjectReference Include="..\ToadicusTools\ToadicusTools.csproj">
<Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project> <Project>{D48A5542-6655-4149-BC27-B27DF0466F1C}</Project>
<Name>ToadicusTools</Name> <Name>ToadicusTools</Name>
</ProjectReference> </ProjectReference>
<ProjectReference Include="..\VesselSimulator\VesselSimulator.csproj"> <ProjectReference Include="..\VesselSimulator\VesselSimulator.csproj">
<Project>{30FD6C0B-D36E-462F-B0FF-F0FAC9C666CF}</Project> <Project>{30FD6C0B-D36E-462F-B0FF-F0FAC9C666CF}</Project>
<Name>VesselSimulator</Name> <Name>VesselSimulator</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
</Project> </Project>
   
file:b/VOID_EditorTWR.cs (new)
  // VOID © 2014 toadicus
  //
  // This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
  // copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
 
  using KSP;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using ToadicusTools;
  using UnityEngine;
 
  namespace VOID
  {
  public class VOID_EditorTWR : VOID_WindowModule, IVOID_EditorModule
  {
  private Dictionary<string, double> bodyGeeValues;
  private List<CelestialBody> sortedBodyList;
 
  public VOID_EditorTWR() : base()
  {
  this._Name = "IP Thrust-to-Weight Ratios";
  }
 
  public override void ModuleWindow(int _)
  {
  if (Event.current.type != EventType.Layout)
  {
  return;
  }
 
  Engineer.VesselSimulator.SimManager.RequestSimulation();
 
  GUILayout.Label(
  this._Name,
  VOID_EditorCore.Instance.LabelStyles["center_bold"],
  GUILayout.ExpandWidth(true));
 
  if (bodyGeeValues == null)
  {
  if (FlightGlobals.Bodies != null && FlightGlobals.Bodies.Count > 0)
  {
  this.bodyGeeValues = new Dictionary<string, double>();
 
  foreach (CelestialBody body in FlightGlobals.Bodies)
  {
  this.bodyGeeValues[body.name] = body.GeeASL;
  }
 
  this.sortedBodyList = new List<CelestialBody>(FlightGlobals.Bodies);
  this.sortedBodyList.Sort(new CBListComparer());
  this.sortedBodyList.Reverse();
 
  Debug.Log(string.Format("sortedBodyList: {0}", string.Join("\n\t", this.sortedBodyList.Select(b => b.bodyName).ToArray())));
  }
  else
  {
  GUILayout.BeginVertical();
  GUILayout.BeginHorizontal();
  GUILayout.Label("Unavailable.");
  GUILayout.EndHorizontal();
  GUILayout.EndVertical();
  }
  }
  else
  {
  GUILayout.BeginVertical();
 
  foreach (CelestialBody body in this.sortedBodyList)
  {
  Tools.PostDebugMessage(this, "Doing label for {0}", body.bodyName);
  GUILayout.BeginHorizontal();
 
  GUILayout.Label(body.bodyName);
  GUILayout.FlexibleSpace();
  GUILayout.Label(
  (VOID_Data.currThrustWeight.Value / this.bodyGeeValues[body.bodyName]).ToString("0.0##"),
  GUILayout.ExpandWidth(true)
  );
 
  GUILayout.EndHorizontal();
  }
 
  GUILayout.EndVertical();
  }
 
  GUI.DragWindow();
  }
  }
 
  public class CBListComparer : IComparer<CelestialBody>
  {
  public int Compare(CelestialBody bodyA, CelestialBody bodyB)
  {
  Tools.PostDebugMessage(this, "got bodyA: {0} & bodyB: {1}", bodyA, bodyB);
 
  if (bodyA == null && bodyB == null)
  {
  Tools.PostDebugMessage(this, "both bodies are null, returning 0");
  return 0;
  }
  if (bodyA == null)
  {
  Tools.PostDebugMessage(this, "bodyA is null, returning -1");
  return -1;
  }
  if (bodyB == null)
  {
  Tools.PostDebugMessage(this, "bodyB is null, returning 1");
  return 1;
  }
 
  Tools.PostDebugMessage(this, "bodies are not null, carrying on");
 
  if (object.ReferenceEquals(bodyA, bodyB))
  {
  Tools.PostDebugMessage(this, "bodies are equal, returning 0");
  return 0;
  }
 
  Tools.PostDebugMessage(this, "bodies are not equal, carrying on");
 
  if (bodyA.orbitDriver == null)
  {
  Tools.PostDebugMessage(this, "bodyA.orbit is null (bodyA is the sun, returning 1");
  return 1;
  }
  if (bodyB.orbitDriver == null)
  {
  Tools.PostDebugMessage(this, "bodyB.orbit is null (bodyB is the sun, returning -1");
  return -1;
  }
 
  Tools.PostDebugMessage(this, "orbits are not null, carrying on");
 
  if (bodyA.orbit.referenceBody == bodyB.orbit.referenceBody)
  {
  Tools.PostDebugMessage(this, "bodies share a parent, comparing SMAs");
  return -bodyA.orbit.semiMajorAxis.CompareTo(bodyB.orbit.semiMajorAxis);
  }
 
  Tools.PostDebugMessage(this, "orbits do not share a parent, carrying on");
 
  if (bodyA.hasAncestor(bodyB))
  {
  Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning -1");
  return -1;
  }
  if (bodyB.hasAncestor(bodyA))
  {
  Tools.PostDebugMessage(this, "bodyA is a moon or sub-moon of bodyB, returning 1");
  return 1;
  }
 
  Tools.PostDebugMessage(this, "bodies do not have an obvious relationship, searching for one");
 
  if (VOID_Tools.NearestRelatedParents(ref bodyA, ref bodyB))
  {
  Tools.PostDebugMessage(this, "good relation {0} and {1}, comparing", bodyA.bodyName, bodyB.bodyName);
  return this.Compare(bodyA, bodyB);
  }
 
  Tools.PostDebugMessage(this, "bad relation {0} and {1}, giving up", bodyA.bodyName, bodyB.bodyName);
 
  return 0;
  }
  }
 
  public static partial class VOID_Data
  {
  public static readonly VOID_DoubleValue nominalThrustWeight = new VOID_DoubleValue(
  "Thrust-to-Weight Ratio",
  delegate()
  {
  if (HighLogic.LoadedSceneIsEditor || currThrustWeight.Value == 0d)
  {
  return maxThrustWeight.Value;
  }
 
  return currThrustWeight.Value;
  },
  ""
  );
  }
  }
 
 
// VOID // VOID
// //
// VOID_Tools.cs // VOID_Tools.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or other // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 3. Neither the name of the copyright holder nor the names of its contributors may be used
// to endorse or promote products derived from this software without specific prior written permission. // to endorse or promote products derived from this software without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public static partial class VOID_Tools public static partial class VOID_Tools
{ {
  #region CelestialBody Utilities
  public static bool hasAncestor(this CelestialBody bodyA, CelestialBody bodyB)
  {
  if (bodyA == null || bodyB == null)
  {
  return false;
  }
   
  while (bodyA.orbitDriver != null)
  {
  if (bodyA.orbit.referenceBody == bodyB)
  {
  return true;
  }
   
  bodyA = bodyA.orbit.referenceBody;
  }
   
  return false;
  }
   
  public static bool NearestRelatedParents(ref CelestialBody bodyA, ref CelestialBody bodyB)
  {
  if (bodyA == null || bodyB == null || bodyA.orbitDriver == null || bodyB.orbitDriver == null)
  {
  throw new ArgumentException(string.Concat(
  "CelestialBody::FindRelatedParents: ",
  "Neither body may be null, and both bodies must have orbits."
  ));
  }
   
  CelestialBody a, b;
   
  a = bodyA;
   
  while (bodyA.orbitDriver != null)
  {
  b = bodyB;
   
  while (b.orbitDriver != null)
  {
  if (a.orbit.referenceBody == b.orbit.referenceBody)
  {
  bodyA = a;
  bodyB = b;
  return true;
  }
   
  b = b.orbit.referenceBody;
  }
   
  a = a.orbit.referenceBody;
  }
   
  return false;
  }
  #endregion
   
#region VESSEL_EXTENSIONS_SCIENCE #region VESSEL_EXTENSIONS_SCIENCE
public static CBAttributeMap.MapAttribute GetBiome(this Vessel vessel) public static CBAttributeMap.MapAttribute GetBiome(this Vessel vessel)
{ {
CBAttributeMap.MapAttribute mapAttribute; CBAttributeMap.MapAttribute mapAttribute;
   
try try
{ {
CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap; CBAttributeMap BiomeMap = vessel.mainBody.BiomeMap;
   
double lat = vessel.latitude * Math.PI / 180d; double lat = vessel.latitude * Math.PI / 180d;
double lon = vessel.longitude * Math.PI / 180d; double lon = vessel.longitude * Math.PI / 180d;
   
mapAttribute = BiomeMap.GetAtt(lat, lon); mapAttribute = BiomeMap.GetAtt(lat, lon);
   
/* /*
lon -= Math.PI / 2d; lon -= Math.PI / 2d;
   
if (lon < 0d) if (lon < 0d)
{ {
lon += 2d * Math.PI; lon += 2d * Math.PI;
} }
   
float v = (float)(lat / Math.PI) + 0.5f; float v = (float)(lat / Math.PI) + 0.5f;
float u = (float)(lon / (2d * Math.PI)); float u = (float)(lon / (2d * Math.PI));
   
Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v); Color pixelBilinear = BiomeMap.Map.GetPixelBilinear(u, v);
mapAttribute = BiomeMap.defaultAttribute; mapAttribute = BiomeMap.defaultAttribute;
   
if (BiomeMap.Map != null) if (BiomeMap.Map != null)
{ {
if (BiomeMap.exactSearch) if (BiomeMap.exactSearch)
{ {
for (int i = 0; i < BiomeMap.Attributes.Length; ++i) for (int i = 0; i < BiomeMap.Attributes.Length; ++i)
{ {
if (pixelBilinear == BiomeMap.Attributes[i].mapColor) if (pixelBilinear == BiomeMap.Attributes[i].mapColor)
{ {
mapAttribute = BiomeMap.Attributes[i]; mapAttribute = BiomeMap.Attributes[i];
} }
} }
} }
else else
{ {
float zero = 0; float zero = 0;
float num = 1 / zero; float num = 1 / zero;
for (int j = 0; j < BiomeMap.Attributes.Length; ++j) for (int j = 0; j < BiomeMap.Attributes.Length; ++j)
{ {
Color mapColor = BiomeMap.Attributes[j].mapColor; Color mapColor = BiomeMap.Attributes[j].mapColor;
float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude; float sqrMagnitude = ((Vector4)(mapColor - pixelBilinear)).sqrMagnitude;
if (sqrMagnitude < num) if (sqrMagnitude < num)
{ {
bool testCase = true; bool testCase = true;
if (BiomeMap.nonExactThreshold != -1) if (BiomeMap.nonExactThreshold != -1)
{ {
testCase = (sqrMagnitude < BiomeMap.nonExactThreshold); testCase = (sqrMagnitude < BiomeMap.nonExactThreshold);
} }
if (testCase) if (testCase)
{ {
mapAttribute = BiomeMap.Attributes[j]; mapAttribute = BiomeMap.Attributes[j];
num = sqrMagnitude; num = sqrMagnitude;
} }
} }
} }
} }
} }
*/ */
} }
catch (NullReferenceException) catch (NullReferenceException)
{ {
mapAttribute = new CBAttributeMap.MapAttribute(); mapAttribute = new CBAttributeMap.MapAttribute();
mapAttribute.name = "N/A"; mapAttribute.name = "N/A";
} }
   
return mapAttribute; return mapAttribute;
} }
   
public static ExperimentSituations GetExperimentSituation(this Vessel vessel) public static ExperimentSituations GetExperimentSituation(this Vessel vessel)
{ {
if (vessel == null) if (vessel == null)
{ {
return ExperimentSituations.SrfSplashed; return ExperimentSituations.SrfSplashed;
} }
   
Vessel.Situations situation = vessel.situation; Vessel.Situations situation = vessel.situation;
   
switch (situation) switch (situation)
{ {
case Vessel.Situations.PRELAUNCH: case Vessel.Situations.PRELAUNCH:
case Vessel.Situations.LANDED: case Vessel.Situations.LANDED:
return ExperimentSituations.SrfLanded; return ExperimentSituations.SrfLanded;
case Vessel.Situations.SPLASHED: case Vessel.Situations.SPLASHED:
return ExperimentSituations.SrfSplashed; return ExperimentSituations.SrfSplashed;
case Vessel.Situations.FLYING: case Vessel.Situations.FLYING:
if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold) if (vessel.altitude < (double)vessel.mainBody.scienceValues.flyingAltitudeThreshold)
{ {
return ExperimentSituations.FlyingLow; return ExperimentSituations.FlyingLow;
} }
else else
{ {
return ExperimentSituations.FlyingHigh; return ExperimentSituations.FlyingHigh;
} }
} }
   
if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold) if (vessel.altitude < (double)vessel.mainBody.scienceValues.spaceAltitudeThreshold)
{ {
return ExperimentSituations.InSpaceLow; return ExperimentSituations.InSpaceLow;
} }
else else
{ {
return ExperimentSituations.InSpaceHigh; return ExperimentSituations.InSpaceHigh;
} }
} }
   
public static string HumanString(this ExperimentSituations situation) public static string HumanString(this ExperimentSituations situation)
{ {
switch (situation) switch (situation)
{ {
case ExperimentSituations.FlyingHigh: case ExperimentSituations.FlyingHigh:
return "Upper Atmosphere"; return "Upper Atmosphere";
case ExperimentSituations.FlyingLow: case ExperimentSituations.FlyingLow:
return "Flying"; return "Flying";
case ExperimentSituations.SrfLanded: case ExperimentSituations.SrfLanded:
return "Surface"; return "Surface";
case ExperimentSituations.InSpaceLow: case ExperimentSituations.InSpaceLow:
return "Near in Space"; return "Near in Space";
case ExperimentSituations.InSpaceHigh: case ExperimentSituations.InSpaceHigh:
return "High in Space"; return "High in Space";
case ExperimentSituations.SrfSplashed: case ExperimentSituations.SrfSplashed:
return "Splashed Down"; return "Splashed Down";
default: default:
return "Unknown"; return "Unknown";
} }
} }
#endregion #endregion
   
#region VESSEL_EXTENSIONS_LAT_LONG #region VESSEL_EXTENSIONS_LAT_LONG
public static string GetLongitudeString(this Vessel vessel, string format = "F4") public static string GetLongitudeString(this Vessel vessel, string format = "F4")
{ {
string dir_long = "W"; string dir_long = "W";
double v_long = vessel.longitude; double v_long = vessel.longitude;
   
v_long = FixDegreeDomain(v_long); v_long = FixDegreeDomain(v_long);
   
if (v_long < -180d) if (v_long < -180d)
{ {
v_long += 360d; v_long += 360d;
} }
if (v_long >= 180) if (v_long >= 180)
{ {
v_long -= 360d; v_long -= 360d;
} }
   
if (v_long > 0) if (v_long > 0)
dir_long = "E"; dir_long = "E";
   
return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long); return string.Format("{0}° {1}", Math.Abs(v_long).ToString(format), dir_long);
} }
   
public static string GetLatitudeString(this Vessel vessel, string format = "F4") public static string GetLatitudeString(this Vessel vessel, string format = "F4")
{ {
string dir_lat = "S"; string dir_lat = "S";
double v_lat = vessel.latitude; double v_lat = vessel.latitude;
if (v_lat > 0) if (v_lat > 0)
dir_lat = "N"; dir_lat = "N";
   
return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat); return string.Format("{0}° {1}", Math.Abs(v_lat).ToString(format), dir_lat);
} }
#endregion #endregion
   
#region VESSEL_EXTENSIONS_GENERAL #region VESSEL_EXTENSIONS_GENERAL
public static double TrueAltitude(Vessel vessel) public static double TrueAltitude(Vessel vessel)
{ {
double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude; double trueAltitude = vessel.orbit.altitude - vessel.terrainAltitude;
   
// HACK: This assumes that on worlds with oceans, all water is fixed at 0 m, // HACK: This assumes that on worlds with oceans, all water is fixed at 0 m,
// and water covers the whole surface at 0 m. // and water covers the whole surface at 0 m.
if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean) if (vessel.terrainAltitude < 0 && vessel.mainBody.ocean)
{ {
trueAltitude = vessel.orbit.altitude; trueAltitude = vessel.orbit.altitude;
} }
   
return trueAltitude; return trueAltitude;
} }
   
public static double Radius(this Vessel vessel) public static double Radius(this Vessel vessel)
{ {
double radius; double radius;
   
radius = vessel.altitude; radius = vessel.altitude;
   
if (vessel.mainBody != null) if (vessel.mainBody != null)
{ {
radius += vessel.mainBody.Radius; radius += vessel.mainBody.Radius;
} }
   
return radius; return radius;
} }
#endregion #endregion
   
#region GEOMETRY_UTILS #region GEOMETRY_UTILS
public static double FixAngleDomain(double Angle, bool Degrees = false) public static double FixAngleDomain(double Angle, bool Degrees = false)
{ {
double Extent = 2d * Math.PI; double Extent = 2d * Math.PI;
if (Degrees) if (Degrees)
{ {
Extent = 360d; Extent = 360d;
} }
   
Angle = Angle % (Extent); Angle = Angle % (Extent);
if (Angle < 0d) if (Angle < 0d)
{ {
Angle += Extent; Angle += Extent;
} }
   
return Angle; return Angle;
} }
   
public static double FixDegreeDomain(double Angle) public static double FixDegreeDomain(double Angle)
{ {
return FixAngleDomain(Angle, true); return FixAngleDomain(Angle, true);
} }
#endregion #endregion
   
private static Dictionary<int, GUI.WindowFunction> functionCache; private static Dictionary<int, GUI.WindowFunction> functionCache;
public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func) public static UnityEngine.GUI.WindowFunction GetWindowHandler(Action<int> func)
{ {
if (functionCache == null) if (functionCache == null)
{ {
functionCache = new Dictionary<int, GUI.WindowFunction>(); functionCache = new Dictionary<int, GUI.WindowFunction>();
} }
   
int hashCode = func.GetHashCode(); int hashCode = func.GetHashCode();
   
if (!functionCache.ContainsKey(hashCode)) if (!functionCache.ContainsKey(hashCode))
{ {
functionCache[hashCode] = delegate (int id) functionCache[hashCode] = delegate (int id)
{ {
try try
{ {
func(id); func(id);
} }
catch (ArgumentException ex) catch (ArgumentException ex)
{ {
Debug.LogWarning( Debug.LogWarning(
string.Format("[{0}]: ArgumentException caught during window call.", func.Target.GetType().Name) string.Format("[{0}]: ArgumentException caught during window call.", func.Target.GetType().Name)
); );
#if DEBUG #if DEBUG
Debug.LogException(ex); Debug.LogException(ex);
#endif #endif
} }
}; };
} }
   
return functionCache[hashCode]; return functionCache[hashCode];
} }
   
/// <summary> /// <summary>
/// Converts the interval given in seconds to a human-friendly /// Converts the interval given in seconds to a human-friendly
/// time period in [years], [days], hours, minutes, and seconds. /// time period in [years], [days], hours, minutes, and seconds.
/// ///
/// Uses sidereal days, since "6 hours per day" is the Kerbal standard. /// Uses sidereal days, since "6 hours per day" is the Kerbal standard.
/// </summary> /// </summary>
/// <returns>Human readable interval</returns> /// <returns>Human readable interval</returns>
/// <param name="seconds"></param> /// <param name="seconds"></param>
public static string ConvertInterval(double seconds) public static string ConvertInterval(double seconds)
{ {
double SecondsPerMinute = 60d; double SecondsPerMinute = 60d;
double SecondsPerHour = 3600d; double SecondsPerHour = 3600d;
double SecondsPerDay; double SecondsPerDay;
double SecondsPerYear; double SecondsPerYear;
   
if (GameSettings.KERBIN_TIME) if (GameSettings.KERBIN_TIME)
{ {
SecondsPerDay = 21600d; SecondsPerDay = 21600d;
SecondsPerYear = 9203545d; SecondsPerYear = 9203545d;
} }
else else
{ {
SecondsPerDay = 86164.1d; SecondsPerDay = 86164.1d;
SecondsPerYear = 31558149d; SecondsPerYear = 31558149d;
} }
   
int years; int years;
int days; int days;
int hours; int hours;
int minutes; int minutes;
   
years = (int)(seconds / SecondsPerYear); years = (int)(seconds / SecondsPerYear);
   
seconds %= SecondsPerYear; seconds %= SecondsPerYear;
   
days = (int)(seconds / SecondsPerDay); days = (int)(seconds / SecondsPerDay);
   
seconds %= SecondsPerDay; seconds %= SecondsPerDay;
   
hours = (int)(seconds / SecondsPerHour); hours = (int)(seconds / SecondsPerHour);
   
seconds %= SecondsPerHour; seconds %= SecondsPerHour;
   
minutes = (int)(seconds / SecondsPerMinute); minutes = (int)(seconds / SecondsPerMinute);
   
seconds %= SecondsPerMinute; seconds %= SecondsPerMinute;
   
string format_1 = string.Intern("{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s"); string format_1 = string.Intern("{0:D1}y {1:D1}d {2:D2}h {3:D2}m {4:00.0}s");
string format_2 = string.Intern("{0:D1}d {1:D2}h {2:D2}m {3:00.0}s"); string format_2 = string.Intern("{0:D1}d {1:D2}h {2:D2}m {3:00.0}s");
string format_3 = string.Intern("{0:D2}h {1:D2}m {2:00.0}s"); string format_3 = string.Intern("{0:D2}h {1:D2}m {2:00.0}s");
string format_4 = string.Intern("{0:D2}m {1:00.0}s"); string format_4 = string.Intern("{0:D2}m {1:00.0}s");
string format_5 = string.Intern("{0:00.0}s"); string format_5 = string.Intern("{0:00.0}s");
   
if (years > 0) if (years > 0)
{ {
return string.Format(format_1, years, days, hours, minutes, seconds); return string.Format(format_1, years, days, hours, minutes, seconds);
} }
else if (days > 0) else if (days > 0)
{ {
return string.Format(format_2, days, hours, minutes, seconds); return string.Format(format_2, days, hours, minutes, seconds);
} }
else if (hours > 0) else if (hours > 0)
{ {
return string.Format(format_3, hours, minutes, seconds); return string.Format(format_3, hours, minutes, seconds);
} }
else if (minutes > 0) else if (minutes > 0)
{ {
return string.Format(format_4, minutes, seconds); return string.Format(format_4, minutes, seconds);
} }
else else
{ {
return string.Format(format_5, seconds); return string.Format(format_5, seconds);
} }
} }
   
public static string UppercaseFirst(string s) public static string UppercaseFirst(string s)
{ {
if (string.IsNullOrEmpty(s)) if (string.IsNullOrEmpty(s))
{ {
return string.Empty; return string.Empty;
} }
char[] a = s.ToCharArray(); char[] a = s.ToCharArray();
a[0] = char.ToUpper(a[0]); a[0] = char.ToUpper(a[0]);
return new string(a); return new string(a);
} }
   
//transfer angles //transfer angles
public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param) public static double Nivvy_CalcTransferPhaseAngle(double r_current, double r_target, double grav_param)
{ {
r_target /= 1000; r_target /= 1000;
r_current /= 1000; r_current /= 1000;
grav_param /= 1000000000; grav_param /= 1000000000;
   
double midpoint = (r_target + r_current) / 2; double midpoint = (r_target + r_current) / 2;
   
double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param); double T_target = (2 * Math.PI) * Math.Sqrt((r_target * r_target * r_target) / grav_param);
double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param); double T_transfer = (2 * Math.PI) * Math.Sqrt((midpoint * midpoint * midpoint) / grav_param);
return 360 * (0.5 - (T_transfer / (2 * T_target))); return 360 * (0.5 - (T_transfer / (2 * T_target)));
} }
   
public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2) public static double Younata_DeltaVToGetToOtherBody(double mu, double r1, double r2)
{ {
/* /*
def deltaVToGetToOtherBody(mu, r1, r2): def deltaVToGetToOtherBody(mu, r1, r2):
# mu = gravity param of common orbiting body of r1 and r2 # mu = gravity param of common orbiting body of r1 and r2
# (e.g. for mun to minmus, mu is kerbin's gravity param # (e.g. for mun to minmus, mu is kerbin's gravity param
# r1 = initial body's orbit radius # r1 = initial body's orbit radius
# r2 = target body's orbit radius # r2 = target body's orbit radius
# return value is km/s # return value is km/s
sur1 = math.sqrt(mu / r1) sur1 = math.sqrt(mu / r1)
sr1r2 = math.sqrt(float(2*r2)/float(r1+r2)) sr1r2 = math.sqrt(float(2*r2)/float(r1+r2))
mult = sr1r2 - 1 mult = sr1r2 - 1
return sur1 * mult return sur1 * mult
*/ */
double sur1, sr1r2, mult; double sur1, sr1r2, mult;
sur1 = Math.Sqrt(mu / r1); sur1 = Math.Sqrt(mu / r1);
sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2)); sr1r2 = Math.Sqrt((2 * r2) / (r1 + r2));
mult = sr1r2 - 1; mult = sr1r2 - 1;
return sur1 * mult; return sur1 * mult;
} }
   
public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v) public static double Younata_DeltaVToExitSOI(double mu, double r1, double r2, double v)
{ {
/* /*
def deltaVToExitSOI(mu, r1, r2, v): def deltaVToExitSOI(mu, r1, r2, v):
# mu = gravity param of current body # mu = gravity param of current body
# r1 = current orbit radius # r1 = current orbit radius
# r2 = SOI radius # r2 = SOI radius
# v = SOI exit velocity # v = SOI exit velocity
foo = r2 * (v**2) - 2 * mu foo = r2 * (v**2) - 2 * mu
bar = r1 * foo + (2 * r2 * mu) bar = r1 * foo + (2 * r2 * mu)
r = r1*r2 r = r1*r2
return math.sqrt(bar / r) return math.sqrt(bar / r)
*/ */
double foo = r2 * (v * v) - 2 * mu; double foo = r2 * (v * v) - 2 * mu;
double bar = r1 * foo + (2 * r2 * mu); double bar = r1 * foo + (2 * r2 * mu);
double r = r1 * r2; double r = r1 * r2;
return Math.Sqrt(bar / r); return Math.Sqrt(bar / r);
} }
   
public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu) public static double Younata_TransferBurnPoint(double r, double v, double angle, double mu)
{ {
/* /*
def transferBurnPoint(r, v, angle, mu): def transferBurnPoint(r, v, angle, mu):
# r = parking orbit radius # r = parking orbit radius
# v = ejection velocity # v = ejection velocity
# angle = phase angle (from function phaseAngle()) # angle = phase angle (from function phaseAngle())
# mu = gravity param of current body. # mu = gravity param of current body.
epsilon = ((v**2)/2) - (mu / r) epsilon = ((v**2)/2) - (mu / r)
h = r * v * math.sin(angle) h = r * v * math.sin(angle)
e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2))) e = math.sqrt(1 + ((2 * epsilon * h**2)/(mu**2)))
theta = math.acos(1.0 / e) theta = math.acos(1.0 / e)
degrees = theta * (180.0 / math.pi) degrees = theta * (180.0 / math.pi)
return 180 - degrees return 180 - degrees
*/ */
double epsilon, h, ee, theta, degrees; double epsilon, h, ee, theta, degrees;
epsilon = ((v * v) / 2) - (mu / r); epsilon = ((v * v) / 2) - (mu / r);
h = r * v * Math.Sin(angle); h = r * v * Math.Sin(angle);
ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu))); ee = Math.Sqrt(1 + ((2 * epsilon * (h * h)) / (mu * mu)));
theta = Math.Acos(1.0 / ee); theta = Math.Acos(1.0 / ee);
degrees = theta * (180.0 / Math.PI); degrees = theta * (180.0 / Math.PI);
return 180 - degrees; return 180 - degrees;
// returns the ejection angle // returns the ejection angle
} }
   
public static double Adammada_CurrrentPhaseAngle( public static double Adammada_CurrrentPhaseAngle(
double body_LAN, double body_LAN,
double body_orbitPct, double body_orbitPct,
double origin_LAN, double origin_LAN,
double origin_orbitPct double origin_orbitPct
) )
{ {
double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct); double angle = (body_LAN / 360 + body_orbitPct) - (origin_LAN / 360 + origin_orbitPct);
if (angle > 1) if (angle > 1)
angle = angle - 1; angle = angle - 1;
if (angle < 0) if (angle < 0)
angle = angle + 1; angle = angle + 1;
if (angle > 0.5) if (angle > 0.5)
angle = angle - 1; angle = angle - 1;
angle = angle * 360; angle = angle * 360;
return angle; return angle;
} }
   
public static double Adammada_CurrentEjectionAngle( public static double Adammada_CurrentEjectionAngle(
double vessel_long, double vessel_long,
double origin_rotAngle, double origin_rotAngle,
double origin_LAN, double origin_LAN,
double origin_orbitPct double origin_orbitPct
) )
{ {
//double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360); //double eangle = ((FlightGlobals.ActiveVOID.vessel.longitude + orbiting.rotationAngle) - (orbiting.orbit.LAN / 360 + orbiting.orbit.orbitPercent) * 360);
double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360); double eangle = ((vessel_long + origin_rotAngle) - (origin_LAN / 360 + origin_orbitPct) * 360);
   
while (eangle < 0) while (eangle < 0)
eangle = eangle + 360; eangle = eangle + 360;
while (eangle > 360) while (eangle > 360)
eangle = eangle - 360; eangle = eangle - 360;
if (eangle < 270) if (eangle < 270)
eangle = 90 - eangle; eangle = 90 - eangle;
else else
eangle = 450 - eangle; eangle = 450 - eangle;
return eangle; return eangle;
} }
   
public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body public static double mrenigma03_calcphase(Vessel vessel, CelestialBody target) //calculates phase angle between the current body and target body
{ {
Vector3d vecthis = new Vector3d(); Vector3d vecthis = new Vector3d();
Vector3d vectarget = new Vector3d(); Vector3d vectarget = new Vector3d();
vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vectarget = target.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
   
if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun")) if ((vessel.mainBody.name == "Sun") || (vessel.mainBody.referenceBody.referenceBody.name == "Sun"))
{ {
vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
else else
{ {
vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime()); vecthis = vessel.mainBody.orbit.getRelativePositionAtUT(Planetarium.GetUniversalTime());
} }
   
vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis); vecthis = Vector3d.Project(new Vector3d(vecthis.x, 0, vecthis.z), vecthis);
vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget); vectarget = Vector3d.Project(new Vector3d(vectarget.x, 0, vectarget.z), vectarget);
   
Vector3d prograde = new Vector3d(); Vector3d prograde = new Vector3d();
prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis; prograde = Quaternion.AngleAxis(90, Vector3d.forward) * vecthis;
   
double phase = Vector3d.Angle(vecthis, vectarget); double phase = Vector3d.Angle(vecthis, vectarget);
   
if (Vector3d.Angle(prograde, vectarget) > 90) if (Vector3d.Angle(prograde, vectarget) > 90)
phase = 360 - phase; phase = 360 - phase;
   
return (phase + 360) % 360; return (phase + 360) % 360;
} }
   
public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase) public static double adjustCurrPhaseAngle(double transfer_angle, double curr_phase)
{ {
if (transfer_angle < 0) if (transfer_angle < 0)
{ {
if (curr_phase > 0) if (curr_phase > 0)
return (-1 * (360 - curr_phase)); return (-1 * (360 - curr_phase));
else if (curr_phase < 0) else if (curr_phase < 0)
return curr_phase; return curr_phase;
} }
else if (transfer_angle > 0) else if (transfer_angle > 0)
{ {
if (curr_phase > 0) if (curr_phase > 0)
return curr_phase; return curr_phase;
else if (curr_phase < 0) else if (curr_phase < 0)
return (360 + curr_phase); return (360 + curr_phase);
} }
return curr_phase; return curr_phase;
} }
   
public static double adjust_current_ejection_angle(double curr_ejection) public static double adjust_current_ejection_angle(double curr_ejection)
{ {
//curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180 //curr_ejection WILL need to be adjusted once for all transfers as it returns values ranging -180 to 180
// need 0-360 instead // need 0-360 instead
// //
// ie i have -17 in the screenshot // ie i have -17 in the screenshot
// need it to show 343 // need it to show 343
// //
// do this // do this
// //
// if < 0, add curr to 360 // 360 + (-17) = 343 // if < 0, add curr to 360 // 360 + (-17) = 343
// else its good as it is // else its good as it is
   
if (curr_ejection < 0) if (curr_ejection < 0)
return 360 + curr_ejection; return 360 + curr_ejection;
else else
return curr_ejection; return curr_ejection;
   
} }
   
public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase) public static double adjust_transfer_ejection_angle(double trans_ejection, double trans_phase)
{ {
// if transfer_phase_angle < 0 its a lower transfer // if transfer_phase_angle < 0 its a lower transfer
//180 + curr_ejection //180 + curr_ejection
// else if transfer_phase_angle > 0 its good as it is // else if transfer_phase_angle > 0 its good as it is
   
if (trans_phase < 0) if (trans_phase < 0)
return 180 + trans_ejection; return 180 + trans_ejection;
else else
return trans_ejection; return trans_ejection;
   
} }
   
public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel) public static void display_transfer_angles_SUN2PLANET(CelestialBody body, Vessel vessel)
{ {
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle( VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.orbit.semiMajorAxis, vessel.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.gravParameter vessel.mainBody.gravParameter
).ToString("F3") + "°", ).ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label( GUILayout.Label(
(VOID_Tools.Younata_DeltaVToGetToOtherBody( (VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
) * 1000).ToString("F2") + "m/s", ) * 1000).ToString("F2") + "m/s",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2PLANET(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.referenceBody.gravParameter / 1000000000),
(vessel.mainBody.orbit.semiMajorAxis / 1000), (vessel.mainBody.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(vessel.mainBody.sphereOfInfluence / 1000), (vessel.mainBody.sphereOfInfluence / 1000),
Math.Abs(dv1) Math.Abs(dv1)
); );
   
double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
dv2, dv2,
(Math.PI / 2.0), (Math.PI / 2.0),
(vessel.mainBody.gravParameter / 1000000000) (vessel.mainBody.gravParameter / 1000000000)
); );
double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
FlightGlobals.ActiveVessel.longitude, FlightGlobals.ActiveVessel.longitude,
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.mainBody.orbit.semiMajorAxis, vessel.mainBody.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.referenceBody.gravParameter vessel.mainBody.referenceBody.gravParameter
) % 360; ) % 360;
double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
body.orbit.LAN, body.orbit.LAN,
body.orbit.orbitPercent, body.orbit.orbitPercent,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle);
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_PLANET2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.orbit.semiMajorAxis, vessel.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.gravParameter vessel.mainBody.gravParameter
); );
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", VOID_Tools.mrenigma03_calcphase(vessel, body).ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv1 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel) public static void display_transfer_angles_MOON2MOON(CelestialBody body, Vessel vessel)
{ {
double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody( double dv1 = VOID_Tools.Younata_DeltaVToGetToOtherBody(
(vessel.mainBody.referenceBody.gravParameter / 1000000000), (vessel.mainBody.referenceBody.gravParameter / 1000000000),
(vessel.mainBody.orbit.semiMajorAxis / 1000), (vessel.mainBody.orbit.semiMajorAxis / 1000),
(body.orbit.semiMajorAxis / 1000) (body.orbit.semiMajorAxis / 1000)
); );
double dv2 = VOID_Tools.Younata_DeltaVToExitSOI( double dv2 = VOID_Tools.Younata_DeltaVToExitSOI(
(vessel.mainBody.gravParameter / 1000000000), (vessel.mainBody.gravParameter / 1000000000),
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
(vessel.mainBody.sphereOfInfluence / 1000), (vessel.mainBody.sphereOfInfluence / 1000),
Math.Abs(dv1) Math.Abs(dv1)
); );
double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint( double trans_ejection_angle = VOID_Tools.Younata_TransferBurnPoint(
(vessel.orbit.semiMajorAxis / 1000), (vessel.orbit.semiMajorAxis / 1000),
dv2, dv2,
(Math.PI / 2.0), (Math.PI / 2.0),
(vessel.mainBody.gravParameter / 1000000000) (vessel.mainBody.gravParameter / 1000000000)
); );
   
double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle( double curr_phase_angle = VOID_Tools.Adammada_CurrrentPhaseAngle(
body.orbit.LAN, body.orbit.LAN,
body.orbit.orbitPercent, body.orbit.orbitPercent,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle( double curr_ejection_angle = VOID_Tools.Adammada_CurrentEjectionAngle(
FlightGlobals.ActiveVessel.longitude, FlightGlobals.ActiveVessel.longitude,
FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle, FlightGlobals.ActiveVessel.orbit.referenceBody.rotationAngle,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN, FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.LAN,
FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent FlightGlobals.ActiveVessel.orbit.referenceBody.orbit.orbitPercent
); );
   
double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle( double trans_phase_angle = VOID_Tools.Nivvy_CalcTransferPhaseAngle(
vessel.mainBody.orbit.semiMajorAxis, vessel.mainBody.orbit.semiMajorAxis,
body.orbit.semiMajorAxis, body.orbit.semiMajorAxis,
vessel.mainBody.referenceBody.gravParameter vessel.mainBody.referenceBody.gravParameter
) % 360; ) % 360;
   
double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle); double adj_phase_angle = VOID_Tools.adjustCurrPhaseAngle(trans_phase_angle, curr_phase_angle);
//double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle); //double adj_ejection_angle = adjustCurrEjectionAngle(trans_phase_angle, curr_ejection_angle);
   
//new stuff //new stuff
// //
double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle); double adj_trans_ejection_angle = VOID_Tools.adjust_transfer_ejection_angle(trans_ejection_angle, trans_phase_angle);
double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle); double adj_curr_ejection_angle = VOID_Tools.adjust_current_ejection_angle(curr_ejection_angle);
// //
// //
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Phase angle (curr/trans):"); GUILayout.Label("Phase angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°", adj_phase_angle.ToString("F3") + "° / " + trans_phase_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Ejection angle (curr/trans):"); GUILayout.Label("Ejection angle (curr/trans):");
GUILayout.Label( GUILayout.Label(
adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°", adj_curr_ejection_angle.ToString("F3") + "° / " + adj_trans_ejection_angle.ToString("F3") + "°",
GUILayout.ExpandWidth(false) GUILayout.ExpandWidth(false)
); );
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
   
GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true)); GUILayout.BeginHorizontal(GUILayout.ExpandWidth(true));
GUILayout.Label("Transfer velocity:"); GUILayout.Label("Transfer velocity:");
GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false)); GUILayout.Label((dv2 * 1000).ToString("F2") + "m/s", GUILayout.ExpandWidth(false));
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
   
public static string get_heading_text(double heading) public static string get_heading_text(double heading)
{ {
if (heading > 348.75 || heading <= 11.25) if (heading > 348.75 || heading <= 11.25)
return "N"; return "N";
else if (heading > 11.25 && heading <= 33.75) else if (heading > 11.25 && heading <= 33.75)
return "NNE"; return "NNE";
else if (heading > 33.75 && heading <= 56.25) else if (heading > 33.75 && heading <= 56.25)
return "NE"; return "NE";
else if (heading > 56.25 && heading <= 78.75) else if (heading > 56.25 && heading <= 78.75)
return "ENE"; return "ENE";
else if (heading > 78.75 && heading <= 101.25) else if (heading > 78.75 && heading <= 101.25)
return "E"; return "E";
else if (heading > 101.25 && heading <= 123.75) else if (heading > 101.25 && heading <= 123.75)
return "ESE"; return "ESE";
else if (heading > 123.75 && heading <= 146.25) else if (heading > 123.75 && heading <= 146.25)
return "SE"; return "SE";
else if (heading > 146.25 && heading <= 168.75) else if (heading > 146.25 && heading <= 168.75)
return "SSE"; return "SSE";
else if (heading > 168.75 && heading <= 191.25) else if (heading > 168.75 && heading <= 191.25)
return "S"; return "S";
else if (heading > 191.25 && heading <= 213.75) else if (heading > 191.25 && heading <= 213.75)
return "SSW"; return "SSW";
else if (heading > 213.75 && heading <= 236.25) else if (heading > 213.75 && heading <= 236.25)
return "SW"; return "SW";
else if (heading > 236.25 && heading <= 258.75) else if (heading > 236.25 && heading <= 258.75)
return "WSW"; return "WSW";
else if (heading > 258.75 && heading <= 281.25) else if (heading > 258.75 && heading <= 281.25)
return "W"; return "W";
else if (heading > 281.25 && heading <= 303.75) else if (heading > 281.25 && heading <= 303.75)
return "WNW"; return "WNW";
else if (heading > 303.75 && heading <= 326.25) else if (heading > 303.75 && heading <= 326.25)
return "NW"; return "NW";
else if (heading > 326.25 && heading <= 348.75) else if (heading > 326.25 && heading <= 348.75)
return "NNW"; return "NNW";
else else
return ""; return "";
} }
} }
} }
   
   
// VOID // VOID
// //
// VOID_VesselInfo.cs // VOID_VesselInfo.cs
// //
// Copyright © 2014, toadicus // Copyright © 2014, toadicus
// All rights reserved. // All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, // Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met: // are permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, // 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. // this list of conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, // 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation and/or other // this list of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution. // materials provided with the distribution.
// //
// 3. Neither the name of the copyright holder nor the names of its contributors may be used // 3. Neither the name of the copyright holder nor the names of its contributors may be used
// to endorse or promote products derived from this software without specific prior written permission. // to endorse or promote products derived from this software without specific prior written permission.
// //
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   
using Engineer.VesselSimulator; using Engineer.VesselSimulator;
using Engineer.Extensions; using Engineer.Extensions;
using KSP; using KSP;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using ToadicusTools; using ToadicusTools;
using UnityEngine; using UnityEngine;
   
namespace VOID namespace VOID
{ {
public class VOID_VesselInfo : VOID_WindowModule public class VOID_VesselInfo : VOID_WindowModule
{ {
public VOID_VesselInfo() : base() public VOID_VesselInfo() : base()
{ {
this._Name = "Vessel Information"; this._Name = "Vessel Information";
   
this.WindowPos.x = Screen.width - 260; this.WindowPos.x = Screen.width - 260;
this.WindowPos.y = 450; this.WindowPos.y = 450;
} }
   
public override void ModuleWindow(int _) public override void ModuleWindow(int _)
{ {
if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate)) if ((TimeWarp.WarpMode == TimeWarp.Modes.LOW) || (TimeWarp.CurrentRate <= TimeWarp.MaxPhysicsRate))
{ {
SimManager.RequestSimulation(); SimManager.RequestSimulation();
} }
   
GUILayout.BeginVertical(); GUILayout.BeginVertical();
   
GUILayout.Label( GUILayout.Label(
vessel.vesselName, vessel.vesselName,
VOID_Core.Instance.LabelStyles["center_bold"], VOID_Core.Instance.LabelStyles["center_bold"],
GUILayout.ExpandWidth(true)); GUILayout.ExpandWidth(true));
   
VOID_Data.geeForce.DoGUIHorizontal ("F2"); VOID_Data.geeForce.DoGUIHorizontal ("F2");
   
VOID_Data.partCount.DoGUIHorizontal (); VOID_Data.partCount.DoGUIHorizontal ();
   
VOID_Data.totalMass.DoGUIHorizontal ("F3"); VOID_Data.totalMass.DoGUIHorizontal ("F3");
   
VOID_Data.resourceMass.DoGUIHorizontal ("F3"); VOID_Data.comboResourceMass.DoGUIHorizontal ();
   
VOID_Data.stageDeltaV.DoGUIHorizontal (3, false); VOID_Data.stageDeltaV.DoGUIHorizontal (3, false);
   
VOID_Data.totalDeltaV.DoGUIHorizontal (3, false); VOID_Data.totalDeltaV.DoGUIHorizontal (3, false);
   
VOID_Data.mainThrottle.DoGUIHorizontal ("F0"); VOID_Data.mainThrottle.DoGUIHorizontal ("F0");
   
VOID_Data.currmaxThrust.DoGUIHorizontal (); VOID_Data.currmaxThrust.DoGUIHorizontal ();
   
VOID_Data.currmaxThrustWeight.DoGUIHorizontal (); VOID_Data.currmaxThrustWeight.DoGUIHorizontal ();
   
VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2"); VOID_Data.surfaceThrustWeight.DoGUIHorizontal ("F2");
   
VOID_Data.intakeAirStatus.DoGUIHorizontal(); VOID_Data.intakeAirStatus.DoGUIHorizontal();
   
GUILayout.EndVertical(); GUILayout.EndVertical();
   
GUI.DragWindow(); GUI.DragWindow();
} }
} }
   
public static partial class VOID_Data public static partial class VOID_Data
{ {
public static readonly VOID_DoubleValue geeForce = new VOID_DoubleValue( public static readonly VOID_DoubleValue geeForce = new VOID_DoubleValue(
"G-force", "G-force",
new Func<double>(() => VOID_Core.Instance.vessel.geeForce), new Func<double>(() => VOID_Core.Instance.vessel.geeForce),
"gees" "gees"
); );
   
public static readonly VOID_IntValue partCount = new VOID_IntValue( public static readonly VOID_IntValue partCount = new VOID_IntValue(
"Parts", "Parts",
new Func<int>(() => VOID_Core.Instance.vessel.Parts.Count), new Func<int>(() => VOID_Core.Instance.vessel.Parts.Count),
"" ""
); );
   
public static readonly VOID_DoubleValue totalMass = new VOID_DoubleValue( public static readonly VOID_DoubleValue totalMass = new VOID_DoubleValue(
"Total Mass", "Total Mass",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return SimManager.LastStage.totalMass; return SimManager.LastStage.totalMass;
}, },
"tons" "tons"
); );
   
public static readonly VOID_DoubleValue resourceMass = new VOID_DoubleValue( public static readonly VOID_DoubleValue resourceMass = new VOID_DoubleValue(
"Resource Mass", "Resource Mass",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return SimManager.LastStage.totalMass - SimManager.LastStage.totalBaseMass; return SimManager.LastStage.totalMass - SimManager.LastStage.totalBaseMass;
}, },
"tons" "tons"
  );
   
  public static readonly VOID_DoubleValue stageResourceMass = new VOID_DoubleValue(
  "Resource Mass (Current Stage)",
  delegate()
  {
  if (SimManager.LastStage == null)
  {
  return double.NaN;
  }
   
  return SimManager.LastStage.mass - SimManager.LastStage.baseMass;
  },
  "tons"
  );
   
  public static readonly VOID_StrValue comboResourceMass = new VOID_StrValue(
  "Resource Mass (curr / total)",
  delegate()
  {
  return string.Format("{0} / {1}", stageResourceMass.ValueUnitString(), resourceMass.ValueUnitString());
  }
); );
   
public static readonly VOID_DoubleValue stageDeltaV = new VOID_DoubleValue( public static readonly VOID_DoubleValue stageDeltaV = new VOID_DoubleValue(
"DeltaV (Current Stage)", "DeltaV (Current Stage)",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return double.NaN; return double.NaN;
return SimManager.LastStage.deltaV; return SimManager.LastStage.deltaV;
}, },
"m/s" "m/s"
); );
   
public static readonly VOID_DoubleValue totalDeltaV = new VOID_DoubleValue( public static readonly VOID_DoubleValue totalDeltaV = new VOID_DoubleValue(
"DeltaV (Total)", "DeltaV (Total)",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return double.NaN; return double.NaN;
return SimManager.LastStage.totalDeltaV; return SimManager.LastStage.totalDeltaV;
}, },
"m/s" "m/s"
); );
   
public static readonly VOID_FloatValue mainThrottle = new VOID_FloatValue( public static readonly VOID_FloatValue mainThrottle = new VOID_FloatValue(
"Throttle", "Throttle",
new Func<float>(() => VOID_Core.Instance.vessel.ctrlState.mainThrottle * 100f), new Func<float>(() => VOID_Core.Instance.vessel.ctrlState.mainThrottle * 100f),
"%" "%"
); );
   
public static readonly VOID_StrValue currmaxThrust = new VOID_StrValue( public static readonly VOID_StrValue currmaxThrust = new VOID_StrValue(
"Thrust (curr/max)", "Thrust (curr/max)",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return "N/A"; return "N/A";
   
double currThrust = SimManager.LastStage.actualThrust; double currThrust = SimManager.LastStage.actualThrust;
double maxThrust = SimManager.LastStage.thrust; double maxThrust = SimManager.LastStage.thrust;
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
currThrust.ToString("F1"), currThrust.ToString("F1"),
maxThrust.ToString("F1") maxThrust.ToString("F1")
); );
} }
); );
   
public static readonly VOID_DoubleValue currThrustWeight = new VOID_DoubleValue( public static readonly VOID_DoubleValue currThrustWeight = new VOID_DoubleValue(
"T:W Ratio", "T:W Ratio",
delegate() delegate()
{ {
if (SimManager.LastStage == null) if (SimManager.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return SimManager.LastStage.actualThrustToWeight; return SimManager.LastStage.actualThrustToWeight;
}, },
"" ""
); );
   
public static readonly VOID_DoubleValue maxThrustWeight = new VOID_DoubleValue( public static readonly VOID_DoubleValue maxThrustWeight = new VOID_DoubleValue(
"T:W Ratio", "T:W Ratio",
delegate() delegate()
{ {
if (SimManager.LastStage == null) if (SimManager.LastStage == null)
{ {
return double.NaN; return double.NaN;
} }
   
return SimManager.LastStage.maxThrustToWeight; return SimManager.LastStage.maxThrustToWeight;
}, },
"" ""
); );
   
public static readonly VOID_StrValue currmaxThrustWeight = new VOID_StrValue( public static readonly VOID_StrValue currmaxThrustWeight = new VOID_StrValue(
"T:W (curr/max)", "T:W (curr/max)",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return "N/A"; return "N/A";
   
return string.Format( return string.Format(
"{0} / {1}", "{0} / {1}",
(VOID_Data.currThrustWeight.Value).ToString("F2"), (VOID_Data.currThrustWeight.Value).ToString("F2"),
(VOID_Data.maxThrustWeight.Value).ToString("F2") (VOID_Data.maxThrustWeight.Value).ToString("F2")
); );
} }
); );
   
public static readonly VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue( public static readonly VOID_DoubleValue surfaceThrustWeight = new VOID_DoubleValue(
"Max T:W @ surface", "Max T:W @ surface",
delegate() delegate()
{ {
if (SimManager.Stages == null || SimManager.LastStage == null) if (SimManager.Stages == null || SimManager.LastStage == null)
return double.NaN; return double.NaN;
   
double maxThrust = SimManager.LastStage.thrust; double maxThrust = SimManager.LastStage.thrust;
double mass = SimManager.LastStage.totalMass; double mass = SimManager.LastStage.totalMass;
double gravity = (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) / double gravity = (VOID_Core.Constant_G * VOID_Core.Instance.vessel.mainBody.Mass) /
(VOID_Core.Instance.vessel.mainBody.Radius * VOID_Core.Instance.vessel.mainBody.Radius); (VOID_Core.Instance.vessel.mainBody.Radius * VOID_Core.Instance.vessel.mainBody.Radius);
double weight = mass * gravity; double weight = mass * gravity;
   
return maxThrust / weight; return maxThrust / weight;
}, },
"" ""
); );
   
public static readonly VOID_StrValue intakeAirStatus = new VOID_StrValue( public static readonly VOID_StrValue intakeAirStatus = new VOID_StrValue(
"Intake Air (Curr / Req)", "Intake Air (Curr / Req)",
delegate() delegate()
{ {
double currentAmount; double currentAmount;
double currentRequirement; double currentRequirement;
   
currentAmount = 0d; currentAmount = 0d;
currentRequirement = 0d; currentRequirement = 0d;
   
foreach (Part part in VOID_Core.Instance.vessel.Parts) foreach (Part part in VOID_Core.Instance.vessel.Parts)
{ {
if (part.enabled) if (part.enabled)
{ {
ModuleEngines engineModule; ModuleEngines engineModule;
ModuleEnginesFX enginesFXModule; ModuleEnginesFX enginesFXModule;
List<Propellant> propellantList = null; List<Propellant> propellantList = null;
   
if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule)) if (part.tryGetFirstModuleOfType<ModuleEngines>(out engineModule))
{ {
propellantList = engineModule.propellants; propellantList = engineModule.propellants;
} }
else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule)) else if (part.tryGetFirstModuleOfType<ModuleEnginesFX>(out enginesFXModule))
{ {
propellantList = enginesFXModule.propellants; propellantList = enginesFXModule.propellants;
} }
if (propellantList != null) if (propellantList != null)
{ {
foreach (Propellant propellant in propellantList) foreach (Propellant propellant in propellantList)
{ {
if (propellant.name == "IntakeAir") if (propellant.name == "IntakeAir")
{ {
currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime; currentRequirement += propellant.currentRequirement / TimeWarp.fixedDeltaTime;
break; break;
} }
} }
} }
} }
   
ModuleResourceIntake intakeModule; ModuleResourceIntake intakeModule;
   
if (part.enabled && part.tryGetFirstModuleOfType<ModuleResourceIntake>(out intakeModule)) if (part.enabled && part.tryGetFirstModuleOfType<ModuleResourceIntake>(out intakeModule))
{ {
if (intakeModule.resourceName == "IntakeAir") if (intakeModule.resourceName == "IntakeAir")
{ {
currentAmount += intakeModule.airFlow; currentAmount += intakeModule.airFlow;
} }
} }
} }
   
if (currentAmount == 0 && currentRequirement == 0) if (currentAmount == 0 && currentRequirement == 0)
{ {
return "N/A"; return "N/A";
} }
   
return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement); return string.Format("{0:F3} / {1:F3}", currentAmount, currentRequirement);
} }
); );
} }
} }