From 7102f572ed1cd54afb7048eb9ae4c573117d5c96 Mon Sep 17 00:00:00 2001 From: Youen Toupin Date: Sat, 2 Apr 2016 00:20:25 +0200 Subject: [PATCH] - fixed angular drag bug - game load support (wip) --- Plugin/ModuleBalloon.cs | 67 +++++++++++++++++++++++++++----- Plugin/ModuleBalloonCase.cs | 77 +++++++++++++++++++++++-------------- 2 files changed, 107 insertions(+), 37 deletions(-) diff --git a/Plugin/ModuleBalloon.cs b/Plugin/ModuleBalloon.cs index 0b40201..e8761c4 100644 --- a/Plugin/ModuleBalloon.cs +++ b/Plugin/ModuleBalloon.cs @@ -26,9 +26,18 @@ namespace Aerostats /// /// Mass of the empty balloon, in kg /// - 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 Lift { get; private set; } public bool IsVenting { get; private set; } @@ -50,7 +59,13 @@ namespace Aerostats AttachedCase = attachedCase; GasMolarMass = gasDensity / GasUtilities.StpVolumeToMoles; 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) var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); var meshFilter = gameObject.GetComponentInChildren(); @@ -72,22 +87,49 @@ namespace Aerostats gameObject.AddComponent(); rigidbody.mass = EmptyMass * 0.001f; part.mass = rigidbody.mass; - rigidbody.velocity = initialVelocity; + rigidbody.velocity = Velocity - Krakensbane.GetFrameVelocity(); rigidbody.position = transform.position; part.rb = rigidbody; - InjectGas(initialGasQuantity); + float initialQuantity = LiftingGasQuantity; + LiftingGasQuantity = 0; + InjectGas(initialQuantity); 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() { + Debug.Log("Balloon part detached"); AttachedCase = null; } private void OnPartDestroyed() { + Debug.Log("Balloon part destroyed"); if(AttachedCase != null) AttachedCase.Cut(); @@ -135,13 +177,13 @@ namespace Aerostats // V = 4/3*pi*r^3 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) { 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; part.mass = rigidbody.mass; @@ -182,8 +224,6 @@ namespace Aerostats float externalPressure = (float)FlightGlobals.getStaticPressure(worldPos, body) * 1000.0f; 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) { // lift @@ -198,5 +238,14 @@ namespace Aerostats 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); + } } } diff --git a/Plugin/ModuleBalloonCase.cs b/Plugin/ModuleBalloonCase.cs index 70f8d31..4d2b586 100644 --- a/Plugin/ModuleBalloonCase.cs +++ b/Plugin/ModuleBalloonCase.cs @@ -8,6 +8,13 @@ namespace Aerostats { public class ModuleBalloonCase : PartModule { + public enum BalloonState + { + Packed, + Deployed, + Detached + } + /// /// Maximum rate at which gas can be injected in the balloon to fill it, in m^3/s at stp /// @@ -43,11 +50,17 @@ namespace Aerostats public float MinimumFillQuantity = 10.0f; /// - /// 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) /// [KSPField(isPersistant = false, guiActive = false)] public float SpringRestLength = 10.0f; + /// + /// Length at which the spring breaks + /// + [KSPField(isPersistant = false, guiActive = false)] + public float SpringBreakLength = 50.0f; + /// /// Force applied by the spring between the balloon and the vessel, proportional to spring extension, in newton per meter /// @@ -57,9 +70,8 @@ namespace Aerostats [KSPField(isPersistant = false, guiActive = true)] public string Status; - private bool Deployed; - - private bool Destroyed; + [KSPField(isPersistant = true, guiActive = false)] + public BalloonState State; /// /// 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)] public void Deploy() { - if (Destroyed || Deployed) + if (State != BalloonState.Packed) return; - Deployed = true; + State = BalloonState.Deployed; - UnityEngine.Debug.Log("Aerostats: staged"); - Util.PostDebugScreenMessage("staged"); + UnityEngine.Debug.Log("Aerostats: deploying"); + Util.PostDebugScreenMessage("deploying"); AvailablePart avPart = PartLoader.Instance.parts.Single(p => p.name == "heliumBalloon"); var balloonPart = (Part)UnityEngine.Object.Instantiate(avPart.partPrefab); 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; balloonPart.SetHierarchyRoot(balloonPart); balloonPart.vessel = vessel; @@ -103,7 +115,7 @@ namespace Aerostats Balloon.part.vessel.vesselName = vessel.vesselName + " balloon"; 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; @@ -120,18 +132,19 @@ namespace Aerostats [KSPEvent(guiActive = true, active = true, externalToEVAOnly = false, guiActiveUnfocused = true, guiName = "Cut rope", unfocusedRange = 5)] public void Cut() { - if (Destroyed || !Deployed) + if (State != BalloonState.Deployed) return; - if (Balloon != null) - { + if(Balloon != null) Balloon.OnDetached(); - Balloon = null; - } - Destroy(Spring); + Balloon = null; + + if(Spring != null) + Destroy(Spring); Spring = null; + part.OnJustAboutToBeDestroyed -= OnPartDestroyed; - Destroyed = true; + State = BalloonState.Detached; } public override void OnStart(PartModule.StartState state) @@ -149,7 +162,10 @@ namespace Aerostats private void FixedUpdate() { - if (Destroyed) + if (State == BalloonState.Deployed && Balloon == null) + Cut(); + + if (State == BalloonState.Detached) { Status = "separated"; VolumeStatus = "-"; @@ -161,7 +177,7 @@ namespace Aerostats Deploy(); } - if (Deployed) + if (State == BalloonState.Deployed) { float currentMaxQuantity = Balloon.GetCurrentMaxQuantity(); @@ -203,7 +219,12 @@ namespace Aerostats float springLength = springVec.magnitude; float springForceMag = 0; 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; springForceMag = tensingLength * SpringHardness; @@ -222,16 +243,16 @@ namespace Aerostats private void LateUpdate() { - if (Destroyed) - return; + if (State == BalloonState.Deployed && Balloon == null) + Cut(); - if (Deployed) - { - var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius; + if (State != BalloonState.Deployed) + return; + + var balloonAttachPoint = Balloon.rigidbody.position - Balloon.transform.up.normalized * Balloon.Radius; - Spring.SetPosition(0, part.transform.position); - Spring.SetPosition(1, balloonAttachPoint); - } + Spring.SetPosition(0, part.transform.position); + Spring.SetPosition(1, balloonAttachPoint); } } }