Browse Source

- fixed angular drag bug

- game load support (wip)
master
Youen Toupin 8 years ago
parent
commit
7102f572ed
  1. 67
      Plugin/ModuleBalloon.cs
  2. 77
      Plugin/ModuleBalloonCase.cs

67
Plugin/ModuleBalloon.cs

@ -26,9 +26,18 @@ namespace Aerostats
/// <summary> /// <summary>
/// Mass of the empty balloon, in kg /// Mass of the empty balloon, in kg
/// </summary> /// </summary>
public float EmptyMass { get; private set; } [KSPField(isPersistant = true, guiActive = false)]
public float EmptyMass;
[KSPField(isPersistant = true, guiActive = false)]
public float LiftingGasQuantity;
[KSPField(isPersistant = true, guiActive = false)]
public float Scale;
[KSPField(isPersistant = true, guiActive = false)]
public Vector3d Velocity;
public float LiftingGasQuantity { get; private set; }
public float CurrentVolume { get; private set; } public float CurrentVolume { get; private set; }
public float Lift { get; private set; } public float Lift { get; private set; }
public bool IsVenting { get; private set; } public bool IsVenting { get; private set; }
@ -50,7 +59,13 @@ namespace Aerostats
AttachedCase = attachedCase; AttachedCase = attachedCase;
GasMolarMass = gasDensity / GasUtilities.StpVolumeToMoles; GasMolarMass = gasDensity / GasUtilities.StpVolumeToMoles;
EmptyMass = part.mass * 1000.0f; EmptyMass = part.mass * 1000.0f;
Velocity = initialVelocity;
LiftingGasQuantity = initialGasQuantity;
Initialize();
}
private void Initialize()
{
// replace mesh and collider by a sphere (hack until proper assets are created) // replace mesh and collider by a sphere (hack until proper assets are created)
var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
var meshFilter = gameObject.GetComponentInChildren<MeshFilter>(); var meshFilter = gameObject.GetComponentInChildren<MeshFilter>();
@ -72,22 +87,49 @@ namespace Aerostats
gameObject.AddComponent<Rigidbody>(); gameObject.AddComponent<Rigidbody>();
rigidbody.mass = EmptyMass * 0.001f; rigidbody.mass = EmptyMass * 0.001f;
part.mass = rigidbody.mass; part.mass = rigidbody.mass;
rigidbody.velocity = initialVelocity; rigidbody.velocity = Velocity - Krakensbane.GetFrameVelocity();
rigidbody.position = transform.position; rigidbody.position = transform.position;
part.rb = rigidbody; part.rb = rigidbody;
InjectGas(initialGasQuantity); float initialQuantity = LiftingGasQuantity;
LiftingGasQuantity = 0;
InjectGas(initialQuantity);
part.OnJustAboutToBeDestroyed += OnPartDestroyed; part.OnJustAboutToBeDestroyed += OnPartDestroyed;
} }
public override void OnLoad(ConfigNode node)
{
base.OnLoad(node);
if (vessel != null)
{
Debug.Log("Loading Balloon part...");
Initialize();
Vector3d worldPos = vessel.GetWorldPos3D();
CelestialBody body = vessel.mainBody;
float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f;
if (externalPressure > 1.0f)
{
vessel.GoOffRails(); // apparently the vessel is on rails on loading, we must take it off rails if it's inside the atmosphere, or it's destroyed by KSP
}
}
}
public override void OnSave(ConfigNode node)
{
base.OnSave(node);
}
public void OnDetached() public void OnDetached()
{ {
Debug.Log("Balloon part detached");
AttachedCase = null; AttachedCase = null;
} }
private void OnPartDestroyed() private void OnPartDestroyed()
{ {
Debug.Log("Balloon part destroyed");
if(AttachedCase != null) if(AttachedCase != null)
AttachedCase.Cut(); AttachedCase.Cut();
@ -135,13 +177,13 @@ namespace Aerostats
// V = 4/3*pi*r^3 // V = 4/3*pi*r^3
Radius = Mathf.Pow(CurrentVolume * 0.75f / Mathf.PI, 0.333f); Radius = Mathf.Pow(CurrentVolume * 0.75f / Mathf.PI, 0.333f);
float scale = Mathf.Max(Radius * 2.0f, 0.1f); Scale = Mathf.Max(Radius * 2.0f, 0.1f);
if(AttachedCase != null) if(AttachedCase != null)
{ {
float dist = Vector3.Distance(AttachedCase.transform.position, transform.position); float dist = Vector3.Distance(AttachedCase.transform.position, transform.position);
scale = Mathf.Min(Mathf.Max(dist, transform.localScale.x * 0.5f) - 0.005f, scale * 0.5f) * 2.0f; // to prevent physics explosion due to interpenetration of objects, don't scale the balloon more than the space available between the case and the balloon (this happens when expanding fast after deploy in vaccum for example) Scale = Mathf.Min(Mathf.Max(dist, transform.localScale.x * 0.5f) - 0.005f, Scale * 0.5f) * 2.0f; // to prevent physics explosion due to interpenetration of objects, don't scale the balloon more than the space available between the case and the balloon (this happens when expanding fast after deploy in vaccum for example)
} }
transform.localScale = new Vector3(scale, scale, scale); transform.localScale = new Vector3(Scale, Scale, Scale);
rigidbody.mass = (EmptyMass + balloonGasMass) * 0.001f; rigidbody.mass = (EmptyMass + balloonGasMass) * 0.001f;
part.mass = rigidbody.mass; part.mass = rigidbody.mass;
@ -182,8 +224,6 @@ namespace Aerostats
float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f; float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f;
float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, body); float airDensity = (float)FlightGlobals.getAtmDensity(externalPressure / 1000.0f, externalTemperature, body);
rigidbody.angularDrag = Mathf.Max(0.5f, 10.0f * externalPressure / GasUtilities.StandardPressure);
if (externalPressure > 0.00001f) if (externalPressure > 0.00001f)
{ {
// lift // lift
@ -198,5 +238,14 @@ namespace Aerostats
rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force); rigidbody.AddForce(-airVelocity.normalized * dragForce / 1000.0f, ForceMode.Force);
} }
} }
private void Update()
{
Vector3d worldPos = vessel.GetWorldPos3D();
CelestialBody body = vessel.mainBody;
float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f;
part.angularDrag = Mathf.Max(0.5f, 10.0f * externalPressure / GasUtilities.StandardPressure);
rigidbody.angularDrag = Mathf.Max(0.5f, 10.0f * externalPressure / GasUtilities.StandardPressure);
}
} }
} }

