public void Kill() { this.shipContainer.parts.Remove(this); this.shipContainer.PartKilled(); this.Detach(); float single = 4f; Collider2D[] collider2DArray = Physics2D.OverlapCircleAll(base.transform.position, single); for (int i = 0; i < (int)collider2DArray.Length; i++) { Part component = collider2DArray[i].GetComponent <Part>(); if (component != null) { float single1 = Vector2.Distance(base.transform.position, component.transform.position); float single2 = single1 / single; Vector2 _position = component.transform.position - base.transform.position; Vector2 _normalized = 200f * single2 * _position.normalized; component.AddForce(_normalized); } } this.shipContainer.PartDamaged(this.health); if (this.shipChunk.transform.childCount != 1) { UnityEngine.Object.Destroy(base.gameObject); } else { UnityEngine.Object.Destroy(this.shipChunk.gameObject); } }
//Update aerodynamics //Adapted from KSP Trajectories, Kerbal Wind Tunnel, FAR, and AeroGUI void UpdateAerodynamics(ModularFI.ModularFlightIntegrator fi, Part part) { Vessel v = FlightGlobals.ActiveVessel; wx_enabled = Util.getWindBool(); //Is weather enabled? use_climo = Util.useCLIM(); //Are we using the climatology use_point = Util.useWX(); //Are we using MPAS point time-series //Get main vessel and get reference to Kerbin (i.e. celestial body) kerbin = Util.getbody(); //Get wind vector (initialize to zero) Vector3d windVec = Vector3d.zero; if (use_climo) { //Retrieve wind vector from climatology windVec = KerbalWxClimo.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position); } else if (use_point) { //Retrieve wind vector from point forecast windVec = KerbalWxPoint.getWSWind(); // .GetWind(FlightGlobals.currentMainBody, part, rb.position); } //Check to see if root part is in list. If not do not perform aero update. //This avoids updating aerodynamics of parts that have been decoupled and are no longer part of the active vessel. bool hasPart = false; for (int i = 0; i < fi.PartThermalDataCount; i++) { PartThermalData pttd = fi.partThermalDataList[i]; Part ppart = pttd.part; if (ppart == v.rootPart) { hasPart = true; } } if (!hasPart) { return; } //Get position of current vessel double vheight = v.altitude; double vlat = v.latitude; double vlng = v.longitude; double air_pressure; double air_density; double soundSpeed; //Define gamma (i.e. ratio between specific heat of dry air at constant pressure and specific heat of dry air at constant volume: cp/cv). double gamma = 1.4; //Util.Log("MFI wx_enabled: " + wx_enabled+", use_point: "+use_point+", use_climo: "+use_climo); bool inatmos = false; if ((FlightGlobals.ActiveVessel.mainBody == kerbin) && (v.altitude <= 70000) && (wx_enabled)) { if (use_climo) { //Retrieve air pressure/density at vessel location climate_api.wx_aero ptd = _clim_api.getPTD(vlat, vlng, vheight); air_density = ptd.density; air_pressure = ptd.pressure; } else { //Retrieve air pressure/density at vessel location weather_api.wx_aero ptd = _wx_api.getPTD(vheight); air_density = ptd.density; air_pressure = ptd.pressure; } //Compute speed of sound based on air pressure and air density. soundSpeed = Math.Sqrt(gamma * (air_pressure / air_density)); inatmos = true; } else { soundSpeed = v.speedOfSound; } //Get height from surface double hsfc = v.heightFromTerrain; //Determine if vessel is grounded (i.e. on the ground) bool isgrounded = true; if (hsfc >= 10) { isgrounded = false; } //If FAR is present FAR will handle aerodynamic updates or if we're not on Kerbin (i.e. in a different atmosphere) if (part.Modules.Contains <ModuleAeroSurface>() || (part.Modules.Contains("MissileLauncher") && part.vessel.rootPart == part) || (haveFAR) || (v.mainBody != kerbin) || (!inatmos)) { fi.BaseFIUpdateAerodynamics(part); if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA"))) { double drag = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * fi.pseudoReDragMult; float pscal = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier); //Estimate lift force from body lift Vector3 lforce = part.transform.rotation * (part.bodyLiftScalar * part.DragCubes.LiftForce); lforce = Vector3.ProjectOnPlane(lforce, -part.dragVectorDir); } return; } else { fi.BaseFIUpdateAerodynamics(part); //Run base aerodynamic update first (fix bug where parachutes experience multiplicative acceleration) // Get rigid body Rigidbody rb = part.rb; if (rb) { if (part == v.rootPart) { v.mach = 0; } //Retrieve wind vector at vessel location //Vector3d windVec = KWPWind.GetWind(FlightGlobals.currentMainBody, part, rb.position); //Util.Log("MFI windVec: " + windVec + ", use_point: " + use_point + ", use_climo: " + use_climo); //Retrieve world velocity without wind vector Vector3 velocity_nowind = rb.velocity + Krakensbane.GetFrameVelocity(); //Compute mach number double mach_nowind = velocity_nowind.magnitude / soundSpeed; Vector3 drag_sum = Vector3.zero; Vector3 lift_sum = Vector3.zero; if (((!part.DragCubes.None) && (!part.hasLiftModule)) || (part.name.Contains("kerbalEVA"))) { //Estimate Drag force double pseudoreynolds = part.atmDensity * Math.Abs(velocity_nowind.magnitude); double pseudoReDragMult = PhysicsGlobals.DragCurvePseudoReynolds.Evaluate((float)pseudoreynolds); double drag = part.DragCubes.AreaDrag * PhysicsGlobals.DragCubeMultiplier * pseudoReDragMult; float pscal = (float)(part.dynamicPressurekPa * drag * PhysicsGlobals.DragMultiplier); drag_sum += -part.dragVectorDir * pscal; //Estimate lift force from body lift float pbodyLiftScalar = (float)(part.dynamicPressurekPa * part.bodyLiftMultiplier * PhysicsGlobals.BodyLiftMultiplier) * PhysicsGlobals.GetLiftingSurfaceCurve("BodyLift").liftMachCurve.Evaluate((float)part.machNumber); Vector3 lforce2 = part.transform.rotation * (pbodyLiftScalar * part.DragCubes.LiftForce); lforce2 = Vector3.ProjectOnPlane(lforce2, -part.dragVectorDir); lift_sum += lforce2; } //Util.Log("BodyLift Default: " + part.bodyLiftScalar + ", Lift Force: " + lift_force); //Loop through each part module to look for lifting surfaces for (int j = 0; j < part.Modules.Count; ++j) { var m = part.Modules[j]; if (m is ModuleLiftingSurface) { //Initialize force vectors Vector3 lforce = Vector3.zero; Vector3 dforce = Vector3.zero; //Convert kPa to Pa double liftQ = part.dynamicPressurekPa * 1000; ModuleLiftingSurface wing = (ModuleLiftingSurface)m; //Get wing coefficients Vector3 nVel = Vector3.zero; Vector3 liftVector = Vector3.zero; float liftdot; float absdot; wing.SetupCoefficients(velocity_nowind, out nVel, out liftVector, out liftdot, out absdot); //Get Lift/drag force lforce = wing.GetLiftVector(liftVector, liftdot, absdot, liftQ, (float)part.machNumber); dforce = wing.GetDragVector(nVel, absdot, liftQ); if (part.name.Contains("kerbalEVA")) { continue; } drag_sum += dforce; //lift_sum += lforce; if (isgrounded) { lift_sum += lforce; } } } //Retrieve world velocity and subtract off wind vector Vector3 velocity_wind = rb.velocity + Krakensbane.GetFrameVelocity() - windVec; //Compute mach number double mach_wind = velocity_wind.magnitude / soundSpeed; //Set mach number part.machNumber = mach_wind; // *mdiv; if (part == v.rootPart) { fi.mach = mach_wind; } //Get drag and lift forces with wind List <Vector3> total_forces = GetDragLiftForce(fi, part, velocity_wind, windVec, part.machNumber, isgrounded); //Compute difference in drag/lift with and without wind. Vector3 total_drag = total_forces[0] - drag_sum; Vector3 total_lift = total_forces[1] - lift_sum; //Calculate force due to wind Vector3 force = total_lift + total_drag; if (double.IsNaN(force.sqrMagnitude) || (((float)force.magnitude).NearlyEqual(0.0f))) { force = Vector3d.zero; } else { //Adapted from FAR - apply numerical control factor float numericalControlFactor = (float)(part.rb.mass * velocity_wind.magnitude * 0.67 / (force.magnitude * TimeWarp.fixedDeltaTime)); force *= Math.Min(numericalControlFactor, 1); part.AddForce(force); } v.mach = fi.mach; } } }