Beispiel #1
0
        private void CalculateBlast()
        {
            if (part.Resources.Contains("HighExplosive"))
            {
                if (part.Resources["HighExplosive"].amount == previousMass)
                {
                    return;
                }

                tntMass = (float)(part.Resources["HighExplosive"].amount * part.Resources["HighExplosive"].info.density * 1000) * 1.5f;
                part.explosionPotential = tntMass / 10f;
                previousMass            = part.Resources["HighExplosive"].amount;
            }

            blastRadius = BlastPhysicsUtils.CalculateBlastRange(tntMass);
        }
Beispiel #2
0
        public static void CreateExplosion(Vector3 position, float tntMassEquivalent, string explModelPath, string soundPath, ExplosionSourceType explosionSourceType, float caliber = 0, Part explosivePart = null, string sourceVesselName = null, string sourceWeaponName = null, Vector3 direction = default(Vector3), bool isfx = false)
        {
            CreateObjectPool(explModelPath, soundPath);

            Quaternion rotation;

            if (direction == default(Vector3))
            {
                rotation = Quaternion.LookRotation(VectorUtils.GetUpDirection(position));
            }
            else
            {
                rotation = Quaternion.LookRotation(direction);
            }

            GameObject newExplosion = explosionFXPools[explModelPath + soundPath].GetPooledObject();

            newExplosion.transform.SetPositionAndRotation(position, rotation);
            ExplosionFx eFx = newExplosion.GetComponent <ExplosionFx>();

            eFx.Range            = BlastPhysicsUtils.CalculateBlastRange(tntMassEquivalent);
            eFx.Position         = position;
            eFx.Power            = tntMassEquivalent;
            eFx.ExplosionSource  = explosionSourceType;
            eFx.SourceVesselName = sourceVesselName != null ? sourceVesselName : explosionSourceType == ExplosionSourceType.Missile ? (explosivePart != null && explosivePart.vessel != null ? explosivePart.vessel.GetName() : null) : null; // Use the sourceVesselName if specified, otherwise get the sourceVesselName from the missile if it is one.
            eFx.SourceWeaponName = sourceWeaponName;
            eFx.Caliber          = caliber;
            eFx.ExplosivePart    = explosivePart;
            eFx.Direction        = direction;
            eFx.isFX             = isfx;
            eFx.pEmitters        = newExplosion.GetComponentsInChildren <KSPParticleEmitter>();
            eFx.audioSource      = newExplosion.GetComponent <AudioSource>();
            if (tntMassEquivalent <= 5)
            {
                eFx.audioSource.minDistance = 4f;
                eFx.audioSource.maxDistance = 3000;
                eFx.audioSource.priority    = 9999;
            }
            newExplosion.SetActive(true);
        }
 private void CalculateBlast()
 {
     foreach (PartResource resource in GetResources())
     {
         var resources = part.Resources.ToList();
         using (IEnumerator <PartResource> ammo = resources.GetEnumerator())
             while (ammo.MoveNext())
             {
                 if (ammo.Current == null)
                 {
                     continue;
                 }
                 if (ammo.Current.resourceName == resource.resourceName)
                 {
                     ammoMass            = ammo.Current.info.density;
                     ammoQuantity        = ammo.Current.amount;
                     ammoExplosionYield += (((ammoMass * 1000) * ammoQuantity) / 6);
                 }
             }
     }
     blastRadius = BlastPhysicsUtils.CalculateBlastRange(ammoExplosionYield);
 }
