public void FixedUpdate() { if (isActive) { FXMonger.Explode(part, part.transform.position, 0f); } }
/// <summary> /// Remove the asteroid after the delay, generating an explosion at the point it disappears from. /// </summary> /// <param name="asteroid">The asteroid to remove.</param> /// <param name="delay">The delay to wait before removing the asteroid.</param> IEnumerator RemoveAfterDelay(Vessel asteroid, float delay) { beingRemoved.Add(asteroid); yield return(new WaitForSeconds(delay)); if (asteroid != null) { // Make an explosion where the impact is going to be and remove the asteroid before it actually impacts, so that KSP doesn't destroy it (regenerating the asteroid is expensive). var impactPosition = asteroid.transform.position + asteroid.srf_velocity * TimeWarp.fixedDeltaTime; FXMonger.ExplodeWithDebris(impactPosition, Math.Pow(asteroid.GetTotalMass(), 0.3d) / 12d, null); asteroid.transform.position += 10000f * upDirection; // Put the asteroid where it won't immediately die on re-activating, since we apparently can't reposition it immediately upon activation. asteroid.SetWorldVelocity(Vector3.zero); // Also, reset its velocity. asteroid.Landed = false; asteroid.Splashed = false; asteroid.gameObject.SetActive(false); beingRemoved.Remove(asteroid); } else { if (BDArmorySettings.DRAW_DEBUG_LABELS) { Debug.Log($"[BDArmory.Asteroids]: Asteroid {asteroid.vesselName} is null, unable to remove."); } } }
void DeploySubmunitions() { missileLauncher.sfAudioSource.PlayOneShot(GameDatabase.Instance.GetAudioClip("BDArmory/Sounds/flare")); FXMonger.Explode(part, transform.position + part.rb.velocity * Time.fixedDeltaTime, 0.1f); deployed = true; if (swapCollidersOnDeploy) { foreach (var col in part.GetComponentsInChildren <Collider>()) { col.enabled = !col.enabled; } } missileLauncher.sfAudioSource.priority = 999; //missileLauncher.explosionSize = 3; foreach (var sub in submunitions) { sub.SetActive(true); sub.transform.parent = null; Vector3 direction = (sub.transform.position - part.transform.position).normalized; Rigidbody subRB = sub.GetComponent <Rigidbody>(); subRB.isKinematic = false; subRB.velocity = part.rb.velocity + (UnityEngine.Random.Range(submunitionMaxSpeed / 10, submunitionMaxSpeed) * direction); Submunition subScript = sub.AddComponent <Submunition>(); subScript.enabled = true; subScript.deployed = true; subScript.sourceVessel = missileLauncher.SourceVessel; subScript.blastForce = missileLauncher.blastPower; subScript.blastHeat = missileLauncher.blastHeat; subScript.blastRadius = missileLauncher.blastRadius; subScript.subExplModelPath = subExplModelPath; subScript.subExplSoundPath = subExplSoundPath; sub.AddComponent <KSPForceApplier>(); } foreach (var fairing in fairings) { Vector3 direction = (fairing.transform.position - part.transform.position).normalized; Rigidbody fRB = fairing.GetComponent <Rigidbody>(); fRB.isKinematic = false; fRB.velocity = part.rb.velocity + ((submunitionMaxSpeed + 2) * direction); fairing.AddComponent <KSPForceApplier>(); fairing.GetComponent <KSPForceApplier>().drag = 0.2f; ClusterBombFairing fairingScript = fairing.AddComponent <ClusterBombFairing>(); fairingScript.deployed = true; fairingScript.sourceVessel = vessel; } part.explosionPotential = 0; missileLauncher.HasFired = false; part.temperature = part.maxTemp + 10; }
private void UnAnchor() { isAnchored = false; part.mass = oldMass; part.CoMOffset = oldOffset; //part.GetComponent<Rigidbody>().isKinematic = false; FXMonger.Explode(part, anchorPoint.position, 0f); Events["Anchor"].guiActive = true; Events["UnAnchor"].guiActive = false; }
private void Anchor() { isAnchored = true; oldMass = part.mass; oldOffset = part.CoMOffset; part.mass = anchorMass; part.CoMOffset = new Vector3(0, offset, 0); //part.GetComponent<Rigidbody>().isKinematic = true; FXMonger.Explode(part, anchorPoint.position, 0f); Events["Anchor"].guiActive = false; Events["UnAnchor"].guiActive = true; }
private IEnumerator <YieldInstruction> self_destruct(float countdown) { var endUT = Planetarium.GetUniversalTime() + countdown; while (Planetarium.GetUniversalTime() < endUT) { yield return(null); } FXMonger.Explode(part, vessel.GetWorldPos3D(), explosionPower(part.Rigidbody)); yield return(null); part.Die(); }
private IEnumerator <YieldInstruction> self_destruct() { var endUT = Planetarium.GetUniversalTime() + selfDestruct; while (Planetarium.GetUniversalTime() < endUT) { yield return(null); } FXMonger.Explode(part, vessel.GetWorldPos3D(), selfDestructPower); yield return(null); part.Die(); }
private void ApplySplashEffect(double depth, Rigidbody body) { if (depth > 1) { return; } float mag = body.velocity.magnitude * 0.02f; if (mag > 0.05) { FXMonger.Splash(part.transform.position, mag); } }
protected void detonatePulse() { if (fuelSupply == null) { return; } totalVesselMass = 0f; foreach (Part current in this.vessel.parts) { totalVesselMass += current.mass; } currentUnit = fuelSupply.getUnit(false); if (currentUnit != null) { float neededCharge = currentUnit.getEnergy() / (activationRatio * efficiency); float rechargeAmount = -currentUnit.getEnergy() / efficiency; float charge = getECInBank(); Debug.Log(charge + ":" + neededCharge); if (charge < neededCharge) { Debug.Log(charge + " " + neededCharge + " " + (charge - neededCharge)); return; } fuelSupply.getUnit(true); consumeCharge(neededCharge); RequestResource("ElectricCharge", rechargeAmount); // add velocity this.vessel.ChangeWorldVelocity(base.transform.up * (this.currentUnit.getImpulse() / totalVesselMass)); base.rigidbody.AddRelativeForce(new Vector3(0f, (this.currentUnit.getImpulse() / totalVesselMass), 0f), ForceMode.Force); if (this.Modules.Contains("HeatTransfer")) { this.temperature += currentUnit.getEnergy() / 50000; } // FX: make explosion sound this.explosionGroup.Power = 10; this.explosionGroup.Burst(); base.gameObject.audio.pitch = 1f; base.gameObject.audio.PlayOneShot(this.explosionGroup.sfx); //TODO replace this with a jet of plasma Vector3d groundZero = new Vector3d(base.transform.FindChild("model").localPosition.x, base.transform.FindChild("model").localPosition.y, base.transform.FindChild("model").localPosition.z); groundZero = base.transform.FindChild("model").TransformPoint(groundZero); FXMonger.Explode(this, groundZero, 10); } }
private void ApplyAeroStressFailure() { bool failureOccured = false; if (part.Modules.Contains <ModuleProceduralFairing>()) { var fairing = part.Modules.GetModule <ModuleProceduralFairing>(); fairing.ejectionForce = 0.5f; fairing.DeployFairing(); failureOccured = true; } List <Part> children = part.children; // ReSharper disable once ForCanBeConvertedToForeach -> decouple modifies collection for (int i = 0; i < children.Count; i++) { Part child = children[i]; child.decouple(25); failureOccured = true; } if (part.parent) { part.decouple(25); failureOccured = true; } if (!failureOccured || !vessel) { return; } vessel.SendMessage("AerodynamicFailureStatus"); string msg = Localizer.Format("FARFlightLogAeroFailure", KSPUtil.PrintTimeStamp(FlightLogger.met), part.partInfo.title); FlightLogger.eventLog.Add(msg); if (FARDebugValues.aeroFailureExplosions) { FXMonger.Explode(part, partTransform.position, (float)projectedArea.totalArea * 0.0005f); } }
private void ApplyAeroStressFailure() { bool failureOccured = false; if (part.Modules.Contains("ModuleProceduralFairing")) { ModuleProceduralFairing fairing = (ModuleProceduralFairing)part.Modules["ModuleProceduralFairing"]; fairing.ejectionForce = 0.5f; fairing.DeployFairing(); failureOccured = true; } List <Part> children = part.children; for (int i = 0; i < children.Count; i++) { Part child = children[i]; child.decouple(25); failureOccured = true; } if (part.parent) { part.decouple(25); failureOccured = true; } if (failureOccured) { if (vessel) { vessel.SendMessage("AerodynamicFailureStatus"); string msg = String.Format("[{0:D2}:{1:D2}:{2:D2}] {3} failed due to aerodynamic stresses.", FlightLogger.met_hours, FlightLogger.met_mins, FlightLogger.met_secs, part.partInfo.title); FlightLogger.eventLog.Add(msg); if (FARDebugValues.aeroFailureExplosions) { FXMonger.Explode(part, partTransform.position, (float)projectedArea.totalArea * 0.0005f); } } } }
IEnumerator <YieldInstruction> launch_complete_construct() { if (!HighLogic.LoadedSceneIsFlight) { yield break; } while (!FlightGlobals.ready) { yield return(null); } vessel_spawner.BeginLaunch(); //hide UI GameEvents.onHideUI.Fire(); yield return(null); //save the game GroundConstructionScenario.SaveGame(kit.Name + "-before_launch"); yield return(null); yield return(new WaitForFixedUpdate()); //load ship construct and launch it var construct = kit.LoadConstruct(); if (construct == null) { Utils.Log("Unable to load ShipConstruct {}. " + "This usually means that some parts are missing " + "or some modules failed to initialize.", kit.Name); Utils.Message("Something went wrong. Constructed ship cannot be launched."); GameEvents.onShowUI.Fire(); vessel_spawner.AbortLaunch(); yield break; } model.gameObject.SetActive(false); FXMonger.Explode(part, part.partTransform.position, 0); yield return(StartCoroutine(launch(construct))); GameEvents.onShowUI.Fire(); part.Die(); }
private bool CheckDieOnHighVelocity(Rigidbody body) { Vector3d velVector = body.velocity + Krakensbane.GetFrameVelocityV3f(); double vertVec = Vector3d.Dot(velVector, vessel.upAxis); if (Math.Abs(vertVec) > part.crashTolerance * vertCrashTolFactor) { GameEvents.onCrashSplashdown.Fire(new EventReport(FlightEvents.SPLASHDOWN_CRASH, part, part.partInfo.title, "", 0, "")); FXMonger.Splash(part.transform.position, 10); part.Die(); return(true); } double horizVel = (velVector - vertVec * vessel.upAxis).magnitude; if (horizVel > part.crashTolerance * horizCrashTolFactor) { GameEvents.onCrashSplashdown.Fire(new EventReport(FlightEvents.SPLASHDOWN_CRASH, part, part.partInfo.title, "", 0, "")); FXMonger.Splash(part.transform.position, 10); part.Die(); return(true); } return(false); }
protected virtual void on_vessel_loaded(Vessel vsl) { FXMonger.Explode(part, part.partTransform.position, 0); ShowDeployHint = false; }
public Vector3d RunDragCalculation(Vector3d velocity, double MachNumber, double rho, double failureForceScaling) { if (isShielded) { Cl = Cd = Cm = 0; return(Vector3d.zero); } double v_scalar = velocity.magnitude; if (v_scalar > 0.1) //Don't Bother if it's not moving or in space { CoDshift = Vector3d.zero; Cd = 0; Vector3d velocity_normalized = velocity / v_scalar; Vector3d upVector = part_transform.TransformDirection(localUpVector); perp = Vector3d.Cross(upVector, velocity).normalized; liftDir = Vector3d.Cross(velocity, perp).normalized; Vector3d local_velocity = part_transform.InverseTransformDirection(velocity_normalized); DragModel(local_velocity, MachNumber, rho); double qS = 0.5 * rho * v_scalar * v_scalar * S; //dynamic pressure, q Vector3d D = velocity_normalized * (-qS * Cd); //drag Vector3d L = liftDir * (qS * Cl); Vector3d force = (L + D) * 0.001; double force_scalar = force.magnitude; currentDrag = (float)force_scalar; Vector3d moment = perp * (qS * Cm * 0.001); Rigidbody rb = part.Rigidbody; if (HighLogic.LoadedSceneIsFlight && (object)rb != null) { if (rb.angularVelocity.sqrMagnitude != 0) { Vector3d rot = Vector3d.Exclude(velocity_normalized, rb.angularVelocity); //This prevents aerodynamic damping a spinning object if its spin axis is aligned with the velocity axis rot *= (-0.00001 * qS); moment += rot; } } //Must handle aero-structural failure before transforming CoD pos and adding pitching moment to forces or else parts with blunt body drag fall apart too easily if (Math.Abs(Vector3d.Dot(force, upVector)) > YmaxForce * failureForceScaling || Vector3d.Exclude(upVector, force).magnitude > XZmaxForce * failureForceScaling) { if (part.parent && !vessel.packed) { part.SendEvent("AerodynamicFailureStatus"); FlightLogger.eventLog.Add("[" + FARMathUtil.FormatTime(vessel.missionTime) + "] Joint between " + part.partInfo.title + " and " + part.parent.partInfo.title + " failed due to aerodynamic stresses."); part.decouple(25); if (FARDebugValues.aeroFailureExplosions) { FXMonger.Explode(part, GetCoDWithoutMomentShift(), 5); } } } globalCoDShift = Vector3d.Cross(force, moment) / (force_scalar * force_scalar); if (double.IsNaN(force_scalar) || double.IsNaN(moment.sqrMagnitude) || double.IsNaN(globalCoDShift.sqrMagnitude)) { Debug.LogWarning("FAR Error: Aerodynamic force = " + force.magnitude + " Aerodynamic moment = " + moment.magnitude + " CoD Local = " + CoDshift.magnitude + " CoD Global = " + globalCoDShift.magnitude + " " + part.partInfo.title); force = moment = CoDshift = globalCoDShift = Vector3.zero; return(force); } double numericalControlFactor = (rb.mass * v_scalar * 0.67) / (force_scalar * TimeWarp.fixedDeltaTime); force *= Math.Min(numericalControlFactor, 1); //part.Rigidbody.AddTorque(moment); return(force); } else { return(Vector3d.zero); } }
void Update() { if (FlightGlobals.ActiveVessel == null) { return; } if (FlightGlobals.currentMainBody != _body) { return; } // Is the vessel within the sphere of influence? if (FlightGlobals.ship_altitude < influenceAltitude) { if (MapView.MapIsEnabled) { MapView.ExitMapView(); } if (FlightGlobals.ActiveVessel.GetComponent <CameraShake>() == null) { FlightGlobals.ActiveVessel.gameObject.AddComponent <CameraShake>().ShakeAmount = 2; if (!String.IsNullOrEmpty(entryMessage)) { ScreenMessages.PostScreenMessage(entryMessage, entryMsgDuration); } } } else { CameraShake shake = FlightGlobals.ActiveVessel.GetComponent <CameraShake>(); if (shake != null) { Destroy(shake); if (!String.IsNullOrEmpty(exitMessage)) { ScreenMessages.PostScreenMessage(exitMessage, exitMsgDuration); } } return; } // Are we within the jump range? if (FlightGlobals.ship_altitude < jumpMaxAltitude && FlightGlobals.ship_altitude > jumpMinAltitude) { // Disable the log output PDebug.DebugLevel l = PDebug.debugLevel; PDebug.debugLevel = PDebug.DebugLevel.None; for (Int32 i = 0; i < 5; i++) { Vector3 random = UnityEngine.Random.onUnitSphere; GameObject effect = FXMonger.Splash( FlightGlobals.ship_position + random * 50, 1000).effectObj; effect.transform.localScale = Vector3.one * 10; effect.transform.up = -random; } // Update the FXMonger FXMonger[] mongers = FindObjectsOfType <FXMonger>(); for (Int32 i = 0; i < mongers.Length; i++) { mongers[i].SendMessage("LateUpdate"); } PDebug.debugLevel = l; // If the Pe is within the jump range, jump if (FlightGlobals.ship_altitude - _lastAlt > 0) { // Move the vessel to the new orbit if (FlightGlobals.ActiveVessel.GetComponent <JumpMarker>() == null) { MakeOrbit(FlightGlobals.ActiveVessel.orbitDriver, _partner); FlightGlobals.ActiveVessel.gameObject.AddComponent <JumpMarker>(); } } } else { // Heat up the vessel for (Int32 i = 0; i < FlightGlobals.ActiveVessel.Parts.Count; i++) { FlightGlobals.ActiveVessel[i].temperature += heatRate; } // Remove the jump marker if neccessary JumpMarker jump = FlightGlobals.ActiveVessel.GetComponent <JumpMarker>(); if (jump != null) { Destroy(jump); } } _lastAlt = FlightGlobals.ship_altitude; }
protected override void on_vessel_launched(Vessel vsl) { base.on_vessel_launched(vsl); if (recipient_node != null) { var construction_node_pos = part.partTransform.TransformPoint(construction_node.position); var construction_part = recipient_node.owner; var docking_node = kit.GetDockingNode(vsl, ConstructDockingNode); if (docking_node == null) { Utils.Message( "No suitable attachment node found in \"{0}\" to dock it to the {1}", vsl.GetDisplayName(), construction_part.Title()); return; } var docking_offset = docking_node.owner.partTransform.TransformPoint(docking_node.position) - construction_node_pos; FXMonger.Explode(part, construction_node_pos, 0); var docking_part = docking_node.owner; this.Log("Docking {} to {}", docking_part.GetID(), construction_part.GetID()); // vessels' position and rotation construction_part.vessel.SetPosition(construction_part.vessel.transform.position, true); construction_part.vessel.SetRotation(construction_part.vessel.transform.rotation); docking_part.vessel.SetPosition( docking_part.vessel.transform.position - docking_offset, true); docking_part.vessel.SetRotation(docking_part.vessel.transform.rotation); construction_part.vessel.IgnoreGForces(10); docking_part.vessel.IgnoreGForces(10); if (construction_part == part.parent) { part.decouple(); } else { construction_part.decouple(); } recipient_node.attachedPart = docking_part; recipient_node.attachedPartId = docking_part.flightID; docking_node.attachedPart = construction_part; docking_node.attachedPartId = construction_part.flightID; docking_part.Couple(construction_part); // manage docking ports, if any foreach (var port in construction_part.FindModulesImplementing <ModuleDockingNode>()) { if (port.referenceNode == recipient_node) { port.dockedPartUId = docking_part.persistentId; port.fsm.StartFSM(port.st_preattached); break; } } foreach (var port in docking_part.FindModulesImplementing <ModuleDockingNode>()) { if (port.referenceNode == docking_node) { port.dockedPartUId = construction_part.persistentId; port.fsm.StartFSM(port.st_preattached); break; } } // add fuel lookups construction_part.fuelLookupTargets.Add(docking_part); docking_part.fuelLookupTargets.Add(construction_part); GameEvents.onPartFuelLookupStateChange.Fire( new GameEvents.HostedFromToAction <bool, Part>(true, docking_part, construction_part)); FlightGlobals.ForceSetActiveVessel(construction_part.vessel); FlightInputHandler.SetNeutralControls(); GameEvents.onVesselWasModified.Fire(construction_part.vessel); recipient_node = null; this.Log("Docked {} to {}, new vessel {}", docking_part, construction_part, construction_part.vessel.GetID()); } }
private bool updateScaffold(float newDeploymentProgress) { if (newDeploymentProgress < 0) { if (segmentScaffold != null) { if (!removeDockingNode()) { return(false); } if (HighLogic.LoadedSceneIsFlight) { FXMonger.Explode(part, segmentScaffold.transform.position, 0); } Destroy(segmentScaffold); segmentScaffold = null; resetRendererCaches(); } } else { if (segmentScaffold == null) { this.Debug($"Creating new scaffold"); var attachmentPoint = getAttachmentTransform(); if (attachmentPoint == null) { return(false); } segmentScaffold = Instantiate(segmentScaffoldPrefab, attachmentPoint, false); segmentScaffold.transform.localPosition = Vector3.zero; segmentScaffold.transform.localRotation = Quaternion.identity; if (!string.IsNullOrEmpty(constructionPortTransformPrefabName)) { var dockingNode = Part.FindHeirarchyTransform(segmentScaffold.transform, constructionPortTransformPrefabName); if (dockingNode != null) { dockingNode.gameObject.name = constructionPortTransformName; } else { this.Error($"Unable to find {constructionPortTransformPrefabName} transform"); } } segmentScaffold.SetActive(true); resetRendererCaches(); #if DEBUG this.Debug($"Scaffold instance tree: {DebugUtils.formatTransformTree(segmentScaffold.transform)}"); #endif } if (newDeploymentProgress < 1 && !removeDockingNode()) { return(false); } if (newDeploymentProgress >= 1) { newDeploymentProgress = 1; } segmentScaffold.transform.localScale = Vector3.Lerp(ScaffoldStartScale, Vector3.one, newDeploymentProgress); segmentScaffold.transform.hasChanged = true; } DeploymentProgress = newDeploymentProgress; if (DeploymentProgress >= 1) { this.Debug($"Deployment finished. Docking node: {constructionPort.GetID()}"); setupDockingNode(); } return(true); }
void DeploySubmunitions() { missileLauncher.sfAudioSource.PlayOneShot(GameDatabase.Instance.GetAudioClip("BDArmory/Sounds/flare")); FXMonger.Explode(part, transform.position + part.rb.velocity * Time.fixedDeltaTime, 0.1f); deployed = true; if (swapCollidersOnDeploy) { IEnumerator <Collider> col = part.GetComponentsInChildren <Collider>().AsEnumerable().GetEnumerator(); while (col.MoveNext()) { if (col.Current == null) { continue; } col.Current.enabled = !col.Current.enabled; } col.Dispose(); } missileLauncher.sfAudioSource.priority = 999; List <GameObject> .Enumerator sub = submunitions.GetEnumerator(); while (sub.MoveNext()) { if (sub.Current == null) { continue; } sub.Current.SetActive(true); sub.Current.transform.parent = null; Vector3 direction = (sub.Current.transform.position - part.transform.position).normalized; Rigidbody subRB = sub.Current.GetComponent <Rigidbody>(); subRB.isKinematic = false; subRB.velocity = part.rb.velocity + Krakensbane.GetFrameVelocityV3f() + (UnityEngine.Random.Range(submunitionMaxSpeed / 10, submunitionMaxSpeed) * direction); Submunition subScript = sub.Current.AddComponent <Submunition>(); subScript.enabled = true; subScript.deployed = true; subScript.blastForce = missileLauncher.GetTntMass(); subScript.blastHeat = missileLauncher.blastHeat; subScript.blastRadius = missileLauncher.GetBlastRadius(); subScript.subExplModelPath = subExplModelPath; subScript.subExplSoundPath = subExplSoundPath; sub.Current.AddComponent <KSPForceApplier>(); } List <GameObject> .Enumerator fairing = fairings.GetEnumerator(); while (fairing.MoveNext()) { if (fairing.Current == null) { continue; } Vector3 direction = (fairing.Current.transform.position - part.transform.position).normalized; Rigidbody fRB = fairing.Current.GetComponent <Rigidbody>(); fRB.isKinematic = false; fRB.velocity = part.rb.velocity + Krakensbane.GetFrameVelocityV3f() + ((submunitionMaxSpeed + 2) * direction); fairing.Current.AddComponent <KSPForceApplier>(); fairing.Current.GetComponent <KSPForceApplier>().drag = 0.2f; ClusterBombFairing fairingScript = fairing.Current.AddComponent <ClusterBombFairing>(); fairingScript.deployed = true; } fairing.Dispose(); part.explosionPotential = 0; missileLauncher.HasFired = false; part.Destroy(); }
public void FixedUpdate() { if (!HighLogic.LoadedSceneIsFlight) { return; } if (vessel.mainBody.ocean && part.GetComponent <Rigidbody>() != null) { if (part.partBuoyancy != null) { Destroy(part.partBuoyancy); } double partAltitude = Vector3d.Distance(forcePoint.position, vessel.mainBody.position) - vessel.mainBody.Radius - buoyancyVerticalOffset; if (partAltitude < 0d) { // float code double floatMultiplier = Math.Max(0d, -Math.Max(partAltitude, -buoyancyRange)) / buoyancyRange; if (floatMultiplier > 0f) { Vector3d up = (this.vessel.GetComponent <Rigidbody>().position - this.vessel.mainBody.position).normalized; Vector3d uplift = up * buoyancyForce * floatMultiplier; //float relativeDirection = Vector3.Dot(vessel.GetComponent<Rigidbody>().velocity.normalized, up); if (vessel.verticalSpeed < maxVerticalSpeed) // || relativeDirection < 0f) // if you are going down, apply force regardless, of going up, limit up speed { this.part.GetComponent <Rigidbody>().AddForceAtPosition(uplift, forcePoint.position); } } // set water drag part.GetComponent <Rigidbody>().drag = dragInWater; // splashed status splashed = true; part.WaterContact = true; part.vessel.Splashed = true; // part destruction if (base.GetComponent <Rigidbody>().velocity.magnitude > waterImpactTolerance) { GameEvents.onCrashSplashdown.Fire(new EventReport(FlightEvents.SPLASHDOWN_CRASH, this.part, this.part.partInfo.title, "ocean", 0, "FSbuoyancy: Hit the water too hard")); this.part.Die(); return; } //FX if (splashFXEnabled) { splashTimer -= Time.deltaTime; if (splashTimer <= 0f) { splashTimer = splashCooldown; if (base.GetComponent <Rigidbody>().velocity.magnitude > 6f && partAltitude > -buoyancyRange) // don't splash if you are deep in the water or going slow { if (Vector3.Distance(base.transform.position, FlightGlobals.camera_position) < 500f) { FXMonger.Splash(base.transform.position, base.GetComponent <Rigidbody>().velocity.magnitude / 50f); } } } } } else { if (splashed) { splashed = false; // set air drag part.GetComponent <Rigidbody>().drag = 0f; part.WaterContact = false; part.vessel.checkSplashed(); } } } }
protected virtual void on_vessel_loaded(Vessel vsl) => FXMonger.Explode(part, part.partTransform.position, 0);
IEnumerable recycle( Part p, float efficiency, bool discard_excess_resources, HashSet <uint> skip_craftIDs = null ) { // first handle children var skip = false; if (p.children.Count > 0) { for (int i = p.children.Count - 1; i >= 0; i--) { foreach (var child_result in recycle(p.children[i], efficiency, discard_excess_resources, skip_craftIDs)) { if (child_result is SkipPart) { skip = true; } else { yield return(child_result); if (child_result == null) { yield break; } } } } } // decide if we have to skip this part (and thus all the parents) if (p.protoModuleCrew.Count > 0) { recycle_report.Add($"Skipped '{p.partInfo.title}' because the crew was inside"); skip = true; } else { skip |= skip_craftIDs != null && skip_craftIDs.Contains(p.craftID); } if (!skip) { // if not, collect its resources if we can, else skip it anyway foreach (var res in p.Resources) { if (res.amount > 0) { if (transfer_resource(p, res.info.id, res.amount, discard_excess_resources) != TransferState.FULL) { skip = true; } } } } if (skip) { yield return(new SkipPart()); yield break; } // recycle the part that is now empty GetRecycleInfo(p, efficiency, out var req_a, out var req_c); var result = recycle_part(p, discard_excess_resources, req_a, req_c); if (result > TransferState.ZERO) { FXMonger.Explode(p, p.transform.position, 0); p.Die(); } // wait for some time before recycle next one, or break the recycling if something went wrong if (result == TransferState.NO_EC) { yield return(new SkipPart()); } else if (result == TransferState.FULL) { yield return(new WaitForSeconds(GLB.RecycleRate)); } else { yield return(null); } }