diff --git a/Parts/Balloon/balloon.cfg b/Parts/Balloon/balloon.cfg
index da650ed..8552083 100644
--- a/Parts/Balloon/balloon.cfg
+++ b/Parts/Balloon/balloon.cfg
@@ -11,11 +11,11 @@ PART
sound_parachute_open = activate
TechRequired = advLanding
entryCost = 3500
- cost = 400
+ cost = 5000
category = Utility
subcategory = 0
title = Balloon
- description = A test balloon.
+ description = A big balloon that can be inflated with helium (sold separately).
attachRules = 1,0,0,1,0
mass = 0.2
dragModelType = default
@@ -30,7 +30,5 @@ PART
MODULE
{
name = ModuleAerostat
- DeployAnimation = semiDeployLarge
- InflateAnimation = fullyDeployLarge
}
}
diff --git a/Parts/HeliumTankRadial/heliumTankRadial.cfg b/Parts/HeliumTankRadial/heliumTankRadial.cfg
new file mode 100644
index 0000000..d04e366
--- /dev/null
+++ b/Parts/HeliumTankRadial/heliumTankRadial.cfg
@@ -0,0 +1,31 @@
+PART
+{
+ name = heliumTankRadial
+ module = Part
+ author = Youen
+ mesh = model.mu
+ rescaleFactor = 1
+ node_attach = 0.0, 0.0, -0.1875, 0.0, 0.0, -1.0
+ TechRequired = advLanding
+ entryCost = 2000
+ cost = 2200
+ category = FuelTank
+ subcategory = 0
+ title = Helium tank
+ description = Disposable helium tank for all your lifting needs (and birthday party balloons). Do not refill after use.
+ attachRules = 0,1,0,0,1
+ mass = 0.003
+ dragModelType = default
+ maximum_drag = 0.2
+ minimum_drag = 0.2
+ angularDrag = 2
+ crashTolerance = 12
+ maxTemp = 2000 // = 2900
+ bulkheadProfiles = srf
+ RESOURCE
+ {
+ name = Helium
+ amount = 30
+ maxAmount = 30
+ }
+}
diff --git a/Parts/HeliumTankRadial/ksp_r_xenonTank_diff.dds b/Parts/HeliumTankRadial/ksp_r_xenonTank_diff.dds
new file mode 100644
index 0000000..00e3691
Binary files /dev/null and b/Parts/HeliumTankRadial/ksp_r_xenonTank_diff.dds differ
diff --git a/Parts/HeliumTankRadial/model.mu b/Parts/HeliumTankRadial/model.mu
new file mode 100644
index 0000000..d79b57f
Binary files /dev/null and b/Parts/HeliumTankRadial/model.mu differ
diff --git a/Plugin/ModuleAerostat.cs b/Plugin/ModuleAerostat.cs
index 302f983..d5cee59 100644
--- a/Plugin/ModuleAerostat.cs
+++ b/Plugin/ModuleAerostat.cs
@@ -8,12 +8,6 @@ namespace Aerostats
{
public class ModuleAerostat : PartModule
{
- [KSPField(isPersistant = false, guiActive = false)]
- public string DeployAnimation = "semiDeploy";
-
- [KSPField(isPersistant = false, guiActive = false)]
- public string InflateAnimation = "fullyDeploy";
-
// In this class, amount of gas Q is specified in m^3 at stp (standard pressure of 100kPa and temperature of 0°C = 273K). Ideal gas equation P.V = n.R.T gives us the equivalent number of moles: n = P.V/R/T = 100000.Q/8.314/273 = 44.Q mol
private static readonly float R = 8.314f;
private static readonly float ZeroCelsius = 273.15f;
@@ -39,16 +33,6 @@ namespace Aerostats
[KSPField(isPersistant = false, guiActive = false)]
public float MaxBalloonVolume = 10000;
- ///
- /// Maximum initial reserve of compressed gas, in m^3 at stp
- /// For helium, the volume needed to store this reserve is about 0.0014m^3 of compressed storage (liquid) for 1m^3 of gas at stp
- ///
- [KSPField(isPersistant = false, guiActive = false)]
- public float CompressedGasStorage = 15000;
-
- [KSPField(isPersistant = true, guiActive = true)]
- public float RemainingCompressedGas = 15000;
-
///
/// Weight, in kilograms, of 1m^3 of gas at 100kPa and 0°C
/// Helium is 179g/m^3
@@ -112,35 +96,6 @@ namespace Aerostats
private GameObject Balloon;
private LineRenderer Spring;
- private void PlayAnimation(string animationName, float animationSpeed)
- {
- foreach (Animation animation in part.FindModelAnimators(animationName))
- {
- AnimationState state = animation[animationName];
- state.normalizedTime = 0;
- state.normalizedSpeed = animationSpeed;
- state.enabled = true;
- animation.Play(animationName);
- }
- }
-
- private bool IsAnimationPlaying(string animationName)
- {
- return part.FindModelAnimators(animationName).Any(a => a[animationName].enabled);
- }
-
- private void SetInflation(float ratio)
- {
- foreach (Animation animation in part.FindModelAnimators(InflateAnimation))
- {
- AnimationState state = animation[InflateAnimation];
- state.normalizedTime = ratio;
- state.normalizedSpeed = 0;
- state.enabled = true;
- animation.Play(InflateAnimation);
- }
- }
-
public override void OnStart(PartModule.StartState state)
{
if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight) { return; }
@@ -153,7 +108,6 @@ namespace Aerostats
{
UnityEngine.Debug.Log("Aerostats: staged");
ScreenMessages.PostScreenMessage("staged");
- //PlayAnimation(DeployAnimation, 1.0f);
Balloon = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Balloon.transform.position = part.Rigidbody.position + part.Rigidbody.transform.up;
@@ -162,8 +116,7 @@ namespace Aerostats
Balloon.rigidbody.angularDrag = 10.0f;
- LiftingGasQuantity = Math.Min(MinimumFillQuantity, RemainingCompressedGas);
- RemainingCompressedGas -= LiftingGasQuantity;
+ LiftingGasQuantity = part.RequestResource("Helium", MinimumFillQuantity);
Spring = Balloon.AddComponent();
Spring.useWorldSpace = true;
@@ -193,96 +146,83 @@ namespace Aerostats
if (Staged)
{
- //if (!IsAnimationPlaying(DeployAnimation))
+ float externalTemperature = (float)FlightGlobals.getExternalTemperature();
+ float balloonInternalTemperature = externalTemperature;
+ float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure() * 1000.0f, 0.00001f);
+ Util.PostSingleScreenMessage("external atmo", "Temperature = " + externalTemperature + "K, Pressure=" + externalPressure + "Pa");
+
+ float currentMaxQuantity = MaxBalloonVolume / R / balloonInternalTemperature * externalPressure / StpVolumeToMoles;
+
+ LiftingGasTargetQuantity = Math.Max(MinimumFillQuantity, LiftingGasTargetQuantity);
+ if(LiftingGasTargetQuantity > LiftingGasQuantity)
+ {
+ // infalting balloon
+ float stepFinalQuantity = Math.Min(LiftingGasQuantity + MaxGasFillRate * Time.fixedDeltaTime, Math.Min(LiftingGasTargetQuantity, currentMaxQuantity));
+ float step = Math.Max(stepFinalQuantity - LiftingGasQuantity, 0.0f);
+ LiftingGasQuantity += part.RequestResource("Helium", step);
+ }
+ else
+ {
+ // deflating balloon
+ LiftingGasQuantity = Math.Max(LiftingGasQuantity - MaxGasVentRate * Time.fixedDeltaTime, LiftingGasTargetQuantity);
+ }
+
+
+ // balloon security valve
+ if (LiftingGasQuantity > currentMaxQuantity)
{
- float externalTemperature = (float)FlightGlobals.getExternalTemperature();
- float balloonInternalTemperature = externalTemperature;
- float externalPressure = Math.Max((float)FlightGlobals.getStaticPressure() * 1000.0f, 0.00001f);
- Util.PostSingleScreenMessage("external atmo", "Temperature = " + externalTemperature + "K, Pressure=" + externalPressure + "Pa");
-
- float currentMaxQuantity = MaxBalloonVolume / R / balloonInternalTemperature * externalPressure / StpVolumeToMoles;
-
- LiftingGasTargetQuantity = Math.Max(MinimumFillQuantity, LiftingGasTargetQuantity);
- if(LiftingGasTargetQuantity > LiftingGasQuantity)
- {
- // infalting balloon
- float stepFinalQuantity = Math.Min(LiftingGasQuantity + MaxGasFillRate * Time.fixedDeltaTime, Math.Min(LiftingGasTargetQuantity, currentMaxQuantity));
- float step = Math.Max(stepFinalQuantity - LiftingGasQuantity, 0.0f);
- LiftingGasQuantity += step;
- RemainingCompressedGas -= step;
-
- // gas exhausted
- if(RemainingCompressedGas < 0)
- {
- Util.PostSingleScreenMessage("out of gas", "Lifting gas reserve exhausted");
- LiftingGasQuantity += RemainingCompressedGas;
- RemainingCompressedGas = 0;
- }
- }
- else
- {
- // deflating balloon
- LiftingGasQuantity = Math.Max(LiftingGasQuantity - MaxGasVentRate * Time.fixedDeltaTime, LiftingGasTargetQuantity);
- }
-
-
- // balloon security valve
- if (LiftingGasQuantity > currentMaxQuantity)
- {
- Util.PostSingleScreenMessage("security valve", "Some gas has been vented by the balloon security valve");
- LiftingGasQuantity = currentMaxQuantity;
- }
-
- float currentGasMoles = StpVolumeToMoles * LiftingGasQuantity;
- float currentGasVolume = currentGasMoles * R * balloonInternalTemperature / externalPressure;
- Inflation = currentGasVolume / MaxBalloonVolume;
-
- Util.PostSingleScreenMessage("inflation", "Inflation = " + (Inflation * 100.0f).ToString("0.00") + "%");
- //SetInflation(Inflation);
-
- float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, vessel.mainBody);
- float currentGasDensity = GasDensity * balloonInternalTemperature / ZeroCelsius / externalPressure * StandardPressure;
- float balloonLift = currentGasVolume * airDensity;
- float balloonGasMass = currentGasDensity * currentGasVolume;
- Util.PostSingleScreenMessage("lift", "Air density = " + airDensity + "kg/m^3, Lift = " + (balloonLift - balloonGasMass) + "kg");
- var gravityAccel = FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D());
- //Util.PostSingleScreenMessage("gravity", "Gravity accel = (" + gravityAccel.x + ", " + gravityAccel.y + ", " + gravityAccel.z + ")");
+ Util.PostSingleScreenMessage("security valve", "Some gas has been vented by the balloon security valve");
+ LiftingGasQuantity = currentMaxQuantity;
+ }
+
+ float currentGasMoles = StpVolumeToMoles * LiftingGasQuantity;
+ float currentGasVolume = currentGasMoles * R * balloonInternalTemperature / externalPressure;
+ Inflation = currentGasVolume / MaxBalloonVolume;
+
+ Util.PostSingleScreenMessage("inflation", "Inflation = " + (Inflation * 100.0f).ToString("0.00") + "%");
+
+ float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, vessel.mainBody);
+ float currentGasDensity = GasDensity * balloonInternalTemperature / ZeroCelsius / externalPressure * StandardPressure;
+ float balloonLift = currentGasVolume * airDensity;
+ float balloonGasMass = currentGasDensity * currentGasVolume;
+ Util.PostSingleScreenMessage("lift", "Air density = " + airDensity + "kg/m^3, Lift = " + (balloonLift - balloonGasMass) + "kg");
+ var gravityAccel = FlightGlobals.getGeeForceAtPosition(vessel.GetWorldPos3D());
+ //Util.PostSingleScreenMessage("gravity", "Gravity accel = (" + gravityAccel.x + ", " + gravityAccel.y + ", " + gravityAccel.z + ")");
- // V = 4/3*pi*r^3
- float radius = Mathf.Pow(currentGasVolume * 0.75f / Mathf.PI, 0.333f);
- float scale = radius * 2.0f + 0.1f;
- Balloon.transform.localScale = new Vector3(scale,scale,scale);
- Balloon.rigidbody.mass = (BalloonEmptyMass + balloonGasMass) * 0.001f;
-
- Balloon.rigidbody.AddForce(-gravityAccel * balloonLift / 1000.0f, ForceMode.Force);
-
- // balloon drag
- var airVelocity = Balloon.rigidbody.velocity + Krakensbane.GetFrameVelocity() /*- vessel.mainBody.getRFrmVel(vessel.GetWorldPos3D())*/;
- float sqVel = (float)airVelocity.magnitude;
- sqVel *= sqVel;
- float dragForce = 0.5f * airDensity * sqVel * BalloonDragCoeff * (Mathf.PI * radius * radius);
- Util.PostSingleScreenMessage("balloon drag", "Drag = " + dragForce + "N");
- Balloon.rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force);
-
- // spring between balloon and base
- float restLength = SpringRestLength + radius;
- var springVec = Balloon.rigidbody.position - part.rigidbody.position;
- float springLength = springVec.magnitude;
- float springForceMag = 0;
- var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * radius;
- if(springLength > restLength)
- {
- float tensingLength = springLength - restLength;
- springForceMag = tensingLength * SpringHardness;
- var springForce = springVec * (springForceMag / springLength * 0.001f);
- part.rigidbody.AddForce(springForce, ForceMode.Force);
- Balloon.rigidbody.AddForceAtPosition(-springForce, balloonAttachPoint, ForceMode.Force);
- }
- Util.PostSingleScreenMessage("spring force", "Spring force = " + springForceMag + "N");
-
- Spring.SetPosition(0, part.transform.position);
- Spring.SetPosition(1, balloonAttachPoint);
+ // V = 4/3*pi*r^3
+ float radius = Mathf.Pow(currentGasVolume * 0.75f / Mathf.PI, 0.333f);
+ float scale = radius * 2.0f + 0.1f;
+ Balloon.transform.localScale = new Vector3(scale,scale,scale);
+ Balloon.rigidbody.mass = (BalloonEmptyMass + balloonGasMass) * 0.001f;
+
+ Balloon.rigidbody.AddForce(-gravityAccel * balloonLift / 1000.0f, ForceMode.Force);
+
+ // balloon drag
+ var airVelocity = Balloon.rigidbody.velocity + Krakensbane.GetFrameVelocity() /*- vessel.mainBody.getRFrmVel(vessel.GetWorldPos3D())*/;
+ float sqVel = (float)airVelocity.magnitude;
+ sqVel *= sqVel;
+ float dragForce = 0.5f * airDensity * sqVel * BalloonDragCoeff * (Mathf.PI * radius * radius);
+ Util.PostSingleScreenMessage("balloon drag", "Drag = " + dragForce + "N");
+ Balloon.rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force);
+
+ // spring between balloon and base
+ float restLength = SpringRestLength + radius;
+ var springVec = Balloon.rigidbody.position - part.rigidbody.position;
+ float springLength = springVec.magnitude;
+ float springForceMag = 0;
+ var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * radius;
+ if(springLength > restLength)
+ {
+ float tensingLength = springLength - restLength;
+ springForceMag = tensingLength * SpringHardness;
+ var springForce = springVec * (springForceMag / springLength * 0.001f);
+ part.rigidbody.AddForce(springForce, ForceMode.Force);
+ Balloon.rigidbody.AddForceAtPosition(-springForce, balloonAttachPoint, ForceMode.Force);
}
+ Util.PostSingleScreenMessage("spring force", "Spring force = " + springForceMag + "N");
+
+ Spring.SetPosition(0, part.transform.position);
+ Spring.SetPosition(1, balloonAttachPoint);
}
}
}
diff --git a/TweakScale.cfg b/TweakScale.cfg
new file mode 100644
index 0000000..f202707
--- /dev/null
+++ b/TweakScale.cfg
@@ -0,0 +1,16 @@
+@PART[heliumTankRadial]
+{
+ %MODULE[TweakScale]
+ {
+ type = free
+ }
+}
+
+@PART[balloon]
+{
+ %MODULE[TweakScale]
+ {
+ type = stack
+ defaultScale = 1.25
+ }
+}
diff --git a/resources.cfg b/resources.cfg
new file mode 100644
index 0000000..7689ae3
--- /dev/null
+++ b/resources.cfg
@@ -0,0 +1,10 @@
+RESOURCE_DEFINITION
+{
+ name = Helium
+ density = 0.000179 // storage unit is m^3 of Helium at standard pressure (100kPa, 0°C), which has a density of 0.179kg/m^3 (helium tanks store liquid helium which occupies less space, but still weights the same)
+ unitCost = 1.2
+ hsp = 3000
+ flowMode = STAGE_PRIORITY_FLOW
+ transfer = PUMP
+ isTweakable = true
+}