Beispiel #4
0
        void Detonate()
        {
            if (!parentPart.partName.Contains("exploding"))
            {
                bool excessFuel = false;
                parentPart.partName += "exploding";
                PartResource fuel = parentPart.Resources.Where(pr => pr.resourceName == "LiquidFuel").FirstOrDefault();
                PartResource ox   = parentPart.Resources.Where(pr => pr.resourceName == "Oxidizer").FirstOrDefault();
                if (fuel != null)
                {
                    tntMassEquivilent += Mathf.Clamp((float)fuel.amount, ((float)fuel.maxAmount * 0.05f), ((float)fuel.maxAmount * 0.2f));
                    if (fuel != null && ox != null)
                    {
                        tntMassEquivilent += Mathf.Clamp((float)ox.amount, ((float)ox.maxAmount * 0.1f), ((float)ox.maxAmount * 0.3f));
                        tntMassEquivilent *= 1.3f;
                    }
                    if (fuel.amount > fuel.maxAmount * 0.3f)
                    {
                        excessFuel = true;
                    }
                }
                PartResource mp = parentPart.Resources.Where(pr => pr.resourceName == "MonoPropellant").FirstOrDefault();
                if (mp != null)
                {
                    tntMassEquivilent += Mathf.Clamp((float)mp.amount, ((float)mp.maxAmount * 0.1f), ((float)mp.maxAmount * 0.3f));
                    if (mp.amount > mp.maxAmount * 0.3f)
                    {
                        excessFuel = true;
                    }
                }
                PartResource ec = parentPart.Resources.Where(pr => pr.resourceName == "ElectricCharge").FirstOrDefault();
                if (ec != null)
                {
                    tntMassEquivilent += ((float)ec.maxAmount / 5000); //fix for cockpit batteries weighing a tonne+
                    ec.maxAmount       = 0;
                    ec.isVisible       = false;
                    parentPart.RemoveResource(ec);//destroy battery. not calling part.destroy, since some batteries in cockpits.
                    Misc.Misc.RefreshAssociatedWindows(parentPart);
                }
                if (excessFuel)
                {
                    float blastRadius = BlastPhysicsUtils.CalculateBlastRange(tntMassEquivilent);
                    using (var blastHits = Physics.OverlapSphere(parentPart.transform.position, blastRadius, 9076737).AsEnumerable().GetEnumerator())
                    {
                        while (blastHits.MoveNext())
                        {
                            if (blastHits.Current == null)
                            {
                                continue;
                            }
                            try
                            {
                                Part partHit = blastHits.Current.GetComponentInParent <Part>();
                                if (partHit != null && partHit.mass > 0)
                                {
                                    Rigidbody rb       = partHit.Rigidbody;
                                    Vector3   distToG0 = parentPart.transform.position - partHit.transform.position;

                                    Ray        LoSRay = new Ray(parentPart.transform.position, partHit.transform.position - parentPart.transform.position);
                                    RaycastHit hit;
                                    if (Physics.Raycast(LoSRay, out hit, distToG0.magnitude, 9076737))
                                    {
                                        KerbalEVA eva = hit.collider.gameObject.GetComponentUpwards <KerbalEVA>();
                                        Part      p   = eva ? eva.part : hit.collider.gameObject.GetComponentInParent <Part>();
                                        if (p == partHit)
                                        {
                                            if (rb == null)
                                            {
                                                return;
                                            }
                                            BulletHitFX.AttachFire(hit, p, 1, SourceVessel, 20);
                                        }
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                Debug.LogWarning("[BDArmory.FireFX]: Exception thrown in Detonate: " + e.Message + "\n" + e.StackTrace);
                            }
                        }
                    }
                }
                ExplosionFx.CreateExplosion(parentPart.transform.position, tntMassEquivilent, explModelPath, explSoundPath, ExplosionSourceType.Bullet, 0, null, parentPart.vessel != null ? parentPart.vessel.name : null, null);
                // needs to be Explosiontype Bullet since missile only returns Module MissileLauncher
                gameObject.SetActive(false);
            }
        }
Beispiel #5
0
        public void Start()
        {
            // extension for feature_engagementenvelope
            InitializeEngagementRange(0, maxTargetingRange);

            SetupAudio();

            if (HighLogic.LoadedSceneIsFlight)
            {
                part.force_activate();

                aimerTexture = BDArmorySetup.Instance.greenPointCircleTexture;
                // GameDatabase.Instance.GetTexture("BDArmory/Textures/grayCircle", false);

                MakeRocketArray();
                UpdateRocketScales();

                if (shortName == string.Empty)
                {
                    shortName = part.partInfo.title;
                }

                UpdateAudio();
                BDArmorySetup.OnVolumeChange += UpdateAudio;

                gauge             = (BDStagingAreaGauge)part.AddModule("BDStagingAreaGauge");
                gauge.AmmoName    = rocketType;
                gauge.AudioSource = sfAudioSource;
            }

            if (HighLogic.LoadedSceneIsFlight || HighLogic.LoadedSceneIsEditor)
            {
                List <ModuleTurret> .Enumerator turr = part.FindModulesImplementing <ModuleTurret>().GetEnumerator();
                while (turr.MoveNext())
                {
                    if (turr.Current == null)
                    {
                        continue;
                    }
                    if (turr.Current.turretID != turretID)
                    {
                        continue;
                    }
                    turret             = turr.Current;
                    targetInTurretView = false;
                    break;
                }
                turr.Dispose();

                if (turret)
                {
                    Events["GuiFire"].guiActive  = false;
                    Events["Jettison"].guiActive = false;
                    Actions["AGFire"].active     = false;

                    if (HighLogic.LoadedSceneIsFlight)
                    {
                        Events["ToggleTurret"].guiActive = true;
                    }
                }

                if (!string.IsNullOrEmpty(deployAnimationName))
                {
                    deployAnimState    = Misc.Misc.SetUpSingleAnimation(deployAnimationName, part);
                    hasDeployAnimation = true;

                    readyToFire = false;
                }
            }

            blastForce = BlastPhysicsUtils.CalculateExplosiveMass(blastRadius);
        }
Beispiel #6
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
            }
        }
Beispiel #7
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);
                }
            }
        }
Beispiel #8
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
            }
        }