Check all referenced objects are not null (Fixes #33).
--- a/KerbalEngineer/Editor/BuildAdvanced.cs
+++ b/KerbalEngineer/Editor/BuildAdvanced.cs
@@ -528,6 +528,11 @@
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
+ GUILayout.Label("Verbose Simulation Log:");
+ SimManager.logOutput = GUILayout.Toggle(SimManager.logOutput, "ENABLED", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
+ GUILayout.EndHorizontal();
+
+ GUILayout.BeginHorizontal();
GUILayout.Label("Build Engineer Overlay:", settingStyle);
BuildOverlay.Visible = GUILayout.Toggle(BuildOverlay.Visible, "VISIBLE", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
BuildOverlayPartInfo.NamesOnly = GUILayout.Toggle(BuildOverlayPartInfo.NamesOnly, "NAMES ONLY", buttonStyle, GUILayout.Width(100.0f * GuiDisplaySize.Offset));
--- a/KerbalEngineer/Flight/Readouts/Orbital/Eccentricity.cs
+++ b/KerbalEngineer/Flight/Readouts/Orbital/Eccentricity.cs
@@ -43,7 +43,7 @@
public override void Draw(SectionModule section)
{
- this.DrawLine(FlightGlobals.ship_orbit.eccentricity.ToString("F3"), section.IsHud);
+ this.DrawLine(FlightGlobals.ship_orbit.eccentricity.ToString("F5"), section.IsHud);
}
#endregion
--- a/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
+++ b/KerbalEngineer/Flight/Readouts/Rendezvous/RendezvousProcessor.cs
@@ -1,7 +1,7 @@
//
// Kerbal Engineer Redux
//
-// Copyright (C) 2014 CYBUTEK
+// Copyright (C) 2015 CYBUTEK
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -17,30 +17,19 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using System;
-
-using KerbalEngineer.Extensions;
-using KerbalEngineer.Helpers;
-
-#endregion
-
namespace KerbalEngineer.Flight.Readouts.Rendezvous
{
+ using System;
+ using Extensions;
+ using Helpers;
+
public class RendezvousProcessor : IUpdatable, IUpdateRequest
{
- #region Fields
-
private static readonly RendezvousProcessor instance = new RendezvousProcessor();
private Orbit originOrbit;
private Orbit targetOrbit;
- #endregion
-
- #region Properties
-
/// <summary>
/// Gets the target's altitude above its reference body.
/// </summary>
@@ -71,7 +60,10 @@
/// </summary>
public static RendezvousProcessor Instance
{
- get { return instance; }
+ get
+ {
+ return instance;
+ }
}
/// <summary>
@@ -149,10 +141,6 @@
/// </summary>
public bool UpdateRequested { get; set; }
- #endregion
-
- #region Methods: public
-
/// <summary>
/// Request and update to calculate the details.
/// </summary>
@@ -166,7 +154,13 @@
/// </summary>
public void Update()
{
- if (FlightGlobals.fetch.VesselTarget == null)
+ if (FlightGlobals.fetch == null ||
+ FlightGlobals.fetch.VesselTarget == null ||
+ FlightGlobals.ActiveVessel == null ||
+ FlightGlobals.ActiveVessel.targetObject == null ||
+ FlightGlobals.ActiveVessel.targetObject.GetOrbit() == null ||
+ FlightGlobals.ship_orbit == null ||
+ FlightGlobals.ship_orbit.referenceBody == null)
{
ShowDetails = false;
return;
@@ -174,55 +168,50 @@
ShowDetails = true;
- this.targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit();
- this.originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun || FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody)
+ targetOrbit = FlightGlobals.fetch.VesselTarget.GetOrbit();
+ originOrbit = (FlightGlobals.ship_orbit.referenceBody == Planetarium.fetch.Sun ||
+ FlightGlobals.ship_orbit.referenceBody == FlightGlobals.ActiveVessel.targetObject.GetOrbit().referenceBody)
? FlightGlobals.ship_orbit
: FlightGlobals.ship_orbit.referenceBody.orbit;
- RelativeInclination = this.originOrbit.GetRelativeInclination(this.targetOrbit);
+ RelativeInclination = originOrbit.GetRelativeInclination(targetOrbit);
RelativeVelocity = FlightGlobals.ship_tgtSpeed;
- RelativeSpeed = FlightGlobals.ship_obtSpeed - this.targetOrbit.orbitalSpeed;
- PhaseAngle = this.originOrbit.GetPhaseAngle(this.targetOrbit);
- InterceptAngle = this.CalcInterceptAngle();
- TimeToAscendingNode = this.originOrbit.GetTimeToVector(this.GetAscendingNode());
- TimeToDescendingNode = this.originOrbit.GetTimeToVector(this.GetDescendingNode());
- AngleToAscendingNode = this.originOrbit.GetAngleToVector(this.GetAscendingNode());
- AngleToDescendingNode = this.originOrbit.GetAngleToVector(this.GetDescendingNode());
- AltitudeSeaLevel = this.targetOrbit.altitude;
- ApoapsisHeight = this.targetOrbit.ApA;
- PeriapsisHeight = this.targetOrbit.PeA;
- TimeToApoapsis = this.targetOrbit.timeToAp;
- TimeToPeriapsis = this.targetOrbit.timeToPe;
- SemiMajorAxis = this.targetOrbit.semiMajorAxis;
- SemiMinorAxis = this.targetOrbit.semiMinorAxis;
-
- Distance = Vector3d.Distance(this.targetOrbit.pos, this.originOrbit.pos);
- OrbitalPeriod = this.targetOrbit.period;
- }
-
- #endregion
-
- #region Methods: private
+ RelativeSpeed = FlightGlobals.ship_obtSpeed - targetOrbit.orbitalSpeed;
+ PhaseAngle = originOrbit.GetPhaseAngle(targetOrbit);
+ InterceptAngle = CalcInterceptAngle();
+ TimeToAscendingNode = originOrbit.GetTimeToVector(GetAscendingNode());
+ TimeToDescendingNode = originOrbit.GetTimeToVector(GetDescendingNode());
+ AngleToAscendingNode = originOrbit.GetAngleToVector(GetAscendingNode());
+ AngleToDescendingNode = originOrbit.GetAngleToVector(GetDescendingNode());
+ AltitudeSeaLevel = targetOrbit.altitude;
+ ApoapsisHeight = targetOrbit.ApA;
+ PeriapsisHeight = targetOrbit.PeA;
+ TimeToApoapsis = targetOrbit.timeToAp;
+ TimeToPeriapsis = targetOrbit.timeToPe;
+ SemiMajorAxis = targetOrbit.semiMajorAxis;
+ SemiMinorAxis = targetOrbit.semiMinorAxis;
+
+ Distance = Vector3d.Distance(targetOrbit.pos, originOrbit.pos);
+ OrbitalPeriod = targetOrbit.period;
+ }
private double CalcInterceptAngle()
{
- var originRadius = (this.originOrbit.semiMinorAxis + this.originOrbit.semiMajorAxis) * 0.5;
- var targetRadius = (this.targetOrbit.semiMinorAxis + this.targetOrbit.semiMajorAxis) * 0.5;
- var angle = 180.0 * (1.0 - Math.Pow((originRadius + targetRadius) / (2.0 * targetRadius), 1.5));
+ double originRadius = (originOrbit.semiMinorAxis + originOrbit.semiMajorAxis) * 0.5;
+ double targetRadius = (targetOrbit.semiMinorAxis + targetOrbit.semiMajorAxis) * 0.5;
+ double angle = 180.0 * (1.0 - Math.Pow((originRadius + targetRadius) / (2.0 * targetRadius), 1.5));
angle = PhaseAngle - angle;
return RelativeInclination < 90.0 ? AngleHelper.Clamp360(angle) : AngleHelper.Clamp360(360.0 - (180.0 - angle));
}
private Vector3d GetAscendingNode()
{
- return Vector3d.Cross(this.targetOrbit.GetOrbitNormal(), this.originOrbit.GetOrbitNormal());
+ return Vector3d.Cross(targetOrbit.GetOrbitNormal(), originOrbit.GetOrbitNormal());
}
private Vector3d GetDescendingNode()
{
- return Vector3d.Cross(this.originOrbit.GetOrbitNormal(), this.targetOrbit.GetOrbitNormal());
- }
-
- #endregion
+ return Vector3d.Cross(originOrbit.GetOrbitNormal(), targetOrbit.GetOrbitNormal());
+ }
}
}
--- a/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
+++ b/KerbalEngineer/Flight/Readouts/Surface/Longitude.cs
@@ -17,35 +17,25 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using KerbalEngineer.Flight.Sections;
-
-#endregion
-
namespace KerbalEngineer.Flight.Readouts.Surface
{
+ using Helpers;
+ using Sections;
+
public class Longitude : ReadoutModule
{
- #region Constructors
-
public Longitude()
{
- this.Name = "Longitude";
- this.Category = ReadoutCategory.GetCategory("Surface");
- this.HelpString = "Shows the vessel's longitude around a celestial body. Longitude is the angle from the bodies prime meridian.";
- this.IsDefault = true;
+ Name = "Longitude";
+ Category = ReadoutCategory.GetCategory("Surface");
+ HelpString = "Shows the vessel's longitude around a celestial body. Longitude is the angle from the bodies prime meridian.";
+ IsDefault = true;
}
-
- #endregion
-
- #region Methods: public
public override void Draw(SectionModule section)
{
- this.DrawLine(KSPUtil.PrintLongitude(FlightGlobals.ship_longitude), section.IsHud);
+ double angle = AngleHelper.Clamp180(FlightGlobals.ship_longitude);
+ DrawLine(Units.ToAngleDMS(angle) + (angle < 0.0 ? "W" : " E"), section.IsHud);
}
-
- #endregion
}
}
--- a/KerbalEngineer/Helpers/AngleHelper.cs
+++ b/KerbalEngineer/Helpers/AngleHelper.cs
@@ -17,21 +17,30 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
-#region Using Directives
-
-using UnityEngine;
-
-#endregion
-
namespace KerbalEngineer.Helpers
{
+ using UnityEngine;
+
public static class AngleHelper
{
- #region Methods: public
+ public static double Clamp180(double angle)
+ {
+ angle = Clamp360(angle);
+ if (angle > 180.0)
+ {
+ angle = angle - 360.0;
+ }
+ return angle;
+ }
- public static double Clamp360(double value)
+ public static double Clamp360(double angle)
{
- return ClampBetween(value, 0.0, 360.0);
+ angle = angle % 360.0;
+ if (angle < 0.0)
+ {
+ angle = angle + 360.0;
+ }
+ return angle;
}
public static double ClampBetween(double value, double minimum, double maximum)
@@ -51,8 +60,8 @@
public static double GetAngleBetweenVectors(Vector3d left, Vector3d right)
{
- var angle = Vector3d.Angle(left, right);
- var rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
+ double angle = Vector3d.Angle(left, right);
+ Vector3d rotated = QuaternionD.AngleAxis(90.0, Vector3d.forward) * right;
if (Vector3d.Angle(rotated, left) > 90.0)
{
@@ -60,7 +69,5 @@
}
return angle;
}
-
- #endregion
}
}
--- a/KerbalEngineer/KerbalEngineer.csproj
+++ b/KerbalEngineer/KerbalEngineer.csproj
@@ -208,8 +208,7 @@
</ItemGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp">
- <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
- <Private>False</Private>
+ <HintPath>..\Game\KSP_Data\Managed\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="System">
<HintPath>..\Game\KSP_Data\Managed\System.dll</HintPath>
@@ -220,8 +219,7 @@
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine">
- <HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\SteamApps\common\Kerbal Space Program\KSP_Data\Managed\UnityEngine.dll</HintPath>
- <Private>False</Private>
+ <HintPath>..\Game\KSP_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup />
--- a/KerbalEngineer/VesselSimulator/EngineSim.cs
+++ b/KerbalEngineer/VesselSimulator/EngineSim.cs
@@ -86,11 +86,10 @@
List<Propellant> propellants,
bool active,
float resultingThrust,
- List<Transform> thrustTransforms)
+ List<Transform> thrustTransforms,
+ LogMsg log)
{
EngineSim engineSim = pool.Borrow();
-
- StringBuilder buffer = null;
engineSim.isp = 0.0;
engineSim.maxMach = 0.0f;
@@ -133,11 +132,7 @@
flowRate = GetFlowRate(engineSim.thrust, engineSim.isp);
}
- if (SimManager.logOutput)
- {
- buffer = new StringBuilder(1024);
- buffer.AppendFormat("flowRate = {0:g6}\n", flowRate);
- }
+ if (log != null) log.buf.AppendFormat("flowRate = {0:g6}\n", flowRate);
engineSim.thrust = flowRate * (engineSim.isp * IspG);
// I did not look into the diff between those 2 so I made them equal...
@@ -150,10 +145,7 @@
flowMass += propellant.ratio * ResourceContainer.GetResourceDensity(propellant.id);
}
- if (SimManager.logOutput)
- {
- buffer.AppendFormat("flowMass = {0:g6}\n", flowMass);
- }
+ if (log != null) log.buf.AppendFormat("flowMass = {0:g6}\n", flowMass);
for (int i = 0; i < propellants.Count; ++i)
{
@@ -165,21 +157,13 @@
}
double consumptionRate = propellant.ratio * flowRate / flowMass;
- if (SimManager.logOutput)
- {
- buffer.AppendFormat(
+ if (log != null) log.buf.AppendFormat(
"Add consumption({0}, {1}:{2:d}) = {3:g6}\n",
ResourceContainer.GetResourceName(propellant.id),
theEngine.name,
theEngine.partId,
consumptionRate);
- }
engineSim.resourceConsumptions.Add(propellant.id, consumptionRate);
- }
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print(buffer);
}
double thrustPerThrustTransform = engineSim.thrust / thrustTransforms.Count;
--- a/KerbalEngineer/VesselSimulator/PartSim.cs
+++ b/KerbalEngineer/VesselSimulator/PartSim.cs
@@ -34,7 +34,9 @@
private readonly List<AttachNodeSim> attachNodes = new List<AttachNodeSim>();
+ public double realMass;
public double baseMass;
+ public double baseMassForCoM;
public Vector3d centerOfMass;
public double cost;
public int decoupledInStage;
@@ -89,6 +91,7 @@
partSim.resourceFlowStates.Reset();
partSim.resources.Reset();
partSim.baseMass = 0d;
+ partSim.baseMassForCoM = 0d;
partSim.startMass = 0d;
}
@@ -100,17 +103,13 @@
public static PartSim New(Part thePart, int id, double atmosphere, LogMsg log)
{
PartSim partSim = pool.Borrow();
-
partSim.part = thePart;
partSim.centerOfMass = thePart.transform.TransformPoint(thePart.CoMOffset);
partSim.partId = id;
partSim.name = partSim.part.partInfo.name;
- if (log != null)
- {
- log.buf.AppendLine("Create PartSim for " + partSim.name);
- }
+ if (log != null) log.buf.AppendLine("Create PartSim for " + partSim.name);
partSim.parent = null;
partSim.parentAttach = partSim.part.attachMode;
@@ -125,19 +124,27 @@
partSim.cost = partSim.part.GetCostWet();
+ if (log != null)
+ {
+ log.buf.AppendLine("Parent part = " + (partSim.part.parent == null ? "null" : partSim.part.parent.partInfo.name));
+ log.buf.AppendLine("physicalSignificance = " + partSim.part.physicalSignificance);
+ log.buf.AppendLine("PhysicsSignificance = " + partSim.part.PhysicsSignificance);
+ }
+
// Work out if the part should have no physical significance
- partSim.isNoPhysics = partSim.part.HasModule<LaunchClamp>() ||
- partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
- partSim.part.PhysicsSignificance == 1;
-
- if (!partSim.isNoPhysics)
- {
- partSim.baseMass = partSim.part.mass;
- }
-
- if (SimManager.logOutput)
- {
- MonoBehaviour.print((partSim.isNoPhysics ? "Ignoring" : "Using") + " part.mass of " + partSim.part.mass);
+ // The root part is never "no physics"
+ partSim.isNoPhysics = partSim.part.physicalSignificance == Part.PhysicalSignificance.NONE ||
+ partSim.part.PhysicsSignificance == 1;
+
+ if (partSim.part.HasModule<LaunchClamp>())
+ {
+ partSim.realMass = 0d;
+ if (log != null) log.buf.AppendLine("Ignoring mass of launch clamp");
+ }
+ else
+ {
+ partSim.realMass = partSim.part.mass;
+ if (log != null) log.buf.AppendLine("Using part.mass of " + partSim.part.mass);
}
for (int i = 0; i < partSim.part.Resources.Count; i++)
@@ -148,21 +155,17 @@
// This can happen if a resource capacity is 0 and tweakable
if (!Double.IsNaN(resource.amount))
{
- if (SimManager.logOutput)
- {
- MonoBehaviour.print(resource.resourceName + " = " + resource.amount);
- }
+ if (log != null)
+ log.buf.AppendLine(resource.resourceName + " = " + resource.amount);
partSim.resources.Add(resource.info.id, resource.amount);
partSim.resourceFlowStates.Add(resource.info.id, resource.flowState ? 1 : 0);
}
else
{
- MonoBehaviour.print(resource.resourceName + " is NaN. Skipping.");
- }
- }
-
- partSim.startMass = partSim.GetMass(-1);
+ if (log != null) log.buf.AppendLine(resource.resourceName + " is NaN. Skipping.");
+ }
+ }
partSim.hasVessel = (partSim.part.vessel != null);
partSim.isLanded = partSim.hasVessel && partSim.part.vessel.Landed;
@@ -179,10 +182,8 @@
partSim.isEngine = partSim.hasMultiModeEngine || partSim.hasModuleEnginesFX || partSim.hasModuleEngines;
- if (SimManager.logOutput)
- {
- MonoBehaviour.print("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
- }
+ if (log != null) log.buf.AppendLine("Created " + partSim.name + ". Decoupled in stage " + partSim.decoupledInStage);
+
return partSim;
}
@@ -229,10 +230,7 @@
ModuleEnginesFX engine = engines[i];
if (engine.engineID == mode)
{
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
+ if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
@@ -254,7 +252,8 @@
engine.propellants,
engine.isOperational,
engine.resultingThrust,
- engine.thrustTransforms);
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
@@ -267,10 +266,7 @@
for (int i = 0; i < engines.Count; ++i)
{
ModuleEngines engine = engines[i];
- if (log != null)
- {
- log.buf.AppendLine("Module: " + engine.moduleName);
- }
+ if (log != null) log.buf.AppendLine("Module: " + engine.moduleName);
Vector3 thrustvec = this.CalculateThrustVector(vectoredThrust ? engine.thrustTransforms : null, log);
@@ -292,7 +288,8 @@
engine.propellants,
engine.isOperational,
engine.resultingThrust,
- engine.thrustTransforms);
+ engine.thrustTransforms,
+ log);
allEngines.Add(engineSim);
}
}
@@ -351,17 +348,22 @@
buffer.Append(name);
buffer.AppendFormat(":[id = {0:d}, decouple = {1:d}, invstage = {2:d}", partId, decoupledInStage, inverseStage);
- buffer.AppendFormat(", vesselName = '{0}'", vesselName);
- buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
- buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+ //buffer.AppendFormat(", vesselName = '{0}'", vesselName);
+ //buffer.AppendFormat(", vesselType = {0}", SimManager.GetVesselTypeString(vesselType));
+ //buffer.AppendFormat(", initialVesselName = '{0}'", initialVesselName);
+
+ buffer.AppendFormat(", isNoPhys = {0}", isNoPhysics);
+ buffer.AppendFormat(", baseMass = {0}", baseMass);
+ buffer.AppendFormat(", baseMassForCoM = {0}", baseMassForCoM);
buffer.AppendFormat(", fuelCF = {0}", fuelCrossFeed);
buffer.AppendFormat(", noCFNKey = '{0}'", noCrossFeedNodeKey);
buffer.AppendFormat(", isSep = {0}", isSepratron);
- foreach (int type in resources.Types)
- {
+ for (int i = 0; i < resources.Types.Count; i++)
+ {
+ int type = resources.Types[i];
buffer.AppendFormat(", {0} = {1:g6}", ResourceContainer.GetResourceName(type), resources[type]);
}
@@ -384,12 +386,11 @@
if (allParts != null)
{
String newPrefix = prefix + " ";
- foreach (PartSim partSim in allParts)
- {
+ for (int i = 0; i < allParts.Count; i++)
+ {
+ PartSim partSim = allParts[i];
if (partSim.parent == this)
- {
partSim.DumpPartToBuffer(buffer, newPrefix, allParts);
- }
}
}
}
@@ -398,18 +399,16 @@
{
foreach (int type in types)
{
- if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_MIN)
- {
+ if (resources.HasType(type) && resourceFlowStates[type] != 0 && resources[type] > SimManager.RESOURCE_PART_EMPTY_THRESH)
return false;
- }
}
return true;
}
- public double GetMass(int currentStage)
- {
- double mass = baseMass;
+ public double GetMass(int currentStage, bool forCoM = false)
+ {
+ double mass = forCoM ? baseMassForCoM : baseMass;
for (int i = 0; i < resources.Types.Count; ++i)
{
@@ -443,49 +442,41 @@
// Rule 1: Each part can be only visited once, If it is visited for second time in particular search it returns as is.
if (visited.Contains(this))
{
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
- }
-
+ if (log != null) log.buf.AppendLine(indent + "Returning empty set, already visited (" + name + ":" + partId + ")");
return;
}
- //if (log != null)
- // log.buf.AppendLine(indent + "Adding this to visited");
+ if (log != null) log.buf.AppendLine(indent + "Adding this to visited");
visited.Add(this);
// Rule 2: Part performs scan on start of every fuel pipe ending in it. This scan is done in order in which pipes were installed.
// Then it makes an union of fuel tank sets each pipe scan returned. If the resulting list is not empty, it is returned as result.
- //MonoBehaviour.print("foreach fuel line");
+ //MonoBehaviour.print("for each fuel line");
int lastCount = allSources.Count;
for (int i = 0; i < this.fuelTargets.Count; i++)
{
PartSim partSim = this.fuelTargets[i];
- if (visited.Contains(partSim))
- {
- //if (log != null)
- // log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
- }
- else
- {
- //if (log != null)
- // log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
-
- partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
+ if (partSim != null)
+ {
+ if (visited.Contains(partSim))
+ {
+ if (log != null) log.buf.AppendLine(indent + "Fuel target already visited, skipping (" + partSim.name + ":" + partSim.partId + ")");
+ }
+ else
+ {
+ if (log != null) log.buf.AppendLine(indent + "Adding fuel target as source (" + partSim.name + ":" + partSim.partId + ")");
+
+ partSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
+ }
}
}
if (allSources.Count > lastCount)
{
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
- }
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " fuel target sources (" + this.name + ":" + this.partId + ")");
return;
}
@@ -500,7 +491,7 @@
if (fuelCrossFeed)
{
lastCount = allSources.Count;
- //MonoBehaviour.print("foreach attach node");
+ //MonoBehaviour.print("for each attach node");
for (int i = 0; i < this.attachNodes.Count; i++)
{
AttachNodeSim attachSim = this.attachNodes[i];
@@ -514,13 +505,11 @@
{
if (visited.Contains(attachSim.attachedPartSim))
{
- //if (log != null)
- // log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Attached part already visited, skipping (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
}
else
{
- //if (log != null)
- // log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Adding attached part as source (" + attachSim.attachedPartSim.name + ":" + attachSim.attachedPartSim.partId + ")");
attachSim.attachedPartSim.GetSourceSet(type, allParts, visited, allSources, log, indent);
}
@@ -531,11 +520,7 @@
if (allSources.Count > lastCount)
{
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
- }
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " attached sources (" + this.name + ":" + this.partId + ")");
return;
}
}
@@ -550,13 +535,14 @@
{
allSources.Add(this);
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
- }
+ if (log != null) log.buf.AppendLine(indent + "Returning enabled tank as only source (" + name + ":" + partId + ")");
}
return;
+ }
+ else
+ {
+ if (log != null) log.buf.AppendLine(indent + "Not fuel tank or disabled. HasType = " + resources.HasType(type) + " FlowState = " + resourceFlowStates[type]);
}
// Rule 7: If the part is radially attached to another part and it is child of that part in the ship's tree structure, it scans its
@@ -567,8 +553,7 @@
{
if (visited.Contains(parent))
{
- //if (log != null)
- // log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Parent part already visited, skipping (" + parent.name + ":" + parent.partId + ")");
}
else
{
@@ -576,11 +561,7 @@
this.parent.GetSourceSet(type, allParts, visited, allSources, log, indent);
if (allSources.Count > lastCount)
{
- if (log != null)
- {
- log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
- }
-
+ if (log != null) log.buf.AppendLine(indent + "Returning " + (allSources.Count - lastCount) + " parent sources (" + this.name + ":" + this.partId + ")");
return;
}
}
@@ -588,8 +569,7 @@
}
// Rule 8: If all preceding rules failed, part returns empty list.
- //if (log != null)
- // log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
+ if (log != null) log.buf.AppendLine(indent + "Returning empty set, no sources found (" + name + ":" + partId + ")");
return;
}
@@ -611,14 +591,22 @@
attachSim.attachedPartSim = null;
}
}
+
+ // Loop through the fuel targets (fuel line sources)
+ for (int i = 0; i < this.fuelTargets.Count; i++)
+ {
+ PartSim fuelTargetSim = this.fuelTargets[i];
+ // If the part is in the set then "remove" it by clearing the PartSim reference
+ if (fuelTargetSim != null && partSims.Contains(fuelTargetSim))
+ {
+ this.fuelTargets[i] = null;
+ }
+ }
}
public void SetupAttachNodes(Dictionary<Part, PartSim> partSimLookup, LogMsg log)
{
- if (log != null)
- {
- log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
- }
+ if (log != null) log.buf.AppendLine("SetupAttachNodes for " + name + ":" + partId + "");
attachNodes.Clear();
@@ -626,29 +614,20 @@
{
AttachNode attachNode = part.attachNodes[i];
- if (log != null)
- {
- log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
- }
+ if (log != null) log.buf.AppendLine("AttachNode " + attachNode.id + " = " + (attachNode.attachedPart != null ? attachNode.attachedPart.partInfo.name : "null"));
if (attachNode.attachedPart != null && attachNode.id != "Strut")
{
PartSim attachedSim;
if (partSimLookup.TryGetValue(attachNode.attachedPart, out attachedSim))
{
- if (log != null)
- {
- log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
- }
+ if (log != null) log.buf.AppendLine("Adding attached node " + attachedSim.name + ":" + attachedSim.partId + "");
attachNodes.Add(AttachNodeSim.New(attachedSim, attachNode.id, attachNode.nodeType));
}
else
{
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
- }
+ if (log != null) log.buf.AppendLine("No PartSim for attached part (" + attachNode.attachedPart.partInfo.name + ")");
}
}
}
@@ -662,19 +641,13 @@
PartSim targetSim;
if (partSimLookup.TryGetValue(p, out targetSim))
{
- if (log != null)
- {
- log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
- }
+ if (log != null) log.buf.AppendLine("Fuel target: " + targetSim.name + ":" + targetSim.partId);
fuelTargets.Add(targetSim);
}
else
{
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
- }
+ if (log != null) log.buf.AppendLine("No PartSim for fuel target (" + p.name + ")");
}
}
}
@@ -687,17 +660,11 @@
parent = null;
if (partSimLookup.TryGetValue(part.parent, out parent))
{
- if (log != null)
- {
- log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
- }
+ if (log != null) log.buf.AppendLine("Parent part is " + parent.name + ":" + parent.partId);
}
else
{
- if (log != null)
- {
- log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
- }
+ if (log != null) log.buf.AppendLine("No PartSim for parent part (" + part.parent.partInfo.name + ")");
}
}
}
@@ -735,43 +702,27 @@
{
Transform trans = thrustTransforms[i];
- if (log != null)
- {
- log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("Transform = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", trans.forward.x, trans.forward.y, trans.forward.z, trans.forward.magnitude);
thrustvec -= trans.forward;
}
- if (log != null)
- {
- log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("ThrustVec = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
thrustvec.Normalize();
- if (log != null)
- {
- log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
- }
+ if (log != null) log.buf.AppendFormat("ThrustVecN = ({0:g6}, {1:g6}, {2:g6}) length = {3:g6}\n", thrustvec.x, thrustvec.y, thrustvec.z, thrustvec.magnitude);
return thrustvec;
}
private int DecoupledInStage(Part thePart, int stage = -1)
{
- if (IsDecoupler(thePart))
- {
- if (thePart.inverseStage > stage)
- {
- stage = thePart.inverseStage;
- }
- }
+ if (IsDecoupler(thePart) && thePart.inverseStage > stage)
+ stage = thePart.inverseStage;
if (thePart.parent != null)
- {
stage = DecoupledInStage(thePart.parent, stage);
- }
return stage;
}
--- a/KerbalEngineer/VesselSimulator/SimManager.cs
+++ b/KerbalEngineer/VesselSimulator/SimManager.cs
@@ -35,6 +35,7 @@
#region Constants
public const double RESOURCE_MIN = 0.0001;
+ public const double RESOURCE_PART_EMPTY_THRESH = 0.01;
#endregion
--- a/KerbalEngineer/VesselSimulator/Simulation.cs
+++ b/KerbalEngineer/VesselSimulator/Simulation.cs
@@ -119,7 +119,7 @@
for (int i = 0; i < allParts.Count; ++i)
{
PartSim partSim = allParts[i];
- vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage));
+ vectorAverager.Add(partSim.centerOfMass, partSim.GetMass(currentStage, true));
}
return vectorAverager.Get();
@@ -394,6 +394,12 @@
this._timer.Start();
}
+ // Update the masses of the parts to correctly handle "no physics" parts
+ this.UpdatePartMasses();
+
+ if (log != null)
+ this.allParts[0].DumpPartToBuffer(log.buf, "", this.allParts);
+
// Update active engines and resource drains
this.UpdateResourceDrains();
@@ -413,11 +419,11 @@
// Store various things in the Stage object
stage.thrust = this.totalStageThrust;
- //MonoBehaviour.print("stage.thrust = " + stage.thrust);
+ if (log != null) log.buf.AppendLine("stage.thrust = " + stage.thrust);
stage.thrustToWeight = this.totalStageThrust / (this.stageStartMass * this.gravity);
stage.maxThrustToWeight = stage.thrustToWeight;
- //MonoBehaviour.print("StageMass = " + stageStartMass);
- //MonoBehaviour.print("Initial maxTWR = " + stage.maxThrustToWeight);
+ if (log != null) log.buf.AppendLine("StageMass = " + stageStartMass);
+ if (log != null) log.buf.AppendLine("Initial maxTWR = " + stage.maxThrustToWeight);
stage.actualThrust = this.totalStageActualThrust;
stage.actualThrustToWeight = this.totalStageActualThrust / (this.stageStartMass * this.gravity);
@@ -650,6 +656,40 @@
return stages;
}
+ public void UpdatePartMasses()
+ {
+ for (int i = 0; i < this.allParts.Count; i++)
+ {
+ this.allParts[i].baseMass = this.allParts[i].realMass;
+ this.allParts[i].baseMassForCoM = this.allParts[i].realMass;
+ }
+
+ for (int i = 0; i < this.allParts.Count; i++)
+ {
+ PartSim part = this.allParts[i];
+ // If the part has a parent
+ if (part.parent != null)
+ {
+ if (part.isNoPhysics)
+ {
+ if (part.parent.isNoPhysics && part.parent.parent != null)
+ {
+ part.baseMass = 0d;
+ part.baseMassForCoM = 0d;
+ }
+ else
+ {
+ part.parent.baseMassForCoM += part.baseMassForCoM;
+ part.baseMassForCoM = 0d;
+ }
+ }
+ }
+ }
+
+ for (int i = 0; i < this.allParts.Count; i++)
+ this.allParts[i].startMass = this.allParts[i].GetMass(currentStage);
+ }
+
// Make sure we free them all, even if they should all be free already at this point
public void FreePooledObject()
{
Binary files a/Output/KerbalEngineer/KerbalEngineer.dll and b/Output/KerbalEngineer/KerbalEngineer.dll differ