private KLFVesselDetail getVesselDetail(Vessel vessel)
{
KLFVesselDetail detail = new KLFVesselDetail();
detail.idle = isIdle;
detail.mass = vessel.GetTotalMass();
bool is_eva = false;
bool parachutes_open = false;
//Check if the vessel is an EVA Kerbal
if (vessel.isEVA && vessel.parts.Count > 0 && vessel.parts.First().Modules.Count > 0)
{
foreach (PartModule module in vessel.parts.First().Modules)
{
if (module is KerbalEVA)
{
KerbalEVA kerbal = (KerbalEVA)module;
detail.percentFuel = (byte)Math.Round(kerbal.Fuel / kerbal.FuelCapacity * 100);
detail.percentRCS = byte.MaxValue;
detail.numCrew = byte.MaxValue;
is_eva = true;
break;
}
}
}
if (!is_eva)
{
if (vessel.GetCrewCapacity() > 0)
detail.numCrew = (byte)vessel.GetCrewCount();
else
detail.numCrew = byte.MaxValue;
Dictionary<string, float> fuel_densities = new Dictionary<string, float>();
Dictionary<string, float> rcs_fuel_densities = new Dictionary<string, float>();
bool has_engines = false;
bool has_rcs = false;
foreach (Part part in vessel.parts)
{
foreach (PartModule module in part.Modules)
{
if (module is ModuleEngines)
{
//Determine what kinds of fuel this vessel can use and their densities
ModuleEngines engine = (ModuleEngines)module;
has_engines = true;
foreach (ModuleEngines.Propellant propellant in engine.propellants)
{
if (propellant.name == "ElectricCharge" || propellant.name == "IntakeAir")
{
continue;
}
if (!fuel_densities.ContainsKey(propellant.name))
fuel_densities.Add(propellant.name, PartResourceLibrary.Instance.GetDefinition(propellant.id).density);
}
}
if (module is ModuleRCS)
{
ModuleRCS rcs = (ModuleRCS)module;
if (rcs.requiresFuel)
{
has_rcs = true;
if (!rcs_fuel_densities.ContainsKey(rcs.resourceName))
rcs_fuel_densities.Add(rcs.resourceName, PartResourceLibrary.Instance.GetDefinition(rcs.resourceName).density);
}
}
if (module is ModuleParachute)
{
ModuleParachute parachute = (ModuleParachute)module;
if (parachute.deploymentState == ModuleParachute.deploymentStates.DEPLOYED)
parachutes_open = true;
}
}
}
//Determine how much fuel this vessel has and can hold
float fuel_capacity = 0.0f;
float fuel_amount = 0.0f;
float rcs_capacity = 0.0f;
float rcs_amount = 0.0f;
foreach (Part part in vessel.parts)
{
if (part != null && part.Resources != null)
{
foreach (PartResource resource in part.Resources)
{
float density = 0.0f;
//Check that this vessel can use this type of resource as fuel
if (has_engines && fuel_densities.TryGetValue(resource.resourceName, out density))
{
fuel_capacity += ((float)resource.maxAmount) * density;
fuel_amount += ((float)resource.amount) * density;
}
if (has_rcs && rcs_fuel_densities.TryGetValue(resource.resourceName, out density))
{
rcs_capacity += ((float)resource.maxAmount) * density;
rcs_amount += ((float)resource.amount) * density;
}
}
}
}
if (has_engines && fuel_capacity > 0.0f)
detail.percentFuel = (byte)Math.Round(fuel_amount / fuel_capacity * 100);
else
detail.percentFuel = byte.MaxValue;
if (has_rcs && rcs_capacity > 0.0f)
detail.percentRCS = (byte)Math.Round(rcs_amount / rcs_capacity * 100);
else
detail.percentRCS = byte.MaxValue;
}
//Determine vessel activity
if (parachutes_open)
detail.activity = Activity.PARACHUTING;
//Check if the vessel is aerobraking
if (vessel.orbit != null && vessel.orbit.referenceBody != null
&& vessel.orbit.referenceBody.atmosphere && vessel.orbit.altitude < vessel.orbit.referenceBody.maxAtmosphereAltitude)
{
//Vessel inside its body's atmosphere
switch (vessel.situation)
{
case Vessel.Situations.LANDED:
case Vessel.Situations.SPLASHED:
case Vessel.Situations.SUB_ORBITAL:
case Vessel.Situations.PRELAUNCH:
break;
default:
//If the apoapsis of the orbit is above the atmosphere, vessel is aerobraking
if (vessel.situation == Vessel.Situations.ESCAPING || (float)vessel.orbit.ApA > vessel.orbit.referenceBody.maxAtmosphereAltitude)
detail.activity = Activity.AEROBRAKING;
break;
}
}
//Check if the vessel is docking
if (detail.activity == Activity.NONE && FlightGlobals.fetch.VesselTarget != null && FlightGlobals.fetch.VesselTarget is ModuleDockingNode
&& Vector3.Distance(vessel.GetWorldPos3D(), FlightGlobals.fetch.VesselTarget.GetTransform().position) < DOCKING_TARGET_RANGE)
detail.activity = Activity.DOCKING;
return detail;
}