77
Plugin/ModuleBalloonCase.cs

@ -8,6 +8,13 @@ namespace Aerostats
{ {
public class ModuleBalloonCase : PartModule public class ModuleBalloonCase : PartModule
{ {
public enum BalloonState
{
Packed,
Deployed,
Detached
}
/// <summary> /// <summary>
/// Maximum rate at which gas can be injected in the balloon to fill it, in m^3/s at stp /// Maximum rate at which gas can be injected in the balloon to fill it, in m^3/s at stp
/// </summary> /// </summary>
@ -43,11 +50,17 @@ namespace Aerostats
public float MinimumFillQuantity = 10.0f; public float MinimumFillQuantity = 10.0f;
/// <summary> /// <summary>
/// Length of spring that can not be extended (no force applied under this length) /// Length of spring at rest (no force applied under this length)
/// </summary> /// </summary>
[KSPField(isPersistant = false, guiActive = false)] [KSPField(isPersistant = false, guiActive = false)]
public float SpringRestLength = 10.0f; public float SpringRestLength = 10.0f;
/// <summary>
/// Length at which the spring breaks
/// </summary>
[KSPField(isPersistant = false, guiActive = false)]
public float SpringBreakLength = 50.0f;
/// <summary> /// <summary>
/// Force applied by the spring between the balloon and the vessel, proportional to spring extension, in newton per meter /// Force applied by the spring between the balloon and the vessel, proportional to spring extension, in newton per meter
/// </summary> /// </summary>
@ -57,9 +70,8 @@ namespace Aerostats
[KSPField(isPersistant = false, guiActive = true)] [KSPField(isPersistant = false, guiActive = true)]
public string Status; public string Status;
private bool Deployed; [KSPField(isPersistant = true, guiActive = false)]
public BalloonState State;
private bool Destroyed;
/// <summary> /// <summary>
/// Gas quantity currently inside the balloon /// Gas quantity currently inside the balloon
@ -76,18 +88,18 @@ namespace Aerostats
[KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Deploy balloon", unfocusedRange = 5)] [KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Deploy balloon", unfocusedRange = 5)]
public void Deploy() public void Deploy()
{ {
if (Destroyed || Deployed) if (State != BalloonState.Packed)
return; return;
Deployed = true; State = BalloonState.Deployed;
UnityEngine.Debug.Log("Aerostats: staged"); UnityEngine.Debug.Log("Aerostats: deploying");
Util.PostDebugScreenMessage("staged"); Util.PostDebugScreenMessage("deploying");
AvailablePart avPart = PartLoader.Instance.parts.Single(p => p.name == "heliumBalloon"); AvailablePart avPart = PartLoader.Instance.parts.Single(p => p.name == "heliumBalloon");
var balloonPart = (Part)UnityEngine.Object.Instantiate(avPart.partPrefab); var balloonPart = (Part)UnityEngine.Object.Instantiate(avPart.partPrefab);
var balloonObject = balloonPart.gameObject; var balloonObject = balloonPart.gameObject;
balloonObject.transform.position = part.Rigidbody.position + part.Rigidbody.transform.up * 3.0f; balloonObject.transform.position = part.Rigidbody.position + part.Rigidbody.transform.up * 1.0f;
balloonObject.transform.rotation = part.Rigidbody.rotation; balloonObject.transform.rotation = part.Rigidbody.rotation;
balloonPart.SetHierarchyRoot(balloonPart); balloonPart.SetHierarchyRoot(balloonPart);
balloonPart.vessel = vessel; balloonPart.vessel = vessel;
@ -103,7 +115,7 @@ namespace Aerostats
Balloon.part.vessel.vesselName = vessel.vesselName + " balloon"; Balloon.part.vessel.vesselName = vessel.vesselName + " balloon";
float initialGasQuantity = Mathf.Min(0.1f, part.RequestResource("Helium", MinimumFillQuantity)); float initialGasQuantity = Mathf.Min(0.1f, part.RequestResource("Helium", MinimumFillQuantity));
Balloon.Initialize(this, part.rigidbody.velocity, GasDensity, initialGasQuantity); Balloon.Initialize(this, (Vector3d)part.rigidbody.velocity + Krakensbane.GetFrameVelocity(), GasDensity, initialGasQuantity);
LiftingGasQuantity = Balloon.LiftingGasQuantity; LiftingGasQuantity = Balloon.LiftingGasQuantity;
@ -120,18 +132,19 @@ namespace Aerostats
[KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)] [KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)]
public void Cut() public void Cut()
{ {
if (Destroyed || !Deployed) if (State != BalloonState.Deployed)
return; return;
if (Balloon != null) if(Balloon != null)
{
Balloon.OnDetached(); Balloon.OnDetached();
Balloon = null; Balloon = null;
}
Destroy(Spring); if(Spring != null)
Destroy(Spring);
Spring = null; Spring = null;
part.OnJustAboutToBeDestroyed -= OnPartDestroyed; part.OnJustAboutToBeDestroyed -= OnPartDestroyed;
Destroyed = true; State = BalloonState.Detached;
} }
public override void OnStart(PartModule.StartState state) public override void OnStart(PartModule.StartState state)
@ -149,7 +162,10 @@ namespace Aerostats
private void FixedUpdate() private void FixedUpdate()
{ {
if (Destroyed) if (State == BalloonState.Deployed && Balloon == null)
Cut();
if (State == BalloonState.Detached)
{ {
Status = "separated"; Status = "separated";
VolumeStatus = "-"; VolumeStatus = "-";
@ -161,7 +177,7 @@ namespace Aerostats
Deploy(); Deploy();
} }
if (Deployed) if (State == BalloonState.Deployed)
{ {
float currentMaxQuantity = Balloon.GetCurrentMaxQuantity(); float currentMaxQuantity = Balloon.GetCurrentMaxQuantity();
@ -203,7 +219,12 @@ namespace Aerostats
float springLength = springVec.magnitude; float springLength = springVec.magnitude;
float springForceMag = 0; float springForceMag = 0;
var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius; var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius;
if(springLength > restLength) if(springLength > SpringBreakLength)
{
Cut();
FlightLogger.eventLog.Add("The balloon cable broke due to extreme extension");
}
else if(springLength > restLength)
{ {
float tensingLength = springLength - restLength; float tensingLength = springLength - restLength;
springForceMag = tensingLength * SpringHardness; springForceMag = tensingLength * SpringHardness;
@ -222,16 +243,16 @@ namespace Aerostats
private void LateUpdate() private void LateUpdate()
{ {
if (Destroyed) if (State == BalloonState.Deployed && Balloon == null)
return; Cut();
if (Deployed) if (State != BalloonState.Deployed)
{ return;
var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius;
var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius;
Spring.SetPosition(0, part.transform.position); Spring.SetPosition(0, part.transform.position);
Spring.SetPosition(1, balloonAttachPoint); Spring.SetPosition(1, balloonAttachPoint);
}
} }
} }
} }

Loading…
Cancel
Save