Example #1
0
        private void ExecutePartBlastEvent(PartBlastHitEvent eventToExecute)
        {
            if (eventToExecute.Part == null || eventToExecute.Part.Rigidbody == null || eventToExecute.Part.vessel == null || eventToExecute.Part.partInfo == null)
            {
                return;
            }

            try
            {
                Part      part         = eventToExecute.Part;
                Rigidbody rb           = part.Rigidbody;
                var       realDistance = eventToExecute.Distance;

                if (!eventToExecute.IsNegativePressure)
                {
                    BlastInfo blastInfo =
                        BlastPhysicsUtils.CalculatePartBlastEffects(part, realDistance,
                                                                    part.vessel.totalMass * 1000f, Power, Range);

                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log(
                            "[BDArmory]: Executing blast event Part: {" + part.name + "}, " +
                            " VelocityChange: {" + blastInfo.VelocityChange + "}," +
                            " Distance: {" + realDistance + "}," +
                            " TotalPressure: {" + blastInfo.TotalPressure + "}," +
                            " Damage: {" + blastInfo.Damage + "}," +
                            " EffectiveArea: {" + blastInfo.EffectivePartArea + "}," +
                            " Positive Phase duration: {" + blastInfo.PositivePhaseDuration + "}," +
                            " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                            " TimeIndex: {" + TimeIndex + "}," +
                            " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                            " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                    }

                    // Add Reverse Negative Event
                    ExplosionEvents.Enqueue(new PartBlastHitEvent()
                    {
                        Distance           = Range - realDistance,
                        Part               = part,
                        TimeToImpact       = 2 * (Range / ExplosionVelocity) + (Range - realDistance) / ExplosionVelocity,
                        IsNegativePressure = true,
                        NegativeForce      = blastInfo.VelocityChange * 0.25f
                    });

                    AddForceAtPosition(rb,
                                       (eventToExecute.HitPoint + part.rb.velocity * TimeIndex - Position).normalized *
                                       blastInfo.VelocityChange *
                                       BDArmorySettings.EXP_IMP_MOD,
                                       eventToExecute.HitPoint + part.rb.velocity * TimeIndex);

                    var damage = part.AddExplosiveDamage(blastInfo.Damage, Caliber, ExplosionSource);
                    if (BDArmorySettings.BATTLEDAMAGE)
                    {
                        Misc.BattleDamageHandler.CheckDamageFX(part, 50, 0.5f, true, SourceVesselName, eventToExecute.Hit);
                    }

                    // Update scoring structures
                    switch (ExplosionSource)
                    {
                    case ExplosionSourceType.Bullet:
                    case ExplosionSourceType.Missile:
                        var aName = eventToExecute.SourceVesselName; // Attacker
                        var tName = part.vessel.GetName();           // Target
                        if (aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(tName) && BDACompetitionMode.Instance.Scores.ContainsKey(aName))
                        {
                            var tData = BDACompetitionMode.Instance.Scores[tName];
                            // Track damage
                            switch (ExplosionSource)
                            {
                            case ExplosionSourceType.Bullet:
                                if (tData.damageFromBullets.ContainsKey(aName))
                                {
                                    tData.damageFromBullets[aName] += damage;
                                }
                                else
                                {
                                    tData.damageFromBullets.Add(aName, damage);
                                }
                                if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                {
                                    BDAScoreService.Instance.TrackDamage(aName, tName, damage);
                                }
                                break;

                            case ExplosionSourceType.Missile:
                                if (tData.damageFromMissiles.ContainsKey(aName))
                                {
                                    tData.damageFromMissiles[aName] += damage;
                                }
                                else
                                {
                                    tData.damageFromMissiles.Add(aName, damage);
                                }
                                if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                {
                                    BDAScoreService.Instance.TrackMissileDamage(aName, tName, damage);
                                }
                                break;

                            default:
                                break;
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }
                else
                {
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log(
                            "[BDArmory]: Executing blast event Part: {" + part.name + "}, " +
                            " VelocityChange: {" + eventToExecute.NegativeForce + "}," +
                            " Distance: {" + realDistance + "}," +
                            " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                            " TimeIndex: {" + TimeIndex + "}," +
                            " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                            " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                    }
                    AddForceAtPosition(rb, (Position - part.transform.position).normalized * eventToExecute.NegativeForce * BDArmorySettings.EXP_IMP_MOD * 0.25f, part.transform.position);
                }
            }
            catch
            {
                // ignored due to depending on previous event an object could be disposed
            }
        }
Example #2
0
        void Detonate()                                                                                          //borrowed from Stockalike Project Orion
        {
            if (hasDetonated || FlightGlobals.currentMainBody == null || VesselSpawner.Instance.vesselsSpawning) // Don't trigger on scene changes or during spawning.
            {
                return;
            }
            if (BDArmorySettings.DRAW_DEBUG_LABELS)
            {
                Debug.Log("[BDArmory.NukeTest]: Running Detonate() on nerva in vessel " + Sourcevessel);
            }
            //affect any nearby parts/vessels that aren't the source vessel

            Dictionary <string, int> vesselsHitByMissiles = new Dictionary <string, int>();

            using (var blastHits = Physics.OverlapSphere(part.transform.position, thermalRadius, 9076737).AsEnumerable().GetEnumerator())
            {
                partsHit.Clear();
                while (blastHits.MoveNext())
                {
                    if (blastHits.Current == null)
                    {
                        continue;
                    }
                    if (blastHits.Current.gameObject == FlightGlobals.currentMainBody.gameObject)
                    {
                        continue;                                                                           // Ignore terrain hits.
                    }
                    Part partHit = blastHits.Current.GetComponentInParent <Part>();
                    if (partsHit.Contains(partHit))
                    {
                        continue;                             // Don't hit the same part multiple times.
                    }
                    partsHit.Add(partHit);
                    if (partHit != null && partHit.mass > 0)
                    {
                        var   distToG0      = Math.Max((part.transform.position - partHit.transform.position).magnitude, 1f);
                        float radiativeArea = !double.IsNaN(partHit.radiativeArea) ? (float)partHit.radiativeArea : partHit.GetArea();
                        if (BDArmorySettings.DRAW_DEBUG_LABELS && double.IsNaN(partHit.radiativeArea))
                        {
                            Debug.Log("[BDArmory.NukeTest]: radiative area of part " + partHit + " was NaN, using approximate area " + radiativeArea + " instead.");
                        }
                        //if (partHit.vessel != this.vessel)
                        if (partHit != part)
                        {
                            partHit.skinTemperature += fluence * 3370000000 / (4 * Math.PI * Math.Pow(distToG0, 2.0)) * radiativeArea / 2; // Fluence scales linearly w/ yield, 1 Kt will produce between 33 TJ and 337 kJ at 0-1000m,
                        } // everything gets heated via atmosphere

                        Ray        LoSRay = new Ray(part.transform.position, partHit.transform.position - part.transform.position);
                        RaycastHit hit;
                        if (Physics.Raycast(LoSRay, out hit, distToG0, 9076737)) // only add impulse to parts with line of sight to detonation
                        {
                            KerbalEVA eva         = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                            Part      p           = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>();
                            float     blastDamage = 100;
                            if (p == partHit)
                            {
                                //if (p.vessel != this.vessel)
                                if (p != part)
                                {
                                    // Forces
                                    if (p.rb != null && p.rb.mass > 0) // Don't apply forces to physicsless parts.
                                    {
                                        var blastImpulse = Mathf.Pow(3.01f * 1100f / distToG0, 1.25f) * 6.894f * lastValidAtmDensity * yieldCubeRoot * radiativeArea / 3f;
                                        // Math.Pow(Math.Pow(Math.Pow(9.54e-3 * 2200.0 / distToG0, 1.95), 4.0) + Math.Pow(Math.Pow(3.01 * 1100.0 / distToG0, 1.25), 4.0), 0.25) * 6.894 * vessel.atmDensity * Math.Pow(yield, 1.0 / 3.0) * partHit.radiativeArea / 3.0; //assuming a 0.05 kT yield
                                        if (float.IsNaN(blastImpulse))
                                        {
                                            Debug.LogWarning("[BDArmory.NukeTest]: blast impulse is NaN. distToG0: " + distToG0 + ", vessel: " + vessel + ", atmDensity: " + lastValidAtmDensity + ", yield^(1/3): " + yieldCubeRoot + ", partHit: " + partHit + ", radiativeArea: " + radiativeArea);
                                        }
                                        else
                                        {
                                            if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                            {
                                                Debug.Log("[BDArmory.NukeTest]: Applying " + blastImpulse.ToString("0.0") + " impulse to " + p + " of mass " + p.mass + " at distance " + distToG0 + "m");
                                            }
                                            p.rb.AddForceAtPosition((partHit.transform.position - part.transform.position).normalized * (float)blastImpulse, partHit.transform.position, ForceMode.Impulse);
                                        }
                                    }

                                    // Damage
                                    blastDamage = ((float)((yield * 3370000000) / (4f * Mathf.PI * distToG0 * distToG0) * (radiativeArea / 2f)));
                                    if (float.IsNaN(blastDamage))
                                    {
                                        Debug.LogWarning("[BDArmory.NukeTest]: blast damage is NaN. distToG0: " + distToG0 + ", yield: " + yield + ", part: " + partHit + ", radiativeArea: " + radiativeArea);
                                        continue;
                                    }
                                    p.AddExplosiveDamage(blastDamage, 100, ExplosionSourceType.Missile);

                                    // Scoring
                                    var aName = Sourcevessel;       // Attacker
                                    var tName = p.vessel.GetName(); // Target
                                    if (tName != null && aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(tName) && BDACompetitionMode.Instance.Scores.ContainsKey(aName))
                                    {
                                        // Part hit counts
                                        if (BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts.ContainsKey(aName))
                                        {
                                            ++BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts[aName];
                                        }
                                        else
                                        {
                                            BDACompetitionMode.Instance.Scores[tName].missilePartDamageCounts[aName] = 1;
                                        }
                                        if (!BDACompetitionMode.Instance.Scores[tName].everyoneWhoHitMeWithMissiles.Contains(aName))
                                        {
                                            BDACompetitionMode.Instance.Scores[tName].everyoneWhoHitMeWithMissiles.Add(aName);
                                        }
                                        ++BDACompetitionMode.Instance.Scores[aName].totalDamagedPartsDueToMissiles;
                                        BDACompetitionMode.Instance.Scores[tName].lastMissileHitTime             = Planetarium.GetUniversalTime();
                                        BDACompetitionMode.Instance.Scores[tName].lastPersonWhoHitMeWithAMissile = aName;
                                        if (vesselsHitByMissiles.ContainsKey(tName))
                                        {
                                            ++vesselsHitByMissiles[tName];
                                        }
                                        else
                                        {
                                            vesselsHitByMissiles[tName] = 1;
                                        }
                                        if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                        {
                                            BDAScoreService.Instance.TrackMissileParts(aName, tName, 1);
                                        }

                                        // Part damage scoring
                                        var tData = BDACompetitionMode.Instance.Scores[tName];
                                        if (tData.damageFromMissiles.ContainsKey(aName))
                                        {
                                            tData.damageFromMissiles[aName] += blastDamage;
                                        }
                                        else
                                        {
                                            tData.damageFromMissiles.Add(aName, blastDamage);
                                        }
                                        if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                        {
                                            BDAScoreService.Instance.TrackMissileDamage(aName, tName, blastDamage);
                                        }
                                        if (BDArmorySettings.DRAW_DEBUG_LABELS)
                                        {
                                            Debug.Log("[BDArmory.NukeTest]: " + aName + " did " + blastDamage + " blast damage to " + tName + " at " + distToG0.ToString("0.000") + "m");
                                        }
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        DestructibleBuilding building = blastHits.Current.GetComponentInParent <DestructibleBuilding>();

                        if (building != null)
                        {
                            var distToEpicenter = Mathf.Max((part.transform.position - building.transform.position).magnitude, 1f);
                            var blastImpulse    = Mathf.Pow(3.01f * 1100f / distToEpicenter, 1.25f) * 6.894f * lastValidAtmDensity * yieldCubeRoot;
                            // blastImpulse = (((((Math.Pow((Math.Pow((Math.Pow((9.54 * Math.Pow(10.0, -3.0) * (2200.0 / distToEpicenter)), 1.95)), 4.0) + Math.Pow((Math.Pow((3.01 * (1100.0 / distToEpicenter)), 1.25)), 4.0)), 0.25)) * 6.894) * (vessel.atmDensity)) * Math.Pow(yield, (1.0 / 3.0))));
                            if (!double.IsNaN(blastImpulse) && blastImpulse > 140) //140kPa, level at which reinforced concrete structures are destroyed
                            {
                                building.Demolish();
                            }
                        }
                    }
                }
            }
            if (vesselsHitByMissiles.Count > 0)
            {
                string message = "";
                foreach (var vesselName in vesselsHitByMissiles.Keys)
                {
                    message += (message == "" ? "" : " and ") + vesselName + " had " + vesselsHitByMissiles[vesselName];
                }
                message += " parts damaged (Blast Wave) by " + Sourcevessel + "'s exploding engine core.";
                BDACompetitionMode.Instance.competitionStatus.Add(message);
                Debug.Log("[BDArmory.NukeTest]: " + message);
            }
            ExplosionFx.CreateExplosion(part.transform.position, 1, explModelPath, explSoundPath, ExplosionSourceType.Missile, 0, null, Sourcevessel, "Reactor Containment Failure");
            hasDetonated = true;
            if (part.vessel != null) // Already in the process of being destroyed.
            {
                part.Destroy();
            }
        }
Example #3
0
        private void ExecutePartBlastEvent(PartBlastHitEvent eventToExecute)
        {
            if (eventToExecute.Part == null || eventToExecute.Part.Rigidbody == null || eventToExecute.Part.vessel == null || eventToExecute.Part.partInfo == null)
            {
                return;
            }

            Part      part         = eventToExecute.Part;
            Rigidbody rb           = part.Rigidbody;
            var       realDistance = eventToExecute.Distance;

            if (!eventToExecute.IsNegativePressure)
            {
                BlastInfo blastInfo =
                    BlastPhysicsUtils.CalculatePartBlastEffects(part, realDistance,
                                                                part.vessel.totalMass * 1000f, Power, Range);

                // Overly simplistic approach: simply reduce damage by amount of HP/2 and Armour in the way. (HP/2 to simulate weak parts not fully blocking damage.) Does not account for armour reduction or angle of incidence of intermediate parts.
                // A better approach would be to properly calculate the damage and pressure in CalculatePartBlastEffects due to the series of parts in the way.
                var damageWithoutIntermediateParts      = blastInfo.Damage;
                var cumulativeHPOfIntermediateParts     = eventToExecute.IntermediateParts.Select(p => p.Item2).Sum();
                var cumulativeArmourOfIntermediateParts = eventToExecute.IntermediateParts.Select(p => p.Item3).Sum();
                blastInfo.Damage = Mathf.Max(0f, blastInfo.Damage - 0.5f * cumulativeHPOfIntermediateParts - cumulativeArmourOfIntermediateParts);

                if (blastInfo.Damage > 0)
                {
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log(
                            "[BDArmory.ExplosionFX]: Executing blast event Part: {" + part.name + "}, " +
                            " VelocityChange: {" + blastInfo.VelocityChange + "}," +
                            " Distance: {" + realDistance + "}," +
                            " TotalPressure: {" + blastInfo.TotalPressure + "}," +
                            " Damage: {" + blastInfo.Damage + "} (reduced from " + damageWithoutIntermediateParts + " by " + eventToExecute.IntermediateParts.Count + " parts)," +
                            " EffectiveArea: {" + blastInfo.EffectivePartArea + "}," +
                            " Positive Phase duration: {" + blastInfo.PositivePhaseDuration + "}," +
                            " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                            " TimeIndex: {" + TimeIndex + "}," +
                            " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                            " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                    }

                    // Add Reverse Negative Event
                    ExplosionEvents.Enqueue(new PartBlastHitEvent()
                    {
                        Distance           = Range - realDistance,
                        Part               = part,
                        TimeToImpact       = 2 * (Range / ExplosionVelocity) + (Range - realDistance) / ExplosionVelocity,
                        IsNegativePressure = true,
                        NegativeForce      = blastInfo.VelocityChange * 0.25f
                    });

                    if (rb != null && rb.mass > 0)
                    {
                        AddForceAtPosition(rb,
                                           (eventToExecute.HitPoint + rb.velocity * TimeIndex - Position).normalized *
                                           blastInfo.VelocityChange *
                                           BDArmorySettings.EXP_IMP_MOD,
                                           eventToExecute.HitPoint + rb.velocity * TimeIndex);
                    }

                    var damage = part.AddExplosiveDamage(blastInfo.Damage, Caliber, ExplosionSource);
                    if (BDArmorySettings.BATTLEDAMAGE)
                    {
                        Misc.BattleDamageHandler.CheckDamageFX(part, 50, 0.5f, true, SourceVesselName, eventToExecute.Hit);
                    }

                    // Update scoring structures
                    switch (ExplosionSource)
                    {
                    case ExplosionSourceType.Bullet:
                    case ExplosionSourceType.Missile:
                        var aName = eventToExecute.SourceVesselName; // Attacker
                        var tName = part.vessel.GetName();           // Target
                        if (aName != tName && BDACompetitionMode.Instance.Scores.ContainsKey(tName) && BDACompetitionMode.Instance.Scores.ContainsKey(aName))
                        {
                            var tData = BDACompetitionMode.Instance.Scores[tName];
                            // Track damage
                            switch (ExplosionSource)
                            {
                            case ExplosionSourceType.Bullet:
                                if (tData.damageFromBullets.ContainsKey(aName))
                                {
                                    tData.damageFromBullets[aName] += damage;
                                }
                                else
                                {
                                    tData.damageFromBullets.Add(aName, damage);
                                }
                                if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                {
                                    BDAScoreService.Instance.TrackDamage(aName, tName, damage);
                                }
                                break;

                            case ExplosionSourceType.Missile:
                                if (tData.damageFromMissiles.ContainsKey(aName))
                                {
                                    tData.damageFromMissiles[aName] += damage;
                                }
                                else
                                {
                                    tData.damageFromMissiles.Add(aName, damage);
                                }
                                if (BDArmorySettings.REMOTE_LOGGING_ENABLED)
                                {
                                    BDAScoreService.Instance.TrackMissileDamage(aName, tName, damage);
                                }
                                break;

                            default:
                                break;
                            }
                        }
                        break;

                    default:
                        break;
                    }
                }
                else if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log("[BDArmory.ExplosiveFX]: Part " + part.name + " at distance " + realDistance + "m took no damage due to parts with " + cumulativeHPOfIntermediateParts + "HP and " + cumulativeArmourOfIntermediateParts + " Armour in the way.");
                }
            }
            else
            {
                if (BDArmorySettings.DRAW_DEBUG_LABELS)
                {
                    Debug.Log(
                        "[BDArmory.ExplosionFX]: Executing blast event Part: {" + part.name + "}, " +
                        " VelocityChange: {" + eventToExecute.NegativeForce + "}," +
                        " Distance: {" + realDistance + "}," +
                        " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                        " TimeIndex: {" + TimeIndex + "}," +
                        " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                        " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                }
                if (rb != null && rb.mass > 0)
                {
                    AddForceAtPosition(rb, (Position - part.transform.position).normalized * eventToExecute.NegativeForce * BDArmorySettings.EXP_IMP_MOD * 0.25f, part.transform.position);
                }
            }
        }
Example #4
0
        private void ExecutePartBlastEvent(PartBlastHitEvent eventToExecute)
        {
            if (eventToExecute.Part == null || eventToExecute.Part.Rigidbody == null || eventToExecute.Part.vessel == null || eventToExecute.Part.partInfo == null)
            {
                return;
            }

            try
            {
                Part      part         = eventToExecute.Part;
                Rigidbody rb           = part.Rigidbody;
                var       realDistance = eventToExecute.Distance;


                if (!eventToExecute.IsNegativePressure)
                {
                    BlastInfo blastInfo =
                        BlastPhysicsUtils.CalculatePartBlastEffects(part, realDistance,
                                                                    part.vessel.totalMass * 1000f, Power, Range);

                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log(
                            "[BDArmory]: Executing blast event Part: {" + part.name + "}, " +
                            " VelocityChange: {" + blastInfo.VelocityChange + "}," +
                            " Distance: {" + realDistance + "}," +
                            " TotalPressure: {" + blastInfo.TotalPressure + "}," +
                            " Damage: {" + blastInfo.Damage + "}," +
                            " EffectiveArea: {" + blastInfo.EffectivePartArea + "}," +
                            " Positive Phase duration: {" + blastInfo.PositivePhaseDuration + "}," +
                            " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                            " TimeIndex: {" + TimeIndex + "}," +
                            " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                            " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                    }

                    // Add Reverse Negative Event
                    ExplosionEvents.Enqueue(new PartBlastHitEvent()
                    {
                        Distance           = Range - realDistance,
                        Part               = part,
                        TimeToImpact       = 2 * (Range / ExplosionVelocity) + (Range - realDistance) / ExplosionVelocity,
                        IsNegativePressure = true,
                        NegativeForce      = blastInfo.VelocityChange * 0.25f
                    });

                    AddForceAtPosition(rb,
                                       (eventToExecute.HitPoint + part.rb.velocity * TimeIndex - Position).normalized *
                                       blastInfo.VelocityChange *
                                       BDArmorySettings.EXP_IMP_MOD,
                                       eventToExecute.HitPoint + part.rb.velocity * TimeIndex);

                    part.AddExplosiveDamage(blastInfo.Damage,
                                            Caliber, IsMissile);
                }
                else
                {
                    if (BDArmorySettings.DRAW_DEBUG_LABELS)
                    {
                        Debug.Log(
                            "[BDArmory]: Executing blast event Part: {" + part.name + "}, " +
                            " VelocityChange: {" + eventToExecute.NegativeForce + "}," +
                            " Distance: {" + realDistance + "}," +
                            " Vessel mass: {" + Math.Round(part.vessel.totalMass * 1000f) + "}," +
                            " TimeIndex: {" + TimeIndex + "}," +
                            " TimePlanned: {" + eventToExecute.TimeToImpact + "}," +
                            " NegativePressure: {" + eventToExecute.IsNegativePressure + "}");
                    }
                    AddForceAtPosition(rb, (Position - part.transform.position).normalized * eventToExecute.NegativeForce * BDArmorySettings.EXP_IMP_MOD * 0.25f, part.transform.position);
                }
            }
            catch
            {
                // ignored due to depending on previous event an object could be disposed
            }
        }