added helium resource, with the corresponding tank part (wip)
This commit is contained in:
parent
67bdfa615c
commit
a49fb7b123
@ -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
|
||||
}
|
||||
}
|
||||
|
31
Parts/HeliumTankRadial/heliumTankRadial.cfg
Normal file
31
Parts/HeliumTankRadial/heliumTankRadial.cfg
Normal file
@ -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
|
||||
}
|
||||
}
|
BIN
Parts/HeliumTankRadial/ksp_r_xenonTank_diff.dds
Normal file
BIN
Parts/HeliumTankRadial/ksp_r_xenonTank_diff.dds
Normal file
Binary file not shown.
BIN
Parts/HeliumTankRadial/model.mu
Normal file
BIN
Parts/HeliumTankRadial/model.mu
Normal file
Binary file not shown.
@ -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;
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </summary>
|
||||
[KSPField(isPersistant = false, guiActive = false)]
|
||||
public float CompressedGasStorage = 15000;
|
||||
|
||||
[KSPField(isPersistant = true, guiActive = true)]
|
||||
public float RemainingCompressedGas = 15000;
|
||||
|
||||
/// <summary>
|
||||
/// 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<LineRenderer>();
|
||||
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)
|
||||
{
|
||||
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 + ")");
|
||||
|
||||
// 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);
|
||||
// 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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
16
TweakScale.cfg
Normal file
16
TweakScale.cfg
Normal file
@ -0,0 +1,16 @@
|
||||
@PART[heliumTankRadial]
|
||||
{
|
||||
%MODULE[TweakScale]
|
||||
{
|
||||
type = free
|
||||
}
|
||||
}
|
||||
|
||||
@PART[balloon]
|
||||
{
|
||||
%MODULE[TweakScale]
|
||||
{
|
||||
type = stack
|
||||
defaultScale = 1.25
|
||||
}
|
||||
}
|
10
resources.cfg
Normal file
10
resources.cfg
Normal file
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user